Add automated weekly TestFlight build via fastlane match #776
Merged
Conversation
Documents the approach for a scheduled GitHub Actions workflow that builds and uploads to TestFlight, using fastlane match (git storage + deploy key) for unattended code signing, plus the one-time setup and required secrets. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Adds a scheduled (weekly) + manually dispatchable GitHub Actions workflow that builds and uploads to TestFlight, plus a `beta_ci` fastlane lane and a Matchfile. Signing is handled by `fastlane match` (git storage repo accessed over an SSH deploy key); App Store Connect credentials, the match passphrase, and the BeeKit config are supplied via the `testflight` environment's secrets. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Removes the scratch planning doc, gitignores the new fastlane build log directory so local lane runs don't leave untracked output, and adds the beta_ci lane to the auto-generated fastlane README. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
…tion Adds a branch-scoped push trigger so the workflow can be validated before it lands on master. Must be removed before merging. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
The archive failed because BeeKit was still on automatic signing and tried to resolve an iOS Development certificate that doesn't exist on the runner. Sign it with the distribution identity (no provisioning profile needed for an embedded framework). https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Adds a cheap pre-check job that compares HEAD against the commit of the most recent builds/* tag and only runs the build/upload job when they differ. Avoids redundant weekly TestFlight builds (and spurious testflight environment approval prompts) when nothing has changed. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Replaces the builds/* creatordate scan with a dedicated ci-latest pointer that the build job force-updates after a successful upload. Simpler and unambiguous; the per-build builds/beta_ci/* tags are kept for history. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
The archive was hanging indefinitely on the signing step: without a CI keychain, codesign blocks on an interactive keychain-access prompt that can't be answered on a headless runner. setup_ci creates a temporary unlocked keychain and points match at it. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Pipeline validated end-to-end on the branch. The workflow now runs only on the weekly schedule and manual dispatch. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Adds a workflow-level default of contents: read so the check job and any future jobs get a minimal token; the build job keeps its explicit contents: write for the per-build and ci-latest tag pushes. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Security review C1: the build job holds the App Store signing chain, so pin every action to a full commit SHA (version in trailing comment) instead of a mutable tag. SHAs resolved from upstream tag refs. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
Replaces repeated team id, bundle id, and ASC key duration literals with TEAM_ID / APP_IDENTIFIER / ASC_KEY_DURATION constants across the beta and beta_ci lanes; the match profile env var is now derived from APP_IDENTIFIER. https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
The single entitlements file pinned aps-environment to development for all configurations. Under the new manual signing in beta_ci that risks either a profile/entitlement mismatch or, worse, TestFlight builds silently getting sandbox push tokens while the backend sends via production APNs. Add a Release-only entitlements file with aps-environment=production and point the Release build configuration at it; Debug is unchanged (development/sandbox). https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GitHub Actions workflow that builds the app and uploads it to TestFlight,
fully unattended.
beta_cifastlane lane: App Store Connect API key from env, buildnumber bumped to
latest_testflight_build_number + 1, distribution signingvia
fastlane match, archive, upload, and a build tag.Matchfilepointing at thebeeminder/BeeSwift-credentialsstoragerepo (git storage, accessed over an SSH deploy key). Local development keeps
Xcode automatic signing unchanged.
fastlane/build_outputlog dir; listbeta_ciin the auto-generated fastlane README.Required configuration (already set up out-of-band)
beeminder/BeeSwift-credentialsprivate repo seeded viafastlane match appstore.testflightGitHub Environment (restricted tomaster) with secrets:MATCH_PASSWORD,MATCH_SSH_KEY,ASC_KEY_ID,ASC_ISSUER_ID,ASC_KEY_P8_BASE64,CONFIG_SWIFT.match(readonly: false)self-heal path; first run only needs read).Test plan
testflightenvironment's allowedbranches, dispatch "Weekly TestFlight Build", confirm a build lands in
TestFlight.
framework target — only the BeeSwift app target is flipped to the match
profile; fix is one line if framework signing fails).
https://claude.ai/code/session_016a6ivCc3wjKG8osTb4h8Fx