Skip to content

ci(drift): open the PR as a GitHub App so its checks actually run - #38

Merged
cubehouse merged 1 commit into
mainfrom
ci/drift-app-token
Sep 8, 2026
Merged

cubehouse merged 1 commit into
mainfrom
ci/drift-app-token

Conversation

@cubehouse

@cubehouse cubehouse commented Sep 8, 2026 •

Copy link
Copy Markdown
Member

The drift job opened its PR with GITHUB_TOKEN. GitHub does not start workflow runs from GITHUB_TOKEN-raised events, so the required checks never reported and the PR was blocked on a report it could not receive. #34 has sat that way since 2026-09-02, its body cheerfully reporting build: success the whole time.

Now the job mints a short-lived installation token from the tpw-drift GitHub App and hands it to create-pull-request. The push comes from the app's identity, pull_request fires normally, CI reports.

- name: Mint an installation token for the drift bot
  id: app-token
  uses: actions/create-github-app-token@v2
  with:
    app-id: ${{ secrets.DRIFT_APP_ID }}
    private-key: ${{ secrets.DRIFT_APP_PRIVATE_KEY }}

- name: Open PR if schema changed
  uses: peter-evans/create-pull-request@v8
  with:
    token: ${{ steps.app-token.outputs.token }}   # the only functional change

The app holds contents:write, pull_requests:write, metadata:read on two repos and nothing else — notably not workflows:write, so it cannot alter CI. The token is minted per run and expires in an hour; the only stored credential is the app private key, revocable independently of any human account.

The create-an-issue steps keep GITHUB_TOKEN deliberately. They open issues on failure, an issue doesn't need to trigger anything, and there's no reason to widen the app's reach.

Why not workflow_dispatch

Tried first, rejected on evidence rather than taste. workflow_dispatch is documented as one of two exceptions to the no-runs rule, and the exception is real — the dispatch does start a run. It just doesn't satisfy branch protection.

Measured on a throwaway PR with push/pull_request stripped from its ci.yml, so the only checks it could get were ones I gave it:

event sha run outcome PR state
workflow_dispatch 8921fb59 success, 3 check runs named exactly Test (Node 20/22/24) on the PR head SHA BLOCKED, rollup empty
push a03bf181 success CLEAN

The dispatched run's checks were verifiably there:

GET /commits/8921fb59/check-runs    total_count=3, all completed/success
GET /commits/8921fb59/check-suites  app=github-actions, success, linkedPRs=1
GET /pulls/37                       mergeable=true, mergeable_state=blocked

Stable across six polls over two minutes, so not eventual consistency. Protection counts check runs by the event that produced their suite, not by SHA and name.

This PR also corrects the comment #36 left on ci.yml's workflow_dispatch trigger, which asserted the approach that turned out not to work. The trigger stays — re-running CI against a ref by hand is useful — but the claim goes.

Verifying it

The mechanism can't be proven by this PR's own CI, only by a drift run. After merge I'll trigger the job manually. Two plausible first-run failures worth naming up front: a malformed private key fails at create-github-app-token, and a repo missing from the app installation fails with "Resource not accessible by integration".

That run also regenerates against the corrected spec — ThemeParks/tpwserver#161 fixed the schedule and price schemas, which makes the currently-open #34 stale as well as unmergeable.

🤖 Generated with Claude Code

The drift job opened its PR with GITHUB_TOKEN. GitHub does not start workflow
runs from GITHUB_TOKEN-raised events, so the required Test (Node ...) checks
never reported and the PR was blocked on a report it could not receive. #34
has sat that way since 2026-09-02 while its body said 'build: success'.

Fixed by minting a short-lived installation token from the tpw-drift app and
handing it to create-pull-request. The push then comes from the app's identity
rather than GITHUB_TOKEN, pull_request fires normally, and CI reports. The app
holds contents:write and pull_requests:write on two repos and nothing else —
notably not workflows:write, so it cannot alter CI.

The create-an-issue steps keep GITHUB_TOKEN deliberately. They open issues on
failure, an issue does not need to trigger anything, and there is no reason to
widen the app's reach.

Also corrects the comment left on ci.yml's workflow_dispatch trigger by the
previous attempt. workflow_dispatch is genuinely a documented exception to the
no-runs rule, and it does start a run — but that run's check runs do not
satisfy branch protection. Measured, not assumed: on one PR, a dispatched run
put three successful check runs with the exact required names on the head SHA
and left it BLOCKED with an empty rollup for two minutes, while a push-event
run on the next commit cleared it at once. The trigger is kept because
re-running CI against a ref by hand is useful; the claim that it fixes drift
is removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cubehouse
cubehouse merged commit a9d121c into main Sep 8, 2026
3 checks passed
@cubehouse
cubehouse deleted the ci/drift-app-token branch September 8, 2026 13:15
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