Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 2 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
# gh-actions-pin

Lock and verify GitHub Actions workflow dependencies from the command line.

This extension resolves `uses:` references to their current commit SHAs and
previews the resulting inline `dependencies:` changes by default. Use `--write`
to apply them. It also supports validation, targeted refreshes, ref upgrades,
and lockfile cleanup.

When a workflow's direct action refs have changed since the last lock, the
write path refuses to silently bless those edits by default. Use `upgrade` for
intentional bumps, or pass `--allow-ref-changes` if you really mean it.
Manage your workflow dependencies.

## Install

Expand All @@ -19,41 +10,5 @@ gh extension install github/gh-actions-pin

## Usage

```bash
# Preview all workflows in .github/workflows/
gh actions-pin

# Write the proposed lockfile changes
gh actions-pin --write

# Explicitly acknowledge direct workflow ref edits
gh actions-pin --write --allow-ref-changes

# Preview a specific workflow and inspect the proposed delta
gh actions-pin .github/workflows/ci.yml --diff

# Check the current lock state
gh actions-pin check

# Refresh a targeted action
gh actions-pin update --action actions/checkout

# Upgrade a workflow action to the latest stable tag and repin it
gh actions-pin upgrade --action actions/checkout --write

# Upgrade to a specific version
gh actions-pin upgrade --action actions/checkout --version v5 --write

# Upgrade only checkout refs currently on v5 to v6
gh actions-pin upgrade --action actions/checkout --from v5 --version v6 --write

# Remove stale entries
gh actions-pin tidy
```

## Notes
Run through the UX feedback loop [here](https://github.com/github/gh-actions-pin/discussions/3).

- with no arguments, the extension discovers workflow files under `.github/workflows/`
- local path actions (`uses: ./path`) are currently skipped
- the default preview prints a compact summary and points you at `--diff` for closer review
- use `--hostname` if you need to target a specific GitHub Enterprise host
36 changes: 2 additions & 34 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
- uses: actions/setup-go@v6
`)

stdout, stderr, err := runCommandWithHTTP(t, reg, "--diff", workflowPath)
stdout, stderr, err := runCommandWithHTTP(t, reg, workflowPath)
require.NoError(t, err)
assert.Empty(t, stdout)
assert.Contains(t, stderr, "Resolving 2 action reference(s)...")
Expand Down Expand Up @@ -272,7 +272,7 @@ dependencies:
`)

stdout, stderr, err := runCommandWithHTTP(t, reg,
"update", "--action", "github.com/actions/checkout", workflowPath,
"update", "--action", "github.com/actions/checkout", "--write", workflowPath,
)
require.NoError(t, err)
assert.Empty(t, stdout)
Expand All @@ -285,38 +285,6 @@ dependencies:
assert.Contains(t, got, "github.com/actions/setup-go@v6:sha1-4a3601121dd01d1626a1e23e37211e3254c1c06c")
}

func TestTidyCommand_RemovesStaleEntries(t *testing.T) {
reg := &httpmock.Registry{}
defer reg.Verify(t)

workflowPath := writeTempWorkflow(t, `
name: ci
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

# Automatically generated and managed by: gh actions-pin --write <workflow-path>
dependencies:
- github.com/actions/checkout@v6:sha1-de0fac2e4500dabe0009e67214ff5f5447ce83dd
- github.com/actions/setup-go@v6:sha1-4a3601121dd01d1626a1e23e37211e3254c1c06c
`)

stdout, stderr, err := runCommandWithHTTP(t, reg, "tidy", workflowPath)
require.NoError(t, err)
assert.Empty(t, stdout)
assert.Contains(t, stderr, "Tidied 1 dependencies")
assert.Contains(t, stderr, "removed 1 stale")

content, readErr := os.ReadFile(workflowPath)
require.NoError(t, readErr)
got := string(content)
assert.Contains(t, got, "github.com/actions/checkout@v6")
assert.NotContains(t, got, "github.com/actions/setup-go@v6")
}

const nodeActionYAML = "name: Test Action\nruns:\n using: node20\n"

func testRepoResponse(nameWithOwner, oid, actionYAML string) map[string]any {
Expand Down
Loading
Loading