GitHub Actions runtime upgrade conventions
Modernize GitHub Actions action versions without changing workflow behavior: select compatible stable major releases, pin runtime/dependency actions immutably, validate post-upgrade workflow parsing and execution, and document each upgrade.
When to invoke
- "Fix this GitHub Actions deprecated runtime warning."
- "Upgrade actions/setup-node to a supported runtime."
- "Review workflow action pins in
.github/workflows."
- "Move this workflow off an old Node.js action runtime."
- "Prepare PR notes for action runtime upgrades."
Upgrade rules
| Rule |
Required behavior |
| Stable major |
Prefer the latest stable major version compatible with the workflow. |
| Immutable pin |
Resolve the target release to a full commit SHA and use that SHA in uses:. |
| Version comment |
Add an optional version comment such as # v4.3.1 beside the SHA. |
| No mutable final pins |
Do not leave final uses: values pinned to @v4, @main, branches, or moving tags. |
| Small changes |
Upgrade one action at a time per commit, or one tightly related group. |
| Behavior preservation |
Keep triggers/permissions, inputs, outputs, release/signing/artifact behavior unchanged unless intentionally requested. |
Actions to prioritize
| Group |
Examples |
Why |
| First-party actions |
actions/* |
They commonly drive runtime deprecation warnings and have clear release lines; review first-party actions before third-party guesses. |
| Setup actions |
actions/setup-*, actions/setup-node, actions/setup-python, actions/setup-dotnet |
Runtime migrations often appear here first and affect downstream build steps. |
| Warning-named actions |
Any action explicitly named in workflow logs |
The log identifies the actual blocker. |
Pinning pattern
Use a full SHA in uses: and keep the human-readable release only as a comment:
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.3.1
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.4
When recommending an upgrade, first identify the latest compatible release, then resolve the release tag to its commit SHA, then update the workflow.
Verification checklist
| Check |
Evidence |
| Workflow parse |
Edited .github/workflows/*.yml or .github/workflows/*.yaml remains valid YAML. |
| Behavior preservation |
Triggers, permissions, env, with, secrets, matrix strategy, and job dependencies are unchanged unless documented. |
| Run validation |
Affected workflows re-run successfully, or equivalent local build/test commands pass when workflow execution is unavailable. |
| Output validation |
Release, signing, cache, and artifact steps still produce expected outputs where applicable. |
| Runtime warning scan |
New logs contain no new deprecation warnings or runtime migration notes. |
PR note content
Include these details in PR summaries or comments:
| Item |
Format |
| Actions upgraded |
<owner/action> from <old ref> -> <new sha> # <version>. |
| Compatibility caveat |
Any action that could not move to a new major and why. |
| Validation |
Workflow run links, rerun names, or local command results. |
| Behavior changes |
State none unless a change was intentional. |
Gotchas
- Do not pin to mutable tags in final recommendations:
@v4 and @main can move after review.
- Do not "fix" runtime warnings by changing unrelated workflow logic: isolate action upgrades from behavior changes.
- Do not batch unrelated actions: small upgrade sets make failures attributable.
- Dependabot is not a substitute for validation: automated bumps still need behavior-preserving checks.
Output template
## GitHub Actions runtime upgrade
**Status:** complete | needs validation | blocked
**Workflow:** `.github/workflows/<name>.yml`
| Action | Old ref | New ref | Reason | Validation |
| --- | --- | --- | --- | --- |
| `<owner/action>` | `<old>` | `<sha> # <version>` | <runtime warning or upgrade> | <run or command> |
### Behavior preservation
- Triggers changed: yes | no
- Permissions changed: yes | no
- Inputs/outputs changed: yes | no
### PR notes
- <summary line>
Quality gate
1---2name: github-actions-runtime-upgrade-conventions-23description: Upgrade GitHub Actions workflow dependencies to supported runtimes while preserving behavior. Use this skill when logs report deprecated Node.js action runtimes, when editing `.github/workflows/*.yml` or `.github/workflows/*.yaml`, or when choosing pinned action versions and validating upgraded workflow runs.4---56# GitHub Actions runtime upgrade conventions78Modernize GitHub Actions action versions without changing workflow behavior: select compatible stable major releases, pin runtime/dependency actions immutably, validate post-upgrade workflow parsing and execution, and document each upgrade.910## When to invoke1112- "Fix this GitHub Actions deprecated runtime warning."13- "Upgrade actions/setup-node to a supported runtime."14- "Review workflow action pins in `.github/workflows`."15- "Move this workflow off an old Node.js action runtime."16- "Prepare PR notes for action runtime upgrades."1718## Upgrade rules1920| Rule | Required behavior |21| --- | --- |22| Stable major | Prefer the latest stable major version compatible with the workflow. |23| Immutable pin | Resolve the target release to a full commit SHA and use that SHA in `uses:`. |24| Version comment | Add an optional version comment such as `# v4.3.1` beside the SHA. |25| No mutable final pins | Do not leave final `uses:` values pinned to `@v4`, `@main`, branches, or moving tags. |26| Small changes | Upgrade one action at a time per commit, or one tightly related group. |27| Behavior preservation | Keep triggers/permissions, inputs, outputs, release/signing/artifact behavior unchanged unless intentionally requested. |2829## Actions to prioritize3031| Group | Examples | Why |32| --- | --- | --- |33| First-party actions | `actions/*` | They commonly drive runtime deprecation warnings and have clear release lines; review first-party actions before third-party guesses. |34| Setup actions | `actions/setup-*`, `actions/setup-node`, `actions/setup-python`, `actions/setup-dotnet` | Runtime migrations often appear here first and affect downstream build steps. |35| Warning-named actions | Any action explicitly named in workflow logs | The log identifies the actual blocker. |3637## Pinning pattern3839Use a full SHA in `uses:` and keep the human-readable release only as a comment:4041```yaml42steps:43 - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.3.144 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.445```4647When recommending an upgrade, first identify the latest compatible release, then resolve the release tag to its commit SHA, then update the workflow.4849## Verification checklist5051| Check | Evidence |52| --- | --- |53| Workflow parse | Edited `.github/workflows/*.yml` or `.github/workflows/*.yaml` remains valid YAML. |54| Behavior preservation | Triggers, `permissions`, `env`, `with`, `secrets`, matrix strategy, and job dependencies are unchanged unless documented. |55| Run validation | Affected workflows re-run successfully, or equivalent local build/test commands pass when workflow execution is unavailable. |56| Output validation | Release, signing, cache, and artifact steps still produce expected outputs where applicable. |57| Runtime warning scan | New logs contain no new deprecation warnings or runtime migration notes. |5859## PR note content6061Include these details in PR summaries or comments:6263| Item | Format |64| --- | --- |65| Actions upgraded | `<owner/action>` from `<old ref>` -> `<new sha> # <version>`. |66| Compatibility caveat | Any action that could not move to a new major and why. |67| Validation | Workflow run links, rerun names, or local command results. |68| Behavior changes | State `none` unless a change was intentional. |6970## Gotchas7172- **Do not pin to mutable tags in final recommendations**: `@v4` and `@main` can move after review.73- **Do not "fix" runtime warnings by changing unrelated workflow logic**: isolate action upgrades from behavior changes.74- **Do not batch unrelated actions**: small upgrade sets make failures attributable.75- **Dependabot is not a substitute for validation**: automated bumps still need behavior-preserving checks.7677## Output template7879```markdown80## GitHub Actions runtime upgrade8182**Status:** complete | needs validation | blocked83**Workflow:** `.github/workflows/<name>.yml`8485| Action | Old ref | New ref | Reason | Validation |86| --- | --- | --- | --- | --- |87| `<owner/action>` | `<old>` | `<sha> # <version>` | <runtime warning or upgrade> | <run or command> |8889### Behavior preservation90- Triggers changed: yes | no91- Permissions changed: yes | no92- Inputs/outputs changed: yes | no9394### PR notes95- <summary line>96```9798## Quality gate99100- [ ] Every changed `uses:` reference is pinned to a full commit SHA, not a mutable tag or branch.101- [ ] The target release is the latest compatible stable major or the exception is documented.102- [ ] Workflow triggers, permissions, inputs, outputs, and artifacts are preserved unless intentionally changed.103- [ ] Edited workflow YAML parses.104- [ ] The affected workflow or equivalent validation ran successfully, or the blocker is reported.105- [ ] PR notes list old -> new action refs, validation, and any action that could not upgrade.