ci-workflow-refs
Skill627 starsChanged 8 days agoMITView on GitHub
Root workflows run at the triggering commit but call reusable workflows and composite actions pinned `@develop`, so on release/hotfix/main the child YAML is newer than the code it checks out. Read before changing any reusable workflow (`*-reusable.yml`, `workflow_call`) or composite action under `tools/actions/`, or before adding a CI step that runs a pnpm script, Nx target or repo file. Also read before writing how a CI change was tested, or before saying a CI change cannot be tested before merge.
In this repository70 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- analyticsSkill
- batch-feature-devSkill
- ci-runnersSkill
- cleanupSkill
- client-idsSkill
- cloud-sync-moduleSkill
- codeownershipSkill
- coin-families-contractSkill
- coin-modulesSkill
- commentsSkill
- configurationSkill
- console-logSkill
- create-changesetSkill
- create-prSkill
- data-layer-advancedSkill
- debug-rn-native-crashSkill
- dependency-patchesSkill
- detect-data-leaksSkill
- device-intent-executorSkill
- devtools-import-boundarySkill
- dialogs-sliceSkill
- docs-migrateSkill
- docs-update-or-createSkill
- domain-dataSkill
- e2e-desktop-add-or-updateSkill
- e2e-desktop-onboardSkill
- e2e-earnSkill
- e2e-mobile-add-or-updateSkill
- e2e-mobile-onboardSkill
- e2e-swapSkill
- errorsSkill
- feature-devSkill
- fix-ciSkill
- flow-packageSkill
- get-pr-commentsSkill
- git-conventionsSkill
- i18n-keysSkill
- impacting-prsSkill
- knip-migrationSkill
- ldls-nativeSkill
- ldls-webSkill
- ledger-wallet-cliSkill
- legacy-migrationSkill
- mvvm-architectureSkill
- new-packageSkill
- package-public-apiSkill
- pnpm-resolutionSkill
- prefer-set-hasSkill
- pre-reviewSkill
- react-generalSkill
- rebuild-to-fix-lib-import-errorsSkill
- remove-feature-flagSkill
- run-buildsSkill
- run-e2e-ciSkill
- runner-imagesSkill
- run-testsSkill
- slack-pr-messageSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 11
merge-queue.yml: only runs for PRs targeting develop, so its YAML always matches the children. - Very specific: line 30
Prefer pnpm exec nx run-many -t <target> -p <project>.
- Very specific: line 41
Create a Jira ticket to remove it after two release cycles.
- Very specific: line 44
Put the ticket key in the comment at the guard, e.g.
- Distinctive: line 60
Do not push the next edit to the PR branch.
- Distinctive: line 70
Do not open a PR for the scratch branch.
- Distinctive: line 72
Put the run URL in the PR's Tested section, then delete the scratch branch.
- Very specific: line 74
If the reusable has no workflow_dispatch (grep -L workflow_dispatch .github/workflows/*-reusable.yml), add one on the scratch branch only.
- Distinctive: line 126
Before a run counts, open the job you changed and check that it ran and that the step you changed ran.
- Very specific: line 139
Write "not testable" only for something a dispatch cannot run (a schedule, merge_group or push-to-develop trigger, or a secret only develop …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CI Workflow Refs (split brain)
How it runs
- Root workflows (
build-and-test-push.yml,build-and-test-pr.yml,merge-queue.yml,release-*.yml) run from the triggering commit's YAML. merge-queue.ymlonly runs for PRs targetingdevelop, so its YAML always matches the children. An input passed only frommerge-queue.ymlcan be renamed or removed in the same PR as the child, with no deprecation.- Children are pinned:
uses: LedgerHQ/ledger-live/.github/workflows/<x>-reusable.yml@developandLedgerHQ/ledger-live/tools/actions/...@develop. They always run develop's YAML. - Checkout uses
github.sha(orinputs.ref), so the code,package.jsonscripts and Nx projects come from the caller's branch.
On develop the two match. On release, hotfix, main and PRs targeting them, the code can be weeks or months older than the YAML running against it.
What breaks
A child workflow or action on develop can only rely on what exists on every branch that calls it:
- ❌ A new step running
pnpm <new-script>,nx run <new-project>:<target>or a new file path. It fails on release/hotfix, where the script or project doesn't exist yet. - ❌ A new required input on a reusable workflow. Older root workflows don't pass it.
- ❌ Removing or renaming an input or output. Older callers still pass or read it.
- ❌ Changing a composite action's inputs in a way older callers can't satisfy.
Release and hotfix pipelines are the worst place to find this out.
Do this instead
- Prefer
pnpm exec nx run-many -t <target> -p <project>. It is a no-op when the project is absent (seetest-boundaries-reusable.yml). Leave a comment saying why. - Guard steps on presence, e.g.
if: hashFiles('path/to/new/config') != '', or check in the script before running it. - Give new inputs a
defaultand keep them optional. Deprecate inputs before removing them, and remove them only after release and hotfix have caught up. - To make a new check mandatory everywhere, land the code first, then wire it into the root workflow (which runs at the commit) rather than the
@developchild. Or wait until the change has reachedmainbefore you make the child depend on it. - Composite actions are local to the repo, but
@developpins them the same way, so the same rules apply.
Clean up guards and deprecations
A presence guard, a run-many no-op or a deprecated input is temporary. It is needed only until
release, hotfix and main have the change. When you add one:
- Create a Jira ticket to remove it after two release cycles. In the ticket, name the guard (file and
step) and the check that shows it can go, e.g.
git ls-tree origin/hotfix -- <path>orgit show origin/main:package.jsonhas the script. - Put the ticket key in the comment at the guard, e.g.
# Guard until hotfix has <path>. Remove in LIVE-1234.
Checklist
- Every command the changed child runs exists on
releaseandmaintoday (git show origin/release:package.json,git ls-tree origin/main -- <path>) - New inputs are optional with defaults, and no inputs or outputs were removed
- Any guard you rely on is explained in a short comment at the step
- Each guard or deprecated input has a cleanup ticket, and its key is in the comment at the step
Test a child change before merge
PR checks run develop's copy of every @develop child, so they do not run your change.
That does not make the change untestable. Run the child yourself from a scratch branch.
- Rebase your PR branch on
origin/develop, then branch off it:git switch -c ci-test/<topic>. Do not push the next edit to the PR branch. - On the scratch branch, change
@developto@ci-test/<topic>on eachuses:line between the workflow you will dispatch and the file you changed:- composite action:
uses: LedgerHQ/ledger-live/tools/actions/composites/<action>@ci-test/<topic> - nested reusable:
uses: LedgerHQ/ledger-live/.github/workflows/<x>-reusable.yml@ci-test/<topic>
- composite action:
- Push, then dispatch the reusable on that branch.
workflow_dispatchruns the YAML from--ref:
Do not open a PR for the scratch branch. The dispatch does not need one, and a PR gets a Copilot review and runs the PR checks.gh workflow run build-desktop-reusable.yml --ref ci-test/<topic> -f ref=ci-test/<topic> gh run list -w build-desktop-reusable.yml -b ci-test/<topic> -L1 # get the run id, then: gh run watch <id> - Put the run URL in the PR's Tested section, then delete the scratch branch.
If the reusable has no workflow_dispatch (grep -L workflow_dispatch .github/workflows/*-reusable.yml),
add one on the scratch branch only. Declare any inputs it reads.
Test older callers (release, hotfix)
Your first dispatch checks out your scratch branch: develop as of your last rebase, plus your change.
Rebase first so it matches what the child will meet on develop. After merge, release, hotfix and main
also run the child, against older code. Use the checklist above first. Run a second dispatch only if
the change depends on something those branches may not have (a script, Nx target, file, input,
dependency version or lockfile entry), or if you cannot tell. Dispatch the same scratch branch and
point ref at the older branch:
gh workflow run <x>-reusable.yml --ref ci-test/<topic> -f ref=release--ref picks the YAML (develop plus your change, as release will run it after merge). ref picks the
code that is checked out.
Gotcha: a cache replay is not a test
Jobs pass builds to each other through caches keyed on source files, not on CI files. If your change alters how something is built, a cache hit hands the next job a build that an older CI made. The run is green, but nothing was tested.
- Nx tasks: Nx hashes project files, root config files and named env vars (
nx.workspace.json→namedInputs), not.github/**ortools/actions/**. Setskip-nx-cache: "true"on thesetup-cachesstep of every job you test (NX_SKIP_NX_CACHE=true). In the log,[local cache],[remote cache],existing outputs match the cache, left as isorNx read the output from the cache instead of running the commandmean a replay. - Mobile native builds (
test-mobile-e2e-reusable.yml):determine-buildslooks up the iOS and Android native builds in the S3 cache, keyed on the app's native folders and a version suffix. On a hit, the build job skips the native build, andskip-nx-cachedoes not change that. On the scratch branch, change the suffix in theDetermine cache keysstep (e.g.-detox-native-ios-4→-detox-native-ios-4-ci-test). Then check thatios_native_exists/android_native_existsisfalseand that the native build step ran. - Desktop e2e userdata is always restored from develop's cache. A change to how it is generated cannot be tested through an e2e run.
- Artifacts within one run (
upload-artifact→download-artifact) are safe only if the job that uploads them ran the step you changed.
Gotcha: a skipped job is green too
- In
build-and-test-pr.yml, a child job runs only ifnx-affectedlists its path (if: contains(needs.determine-affected.outputs.paths, '<path>')). A greennx-affecteddoes not mean the job you changed ran. A PR that changes only CI files affects no project, so those jobs do not start. - Some children get values from the root as inputs (
js_bundle_hash_*,build-web-tools,affected_paths). A dispatch does not run the root.-fcan only set inputs declared underworkflow_dispatch. An input declared only underworkflow_callis empty in a dispatch: its default does not apply, and-frejects it. To set one, declare it underworkflow_dispatchon the scratch branch. Steps gated on these inputs can behave differently from the PR path. - Before a run counts, open the job you changed and check that it ran and that the step you changed ran. It must not be skipped, and it must not be a cache replay.
Quick local check
A composite action's run: steps are shell commands. Run them locally first when you can, on the same OS
as the runner. This catches mistakes faster than CI, but it does not replace the dispatched run.
What to write in the PR
- ✅
CI | Dispatched build-desktop-reusable on ci-test/<topic> with the action repointed and the Nx cache skipped. Job "macOS Build", step "Build desktop" ran: <run URL> - ✅
Release callers | Same dispatch with -f ref=release: <run URL>(only when you ran it) - ❌
Not testable before merge: PR builds run this action @develop.Use the steps above instead. Write "not testable" only for something a dispatch cannot run (aschedule,merge_groupor push-to-develop trigger, or a secret only develop can read). Name that part and say what you checked instead.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

