Skip to content

ci: publish the evidence a borrowed-device session hands off - #1079

Merged
mikepitre merged 5 commits into
mainfrom
mike/verify-attach-android
Oct 13, 2026
Merged

mikepitre merged 5 commits into
mainfrom
mike/verify-attach-android

Conversation

@mikepitre

@mikepitre mikepitre commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

What & why

A cloud agent cannot put a run's video and screenshots on its pull request. Its sandbox refuses the upload, and the Actions token cannot attach files. So attach in #1069 hands the files to the session's runner, which keeps them as the artifact verify-evidence. This PR adds the workflow that reads that artifact and puts the evidence in the pull request description, with a bot token.

It is the fifth PR of the stack and sits on #1069, which sits on #1052, #1046, and #1041. GitHub starts the workflow only from the copy on main. So it does nothing until this PR has merged, which is after the rest of the stack.

One commit.

File Lines added What it does
.github/workflows/verify-attach.yml 84 Runs on workflow_run when a verify-remote session ends, from the default branch.
.github/scripts/verify-attach.mjs 813 Downloads the artifact, validates it, and edits one block of the description with gh pr edit --attach.
.github/scripts/verify-attach.test.mjs 1,459 143 tests of the script and of the workflow file.
.github/workflows/android-test.yml 6 Runs those tests in the e2e-runner-tests job.

The script is the same file, byte for byte, in clerk/clerk-ios and clerk/javascript. Review it once.

  • The artifact was written by branch code, so the job treats it as data. It never checks out, installs, or runs anything from the branch or from the artifact. The script reads the zip itself and refuses anything outside a fixed manifest, file names, sizes, counts, and leading bytes.
  • It publishes only to the open pull request of the session's branch, in this repository, and only when the commit the session started on and the commit the run was made at are both commits of that pull request. GitHub lists only the first 250 commits of a pull request, and when a longer one has either commit past them the workflow says so and publishes nothing.
  • The line it writes says that the session reported the result, links the session's run, and names the commit and the account that started the session, as GitHub records it. When the pull request has newer commits, the line says so. A later run and attach replaces the block.
  • The block sits between the comments <!-- verify-evidence:android --> and <!-- /verify-evidence:android -->. Everything outside it is kept as it was, with the line endings the description has. The workflow refuses a description that has neither comment and ends inside a code fence that never closes.
  • The runs for one branch take turns, and queue: max keeps every run that waits.

The environment verify-evidence exists in this repository and allows only main. It holds the secret VERIFY_EVIDENCE_TOKEN, a fine-grained token of a machine account that is limited to this repository and has "Pull requests: read and write". There is no repository secret of that name, and there must not be one.

A repository secret can be read by a workflow that anyone with write access adds on any branch. A secret of an environment that allows only main cannot. Without the secret the job prints a notice and publishes nothing.

What to focus on

  • The token. The workflow has actions: read and contents: read, and only the step that runs gh holds the token. Check that nothing from the artifact or the branch can reach that step.
  • The rule for which pull request gets the evidence, in pullRequestMismatch and commitNotListed.
  • The workflow starts after every verify-remote session, with or without evidence, and each start shows as a deployment to verify-evidence.

node --test .github/scripts/verify-attach.test.mjs passes 143 of 143. Every rule has a test with an input that is refused. actionlint reports one finding in the new workflow, the queue key, which the installed version does not know.

Not proven, and not provable before the stack is on main:

  • That a real session's end starts the workflow, and that the job gets the environment's secret.
  • That a fine-grained token with only "Pull requests: read and write" can attach files with gh pr edit --attach.
  • A real verify-evidence artifact. The script was run against zips made on a Mac.
  • That queue: max keeps every waiting run in this workflow.
  • A real hand-off from a cloud sandbox through the tunnel, which is feat(verify): borrow an emulator on a CI runner when the machine cannot run one #1069's part.

Screenshots / video

None. The change has no screen.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Verify-run evidence is validated and added to the relevant pull request, making results and supporting files easier to review.
    • When matching evidence is already present, the pull request can be updated with a note about newer commits.
  • Bug Fixes
    • Evidence is not published when the archive is malformed or inconsistent, or the pull request no longer matches the verify run.
    • Evidence handling is skipped when the required token is unavailable.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: clerk/clerk-android/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: f855a366-3f50-4191-9ee6-3a8bc29e21ab
📥 Commits

Reviewing files that changed from the base of the PR and between d3f42d0 and 83c76d6.

📒 Files selected for processing (2)
  • .github/scripts/verify-attach.test.mjs
  • .github/workflows/verify-attach.yml
💤 Files with no reviewable changes (2)
  • .github/workflows/verify-attach.yml
  • .github/scripts/verify-attach.test.mjs

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.

📝 Walkthrough

The pull request adds a script and workflow to fetch, validate, and publish evidence from eligible verify runs. It also adds tests for bundle validation, artifact fetching, publication behavior, and workflow configuration.

Changes: Verify evidence publication

Layer / File(s) Summary
Evidence bundle validation
.github/scripts/verify-attach.mjs, .github/scripts/verify-attach.test.mjs
The script validates ZIP structure, manifest fields, file names, sizes, checksums, and media signatures. Tests cover accepted bundles and rejection cases.
Artifact fetching and workflow setup
.github/scripts/verify-attach.mjs, .github/scripts/verify-attach.test.mjs, .github/workflows/verify-attach.yml, .github/workflows/android-test.yml
The fetch step selects an eligible artifact and writes validated files to a new or empty work directory. The workflow gates runs, supplies run metadata, and conditionally runs the script tests when watched paths change.
Pull request evidence publication
.github/scripts/verify-attach.mjs, .github/scripts/verify-attach.test.mjs, .github/workflows/verify-attach.yml
The publish step checks pull request and commit state, then adds or replaces evidence in the pull request description. It rechecks pull request state before editing. Tests cover evidence formatting, refusal paths, outputs, and workflow configuration.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant VerifyRun as verify-remote run
  participant Workflow as verify-attach workflow
  participant Script as verify-attach script
  participant ActionsAPI as GitHub Actions API
  participant GitHubCLI as GitHub CLI
  participant PullRequest as pull request
  VerifyRun-->>Workflow: Completed run metadata
  Workflow->>Script: Fetch evidence for the run
  Script->>ActionsAPI: List and download eligible artifact
  ActionsAPI-->>Script: Artifact ZIP
  Script->>Script: Validate bundle and write evidence files
  Workflow->>Script: Publish with run details and token
  Script->>GitHubCLI: Read pull request and commits
  GitHubCLI-->>Script: Pull request state and commit list
  Script->>GitHubCLI: Update pull request description
  GitHubCLI->>PullRequest: Save evidence block
Loading
Merge Risk: ⚪ Minimal · up to 83c76

No actionable issue was found that would block merging. The workflow still needs its normal first-run validation after it reaches the default branch.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly and concisely describes the main change: publishing evidence from a borrowed-device session.
Description check Passed The description includes all template sections and provides detailed context, implementation scope, review risks, testing results, known limitations, and screenshots information.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 2 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@mikepitre
mikepitre added this pull request to stack #1053 October 9, 2026 01:53
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 68e6c6a to bf1ffda Compare October 9, 2026 02:43
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from bf1ffda to 0a0e7e6 Compare October 9, 2026 03:58
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 0a0e7e6 to 47dfedb Compare October 9, 2026 05:23
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 47dfedb to 5347a9b Compare October 9, 2026 14:52
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 5347a9b to 6705c90 Compare October 9, 2026 19:17
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 6705c90 to 7387011 Compare October 12, 2026 17:58
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 7387011 to d291296 Compare October 12, 2026 19:10
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from d291296 to 5bd9f34 Compare October 12, 2026 20:18
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch 2 times, most recently from 5bd9f34 to 2ac5104 Compare October 13, 2026 15:32
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 2ac5104 to 9976318 Compare October 13, 2026 16:00
@mikepitre
mikepitre marked this pull request as ready for review October 13, 2026 16:05
@mikepitre
mikepitre requested a review from swolfand October 13, 2026 16:05
@swolfand

Copy link
Copy Markdown
Collaborator
  • verify-attach.yml:29 uses concurrency: queue: max. I couldn't confirm GitHub accepts a queue key, and no other workflow here or in clerk-ios/clerk/javascript uses it. If it's invalid, the workflow file is rejected and, since it only runs from main, nobody notices until after merge. Can you confirm with actionlint or a scratch repo?
  • verify-attach.mjs:701-732: a human edit to the PR description between the re-read and gh pr edit could be overwritten. Short window, low risk.
  • actions/checkout and setup-node are pinned to v4 (Node 20); other workflows use newer versions.
  • Nit: the comment at verify-attach.yml:77-78 describes our own step (AGENTS.md).

@swolfand

Copy link
Copy Markdown
Collaborator

Pushed fixes for the review findings above:

Left concurrency.queue: max as is. GitHub's workflow syntax docs list queue (single default, max up to 100 pending) for both workflow-level and jobs.<job_id>.concurrency. They say it can't be combined with cancel-in-progress: true, and this job uses false. actionlint 1.7.12 (latest) still reports unexpected key "queue", but that's a known gap: rhysd/actionlint#657 is open. The repo doesn't run actionlint in CI. The comment at ~:77-78 was already removed in your 453c64b.

Base automatically changed from mike/verify-borrowed-device-android to main October 13, 2026 22:26
A cloud agent cannot attach a run's video and screenshots to its pull
request: its sandbox refuses the upload, and the Actions token cannot
attach. `verify-attach.yml` does it instead. It runs on `workflow_run`
when a `verify-remote` session ends, so GitHub always runs the copy on
the default branch.

The job downloads the session's `verify-evidence` artifact and treats
it as data. `.github/scripts/verify-attach.mjs` reads the zip itself,
refuses anything outside a fixed manifest schema, file names, sizes,
counts, and leading bytes, and writes only files it validated. It then
edits one marked block in the description with `gh pr edit --attach`.
The line it writes says that the session reported the result and links
the session's run.

It publishes only to the open pull request of the session's branch, in
this repository, and only when the commit the session started on and
the commit the run was made at are both commits of that pull request.
When the pull request has moved on, the line says so.

The bot token is the secret `VERIFY_EVIDENCE_TOKEN` of the environment
`verify-evidence`, which allows only the default branch. A repository
secret could be read by a workflow on any branch. Only the step that
runs `gh` holds the token. Without the secret the job prints a notice.
GitHub starts this workflow only when it and `verify-remote.yml` are
both on the default branch.

The runs for one branch take turns at the description, and
`queue: max` keeps every run that waits.

The `e2e-runner-tests` job of `android-test.yml` runs the script's
tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mikepitre and others added 4 commits October 13, 2026 18:26
The header of verify-attach.yml restated what the script's tests already
pin: the token's environment, the permissions and the conditions of the
job. The comment in the script's tests described a helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t v7

This job is the only one that holds the evidence token, so its actions
are pinned by commit. checkout is v7.0.1 and setup-node is v7.1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mikepitre
mikepitre force-pushed the mike/verify-attach-android branch from 9de688b to 3de9643 Compare October 13, 2026 22:26
@mikepitre
mikepitre merged commit 1aba14e into main Oct 13, 2026
14 checks passed
@mikepitre
mikepitre deleted the mike/verify-attach-android branch October 13, 2026 22:43
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.

2 participants