Repository navigation
ci: dispatch external CI to the external repositories (led-blinker pilot) - #6328
Open
thomas-bc-autowot wants to merge 22 commits into
Open
thomas-bc-autowot wants to merge 22 commits into
thomas-bc-autowot wants to merge 22 commits into
Conversation
…rator) Adds ext-ci-trigger.yml (no-op pull_request gate), ext-ci.yml (workflow_run orchestrator: dispatch, poll, one Check Run per external repo, failed-only re-run, notify/block policy) and .github/ext-ci-manifest.json onboarding led-blinker, zephyr-reference and generic-hub-reference in the notify tier. Existing ext-*.yml workflows are untouched and keep running alongside.
…o dispatch errors are visible
Same behaviour and workflows; folds in review findings: no automatic retry of the non-idempotent dispatch call (a lost response falls back to dispatch_id correlation), a failed check-status update is not treated as a failed dispatch, and a check whose completion update failed is closed by the finalize step with the remote result.
…nifest source, compare 404, concurrency key) - correlate/poll_all tolerate carried-forward entries (no remote_* keys) on a re-run - a manual run with fprime_ref reads the manifest and ext ref from the branch the run was started from, not from the ref under test (any PR SHA is readable via /contents?ref=) - a release push whose before SHA was rewritten runs everything instead of aborting - concurrency group includes the event name so a PR branch named release/* cannot cancel the push run
Drop owner notifications (a notify repo is just a neutral check; no pull-requests/issues write needed any more), failed-only re-run carry-forward (a re-run re-dispatches every repo), the dispatch_id correlation fallback (the dispatch API returns the run id), manifest lookup from the base branch and ETag polling.
…nual runs, readability
…trator faults fail the job
…; notify repos never cancelled-red
thomas-bc
reviewed
Nov 5, 2026
This comment was marked as off-topic.
This comment was marked as off-topic.
thomas-bc
reviewed
Nov 5, 2026
… stay inside the 60-min job
… / Orchestrate", "External CI / <id>"
…ot match the orchestrator itself
…) instead of a PAT Check Runs created with GITHUB_TOKEN are filed into an arbitrary existing Actions check suite on the PR head, so the PR shows them as '<other workflow> / ext-ci / led-blinker'. Creating them with the External CI App's own installation token gives them their own suite. The same App's fprime-community installation replaces EXT_CI_DISPATCH_TOKEN; secrets are EXT_CI_APP_ID and EXT_CI_APP_PRIVATE_KEY. Falls back to GITHUB_TOKEN for the checks while the App is not installed on this repo.
This branch has not been deployed
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.
Change Description
Dispatch an external project's own
ci.ymland report the result on the F´ commit, instead of building the project inside nasa/fprime.ext-ci-trigger.yml: trivialpull_request/merge_groupworkflow withpermissions: {}, so GitHub's fork-approval gate applies before anything privileged runs.ext-ci.yml: runs onworkflow_runof the trigger, nightly, onrelease/**pushes and manual dispatch, always from the default branch (never PR code). One Check Run per external repo on the PR head SHA; dispatches the externalci.ymlwith{fprime_repository, fprime_ref, fprime_pr_number, dispatch_id}, polls, finalizes (closes open checks, cancels orphaned remote runs). A re-run re-dispatches every repo..github/actions/ext-ci/orchestrator.py(documented in.github/actions/ext-ci/README.md): standard-library-only Python script doing the above..github/actions/ext-ci/manifest.json: pilot withfprime-community/fprime-workshop-led-blinkeronly,failure_policy: notify(a failure shows as a neutral check and does not block).ext-build-led-blinker.ymlstays until the new check has run in parallel for a while.Credentials: one GitHub App ("External CI", registered under fprime-community: Actions rw, Checks rw, Contents ro, Pull requests ro, no webhook) installed on the external repos and on nasa/fprime; repository secrets
EXT_CI_APP_ID+EXT_CI_APP_PRIVATE_KEY. The workflow mints two 1-hour installation tokens: one scoped to the external repos (dispatch/cancel), one to nasa/fprime (Check Runs, so they get their own "External CI" group in the PR checks list instead of being filed under another workflow, which is whatGITHUB_TOKEN-created checks get). Until the nasa/fprime installation is approved the checks fall back toGITHUB_TOKEN. Dispatched runs havecontents: read, no secrets, ccache off; the action-side pip-cache save is closed by nasa/fprime-actionscache-mode: read(separate PR) — see finding 1 below for what that does not cover.Operation:
pr-<N>branch when it exists, else its default branch (shown in the check title, e.g.success (… @ devel)); the externalci.ymlchecks itself out from that ref and builds against the F´ revision it is given.<App name> / External CI / led-blinkerand the merge box the App avatar +External CI / led-blinker; branch protection matches on the check name.Rationale
Each
ext-*.ymlre-implements an external build on nasa/fprime runners and every external breakage is fixed in many workflows; this leaves nasa/fprime with dispatch/poll/report and one manifest entry per project.Testing/Review Recommendations
Design, evidence and security review: https://github.com/JPL-Devin/fprime-test-ci-fprime/blob/main/docs/ext-ci-dispatch-plan.md. Review focus:
ext-ci.ymlholds the write permissions and the secret but checks out only the default branch; nopull_request_target. Proven end to end from the JPL-Devin fork: orchestrator run https://github.com/JPL-Devin/fprime/actions/runs/41948640203 dispatched https://github.com/fprime-community/fprime-workshop-led-blinker/actions/runs/41948655128 and closed theExternal CI / led-blinkercheck with its result. After merge: a PR touching a non-ignored path should get that check.Review findings and resolutions (multi-agent review at 6052882)
Full summary review: JPL-Devin#297 (review) (8 lenses, 2 routed out as not applicable; CI safety No-Go / merge readiness No-Go as posted, with the dispositions below).
Boundary verified clean by every lens that traced it: the orchestrator never runs PR code; none of the tokens (
GITHUB_TOKEN, App installation tokens) is reachable from the PR; manifest and script are read from the default/release branch; only GitHub-authoredworkflow_runpayload fields are trusted; PR resolution is filtered onbase.repo; nopull_request_target; Check Runs can only be written by the orchestrator; concurrency keys are owner-qualified;finalizecloses checks and cancels remote runs under cancellation; the dispatched led-blinker workflow hascontents: readand no secrets. The context this review assumed: nasa/fprime requires approval for workflow runs from all outside collaborators, and the external repositories hold no secrets.ccache: false/cache-mode: read, which only stop the action's own saves. (JPL-Devin#297 (comment))design-needs-human-adjudication: a new privileged mechanism (long-lived PAT in a repository secret, external dispatch). (JPL-Devin#297 (comment))failure_policy: notifyalso silences orchestrator-side faults and nightly/release runs: the job exits 0, nobody is alerted. (JPL-Devin#297 (comment))notifyonly softens the PR check; dispatch/poll errors and non-PR runs (nightly, release, merge queue) fail the job.dispatch_failedwhile the remote run proceeds untracked (not polled, not cancelled). (JPL-Devin#297 (comment))dispatch_idrun-name before giving up.DISPATCH_TOKENis job-level env (also visible toactions/checkout/upload-artifact); fork-controlledhead_branchwritten raw to the step summary;on_pr: falsebypassed by a manual run naming the repo pluspr_number.head_branchthroughcode(), honouron_pron manual runs.CONTRIBUTING.mdcheck description, manifest/ci.ymlcontract in the script header).Rule for external repositories with self-hosted / hardware runners
Compared with the current
ext-*.ymlmodel, a dispatched run executes in the external repository's trusted context (default branch,workflow_dispatch) instead of a forkpull_requestcontext: GitHub no longer strips secrets or forces a read-only token, default-branch caches are writable (persistence that survives runner re-imaging), and the App's dispatch token can start runs on those runners without an approval click. Before any such repository is added to the manifest:on_pr: falsefor that entry (hardware testsdevelnightly,release/**and the merge queue only), or at most same-repo heads via a job-levelif: inputs.fprime_repository == 'nasa/fprime'in the external workflow.permissions: {}(orcontents: read), no${{ secrets.* }}, no cache restore or save on dispatched runs, ephemeral/JIT runners, SHA-pinned actions, CODEOWNERS on.github/workflows/including nasa/fprime maintainers.workflow_dispatchitsci.ymlwith anyfprime_ref, outside nasa/fprime's approval gate — the external workflow's own restrictions above are what bound that path, not the orchestrator.on_pr: falseis the recommendation.Future Work
Add the other
fprime-communityrepos as theirci.ymllands; retire the matchingext-*.yml.Contributor Checklist
AI Usage (see policy)
Devin, under maintainer direction, wrote the workflows, script and manifest and ran the prototype and reviews.
AGENTS.md).IAMAI