# Upgrade Pinned GitHub Actions to the Latest Releases

Yes. A Rush agent pins every uses: line to a release commit SHA, bumps your action's npm dependencies, runs npm run all and opens one pull request.

[Run this on Rush](https://cloud.getrush.ai/run/update-github-actions/github-actions/), in a Project that has your repository.

## What the agent does

In a repository like actions/typescript-action, the workflows reference other actions by tag, not by commit: ci.yml, check-dist.yml, licensed.yml and linter.yml use actions/checkout@v6 and actions/setup-node@v6, codeql-analysis.yml uses github/codeql-action/init, autobuild and analyze @v4, check-dist.yml uses actions/upload-artifact@v7, linter.yml uses super-linter/super-linter/slim@v8, and licensed.yml uses ruby/setup-ruby@v1 and licensee/setup-licensed@v1.3.2. A tag can be moved to different code; a full commit SHA cannot. The agent lists every uses: line with its file, skips the local uses: ./ that ci.yml runs to test the action itself, and resolves each tag's latest release to the commit it points at.

It rewrites each line as owner/repo@<40-character SHA> # vX.Y.Z, so the pin is immutable and the comment keeps it readable. .github/dependabot.yml already watches the github-actions ecosystem weekly, and Dependabot updates SHA pins that carry a version comment, so the pins keep getting proposed after this change. A major version jump, such as a new checkout major, is read against that action's release notes for removed inputs before it is kept.

The npm side is the action itself. package.json declares engines node >=24.0.0, .node-version says 24.4.0, action.yml runs using: node24 with main: dist/index.js, and the one runtime dependency is @actions/core ^3.0.0, with Rollup, Jest 30, ts-jest, ESLint 10 and TypeScript 5 as dev dependencies. The agent bumps them with npm, then runs npm run all, which is format:write, lint, test (Jest with --experimental-vm-modules), coverage (rewriting badges/coverage.svg) and package (Rollup into dist/).

Because check-dist.yml rebuilds dist/ and fails on any diff, the agent commits the rebuilt dist/index.js with the dependency changes, so the pull request's own check passes. A bump that breaks lint, tests or the bundle is left out, with its output.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Pin every third-party uses: line in .github/workflows to the full commit SHA of its latest release, written as owner/repo@<sha> # vX.Y.Z; leave the local uses: ./ alone and check release notes for removed inputs on any major jump. Upgrade the npm dependencies to the latest compatible versions with npm, run npm run all, and commit the rebuilt dist/ so check-dist passes. Leave out any upgrade that breaks the build or tests and say why. Open a pull request with one line per bump, actions and npm packages listed separately.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

The pull request changes the five workflow files, package.json, package-lock.json, dist/ and badges/coverage.svg. Its description lists each action with its old tag, the new release and the SHA it is pinned to, then each npm package with old and new versions, and finally anything left out with the failing step. The checks on the pull request itself (ci.yml, check-dist.yml, linter.yml, codeql-analysis.yml, licensed.yml) run on the pinned versions, so a wrong SHA fails there before merge.

A reviewer checks each SHA against the release it names on that action's releases page, reads the notes for any major version, and confirms that .licenses/ still matches the dependency tree, since licensed.yml checks it. The npm run all output is in the session transcript.

## Run it on every Dependabot pull request that fails

Dependabot already opens weekly pull requests here. When one fails check-dist or the tests, start a run with POST /o/{org}/sessions naming the repository on that branch with a resources URL ending in /pull/<n>, and an input that asks the agent to fix the failure. A webhook on the key reports run.completed when it has pushed.

For the first pass, run the request above once to move every tag to a SHA; after that the failing Dependabot pull requests are the events worth a run.

## Why run it on Rush?

Resolving every tag to a commit, reading release notes for the majors, bumping npm packages, running format, lint, tests, coverage and Rollup, and committing a rebuilt dist/ is fiddly work that is easy to get half right. In Rush it runs in its own sandbox, and each gh, git and npm command, with its output, is in the transcript for the reviewer.

A run per repository means every action you maintain can get the same treatment at once, within the key's concurrency limit, each coming back as a pull request that its own checks have already exercised.

## Frequently asked questions

### Why pin to a SHA instead of a tag?

A tag can be moved to point at different code, and a SHA cannot. Pinning to the full commit with the version in a comment keeps the workflow readable and stops a retagged release from changing what runs.

### Will Dependabot still update the pins?

Yes. .github/dependabot.yml watches the github-actions ecosystem weekly, and Dependabot updates SHA pins that carry a version comment. The agent writes the comment in that form.

### Why does the pull request change dist/?

action.yml runs dist/index.js, and check-dist.yml fails when a fresh build differs from what is committed. Bumping a dependency changes the bundle, so the rebuilt dist/ is part of the change.

### Does it change what my action does?

It should not. The request limits it to version bumps and the fixes they force, and the existing Jest tests in __tests__/ must still pass. Any source change is listed in the description with the reason.
