Skip to content

ci: automate macOS TestFlight and App Store promotion - #261

Open
khaira777 wants to merge 1 commit into
feat/microsoft-store-publishingfrom
feat/macos-app-store-publishing
Open

ci: automate macOS TestFlight and App Store promotion#261
khaira777 wants to merge 1 commit into
feat/microsoft-store-publishingfrom
feat/macos-app-store-publishing

Conversation

@khaira777

Copy link
Copy Markdown
Contributor

Summary

  • Add a MAS-signed macOS TestFlight workflow for scheduled internal nightlies and reviewer-gated external beta candidates.
  • Use a unique CI build number and emit a promotion manifest so the exact processed TestFlight build can be promoted later.
  • Add a reviewer-gated production workflow that submits an already-processed build to Mac App Store review.
  • Support manual, automatic-after-review, and seven-day phased release modes.
  • Pin Ruby setup and Fastlane, use separate MAS signing/provisioning credentials from direct-distribution notarization credentials, and keep production submission separate from the nightly lane.
  • Prevent build:mas from implicitly publishing through electron-builder.

This PR is intentionally stacked on feat/microsoft-store-publishing and should be merged after PR #260, or retargeted to main once that PR lands.

Required setup

  • macos-testflight-nightly Environment: MAS signing/API secrets, no approval for scheduled nightlies.
  • macos-testflight-beta Environment: same secrets, required maintainer approval for manual beta runs.
  • production-release Environment: App Store Connect API secrets and required maintainers.
  • App Store Connect bundle ID com.flo.desktop, Mac App Distribution certificate, MAS provisioning profile, TestFlight groups, and prepared version metadata.

See the workflow comments and fastlane/Fastfile for the lane behavior. The first production mode should be manual; switch to automatic or phased only after a successful review cycle.

Verification

  • npm run test:release-config
  • YAML parsing for all release workflows
  • git diff --check

Apple signing, TestFlight processing, and App Store review require the maintainer's Apple/GitHub credentials and cannot be validated locally.

@khaira777
khaira777 requested a review from itsbkm as a code owner August 11, 2026 22:01
@khaira777

Copy link
Copy Markdown
Contributor Author

@itsbkm — macOS App Store/TestFlight setup requested before merging PR #261

This PR is stacked on PR #260. Please merge #260 first, then retarget #261 to main if GitHub does not do that automatically.

Apple Developer / App Store Connect setup

  1. Confirm the existing App Store Connect app:

    • Mac App Store listing: https://apps.apple.com/in/app/flo-cafe/id6763136018
    • Bundle ID: com.flo.desktop
    • Team ID: BKDY677XJA
  2. In Apple Developer Certificates, Identifiers & Profiles:

    • Create/export a Mac App Distribution certificate as a .p12.
    • Create a Mac App Store distribution provisioning profile for com.flo.desktop.
    • Do not reuse the direct-distribution MAC_CERTS; that is the Developer ID certificate used for DMG/ZIP notarization.
    • The profile must be supplied to CI at build/flo.provisionprofile; it must never be committed.
  3. In App Store Connect, create a dedicated API key with App Manager-level access for the first implementation. The key must be allowed to upload builds, manage TestFlight information, and submit builds for review. Keep the .p8 private key; Apple only allows downloading it once.

  4. Create/confirm TestFlight groups:

    • Internal group for maintainers/staff.
    • External beta group for release candidates.
    • Complete the beta app description, feedback email, and external review information. Apple may review the first external build before distribution.
  5. Ensure the App Store Connect agreement/tax/banking status and the current app metadata are complete. For production, the target version must have release notes and review information prepared in App Store Connect. This PR deliberately does not overwrite production metadata from the repository.

GitHub Environments and values

Create these environments:

macos-testflight-nightly

Used only by the scheduled nightly workflow from main. Add:

Secrets

  • MAS_MAC_CERTS — base64 .p12 Mac App Distribution certificate
  • MAS_MAC_CERTS_PASSWORD
  • MAS_PROVISIONING_PROFILE — base64 provisioning profile
  • ASC_API_KEY_ID
  • ASC_API_ISSUER_ID
  • ASC_API_PRIVATE_KEY — base64 .p8 key

Variables

  • TESTFLIGHT_GROUP — internal group name, if required
  • TESTFLIGHT_CHANGELOG — optional nightly “what to test” text

Do not add required reviewers here, otherwise every scheduled nightly will pause.

macos-testflight-beta

Use the same secrets and variables as above, but add required maintainer reviewers. All manual TestFlight runs use this environment, including internal manual runs and external beta runs.

production-release

Add the App Store Connect API secrets above. This is the same protected environment used by PR #260 for Microsoft Store publishing. Keep required maintainer reviewers and self-approval disabled.

Add the optional environment variable:

MACOS_STORE_RELEASE_MODE=manual

Allowed values are:

  • manual — submit to Apple review, then release manually after approval; safest first mode.
  • automatic — Apple releases automatically after approval.
  • phased — Apple releases automatically using the seven-day phased rollout.

How the workflows work

Nightly/internal TestFlight

The scheduled macos-testflight.yml workflow:

  1. Checks out main.
  2. Builds the mas target, not the direct DMG/ZIP target.
  3. Sets a unique numeric CFBundleVersion from the GitHub run number.
  4. Verifies the MAS package signature, bundle ID, marketing version, and build number.
  5. Uploads the .pkg to TestFlight using Fastlane.
  6. Publishes a promotion manifest containing the exact version, build number, source ref, and commit SHA.

External beta

Run macos-testflight.yml manually from the workflow UI while selecting the workflow definition from main:

  • channel=external
  • source_ref=release/... or a strict X.Y.Z-rc.N tag

The workflow rejects arbitrary branch refs and waits for the protected macos-testflight-beta approval. The exact build number from the promotion manifest is the candidate to promote later.

Production App Store submission

Run macos-app-store-submit.yml manually from the workflow definition on main with:

version:      X.Y.Z
build_number: exact processed TestFlight build number
release_mode: manual   # first release

The workflow does not rebuild or checkout arbitrary release code. It uses Fastlane to select the already-processed App Store Connect build and submit that exact build for Mac App Store review. The production-release approval is required.

After Apple approves a manual release, release it from App Store Connect. Once the process is proven, use automatic or phased for later releases.

The Mac App Store is the production channel; it has no GitHub-style latest channel. TestFlight is separate, and direct GitHub DMG/ZIP users remain on the existing electron-updater channel.

First validation sequence

  1. Create the certificates, profile, API key, environments, groups, and metadata.
  2. Run an internal TestFlight build from main.
  3. Install it through TestFlight and test SQLite, printers, KDS, backups, and MAS sandbox behavior.
  4. Run an external RC build from a protected release branch/tag and complete Apple beta review if requested.
  5. Use the manifest’s exact build number in the production submission workflow with release_mode=manual.
  6. After approval, manually release the version and verify the public listing.
  7. Only then consider automatic or phased mode.

Fastlane is pinned to 2.237.0; Ruby setup is pinned in the workflow. Apple’s official references:

Anyone with repository Write access may be able to enqueue a manual workflow, but manual beta and production jobs cannot use their protected credentials or submit until a maintainer approves the environment. Release tag rulesets should separately restrict production tags to maintainers/owners.

@khaira777

Copy link
Copy Markdown
Contributor Author

@itsbkm Governance prerequisite: issue #204 now contains the complete main/tag ruleset checklist and the remaining follow-up release-gating work. Please apply those repository settings before treating these publishing PRs as production-ready: #204 (comment)

@khaira777

Copy link
Copy Markdown
Contributor Author

@itsbkm This PR is intentionally stacked: #261 targets feat/microsoft-store-publishing, while #260 targets main. Please merge #260 first. After #260 is merged, change #261 base to main using the PR Edit UI (or gh pr edit 261 --base main), then re-run checks and review/merge the Apple-only diff. Do not retarget it before #260 merges, or the Microsoft commits will appear duplicated in #261.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant