diff --git a/.github/workflows/fork-ci.yml b/.github/workflows/fork-ci.yml index 3f203892342..2e50722418f 100644 --- a/.github/workflows/fork-ci.yml +++ b/.github/workflows/fork-ci.yml @@ -36,15 +36,28 @@ on: - fork/tim - fork/candidates - fork/changes + # Stable contributor and release branch (docs/stable-dev-release-branch-handover.md). + - fork/dev # Registered integration overlays (same names as .github/pr-stack.json) - t3-discord/f7d37879-desktop-deeplinks - fork/discord - fork/vscode - fork/identity + # fork/dev is never rebased, so its merge commits are the release candidates. + # Deployment promotes an exact green SHA and keys on a successful run of this + # workflow for that SHA, so every merge must produce one — a green PR tip is + # not enough when the merge SHA differs. + push: + branches: + - fork/dev concurrency: - group: ci-${{ github.event.pull_request.number || inputs.checkout_ref || github.ref }} - cancel-in-progress: true + # Push runs are keyed by SHA and never cancelled: the conclusion of a push run + # is what approves that exact commit for deployment, so cancelling one as + # superseded would leave that merge SHA permanently unapprovable. + group: ci-${{ github.event.pull_request.number || inputs.checkout_ref || + (github.event_name == 'push' && github.sha) || github.ref }} + cancel-in-progress: ${{ github.event_name != 'push' }} jobs: check: @@ -181,7 +194,12 @@ jobs: deployment_scope: name: Classify Deployment Scope - if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/fork/integration' + # Two release tips during the cutover: the composed fork/integration tip + # (dispatched by the stack workflow) and fork/dev merge commits. Keep both + # until fork/integration is retired. + if: >- + (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/fork/integration') || + (github.event_name == 'push' && github.ref == 'refs/heads/fork/dev') runs-on: ubuntu-24.04 timeout-minutes: 5 permissions: @@ -200,16 +218,22 @@ jobs: with: fetch-depth: 0 - - name: Find previous successful integration CI + - name: Find previous successful release-tip CI id: previous env: GH_TOKEN: ${{ github.token }} + # Compare against this branch's own history. Hardcoding + # fork/integration + workflow_dispatch here would make every fork/dev + # push diff against an unrelated tip and classify every component as + # changed. + SCOPE_BRANCH: ${{ github.ref_name }} + SCOPE_EVENT: ${{ github.event_name }} run: | previous_sha="$( gh api --method GET \ "repos/${GITHUB_REPOSITORY}/actions/workflows/fork-ci.yml/runs" \ - -f branch=fork/integration \ - -f event=workflow_dispatch \ + -f "branch=${SCOPE_BRANCH}" \ + -f "event=${SCOPE_EVENT}" \ -f status=success \ -f per_page=20 \ --jq ".workflow_runs | map(select(.head_sha != \"${GITHUB_SHA}\")) | first | .head_sha // \"\"" @@ -258,9 +282,9 @@ jobs: dispatch_mobile_releases: name: Dispatch Mobile Releases needs: [check, test, mobile_native_static_analysis, release_smoke, deployment_scope] - if: | - github.event_name == 'workflow_dispatch' && - github.ref == 'refs/heads/fork/integration' && + if: >- + ((github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/fork/integration') || + (github.event_name == 'push' && github.ref == 'refs/heads/fork/dev')) && needs.deployment_scope.outputs.mobile == 'true' runs-on: ubuntu-24.04 timeout-minutes: 5 @@ -268,22 +292,25 @@ jobs: actions: write contents: read steps: - - name: Dispatch exact integration SHA + - name: Dispatch exact release SHA env: GH_TOKEN: ${{ github.token }} + # Dispatch against the branch this run is validating so the mobile + # workflows come from the same tip, not a stale fork/integration copy. + RELEASE_REF: ${{ github.ref_name }} run: | # mode=auto, not update: an OTA alone never reaches a phone when the # native runtime changed, so the fingerprint decides between an update # and a TestFlight build. iOS only, because Android has no keystore. gh workflow run mobile-eas-production.yml \ --repo "$GITHUB_REPOSITORY" \ - --ref fork/integration \ + --ref "$RELEASE_REF" \ -f mode=auto \ -f platform=ios \ -f sha="$GITHUB_SHA" \ - -f message="Integration ${GITHUB_SHA}" + -f message="${RELEASE_REF} ${GITHUB_SHA}" gh workflow run mobile-eas-development.yml \ --repo "$GITHUB_REPOSITORY" \ - --ref fork/integration \ + --ref "$RELEASE_REF" \ -f platform=ios \ -f sha="$GITHUB_SHA"