Make local-action migration default-on with a --no-migrate-local-actions opt-out by nodeselector · Pull Request #92 · github/gh-actions-lock · GitHub
Skip to content

Make local-action migration default-on with a --no-migrate-local-actions opt-out - #92

Merged
nodeselector merged 2 commits into
mainfrom
nodeselector-migrate-local-actions-default-on
Jul 24, 2026
Merged

nodeselector merged 2 commits into
mainfrom
nodeselector-migrate-local-actions-default-on

Conversation

@nodeselector

Copy link
Copy Markdown
Collaborator

Why

Rewriting same-repo ./… composite action refs to the inherently-pinned $/… form was gated behind the opt-in --migrate-local-actions flag, so most fix runs left non-compliant local refs in place. Since the rewrite is safe (only paths that resolve to an in-repo action file are migrated) and is what we want in the common case, this makes it the default and gives users a clean way to opt out.

What changed

  • Default-on migration. The gate at both entrypoints (run.go and verify.go) becomes !opts.noMigrateLocalActions && !opts.noFix. Migration now runs automatically on any fix run. The !opts.noFix guard is preserved exactly, so read-only runs still never touch disk.
  • Real named opt-out. Replaces the opt-in flag with --no-migrate-local-actions (opts.noMigrateLocalActions, default false), mirroring the repo's existing --no-fix negative-flag convention rather than relying on --flag=false. The old --migrate-local-actions flag was unreleased, so no back-compat no-op alias is kept.
  • Wording. Updates the diagnose.go remediation strings and the README to say migration is automatic and can be disabled with the opt-out flag.

The rewrite algorithm itself (MigrateLocalActionsToSelfRepository, migrateLocalActions) is untouched.

Heads-up for review

One behavior change worth a conscious look: because migration now runs by default, an invalid $/… ref is validated during the migration pass and aborts the whole run early, where a plain run previously proceeded to diagnosis. The affected pre-existing command test was updated to assert that error; the invariants it guards (no network, file left untouched) still hold. If we'd rather soften this (downgrade a migration-validation failure to a warning and skip that file instead of aborting), that can be a follow-up.

Tests

  • New TestMigrateLocalActions_DefaultOnAndOptOut covers: (a) a plain fix run rewrites ./.github/actions/foo to $/…, (b) --no-fix leaves the file untouched, (c) --no-migrate-local-actions suppresses the rewrite.
  • Existing selfref/migrate tests updated to drop the now-default flag.
  • Catalog: the rewrite scenario drops the flag and notes default-on; added a migrate_local_actions_opt_out scenario. Both are [stub]-tagged so they run in blocking CI.

Verified with gofmt, go build ./..., go vet, go test ./..., plus a manual smoke on a throwaway repo confirming all three behaviors.

Out of scope

Job-level local reusable-workflow calls (uses: ./.github/workflows/x.yml) remain excluded. The rewrite algorithm is unchanged.

Local-action migration (same-repo `./…` composite refs → inherently-pinned
`$/…`) was gated behind opt-in `--migrate-local-actions`. Flip it to run by
default on any fix run, and add a real named opt-out that mirrors the existing
`--no-fix` negative-flag convention.

- Gate at both entrypoints (run.go, verify.go) becomes
  `!opts.noMigrateLocalActions && !opts.noFix`; the `!opts.noFix` guard is
  preserved exactly so read-only runs never touch disk.
- Replace the opt-in flag with `--no-migrate-local-actions`
  (`opts.noMigrateLocalActions`, default false). The old flag was unreleased,
  so no back-compat no-op alias is kept.
- Update diagnose.go remediation strings and the README to say migration is
  automatic and can be disabled with the opt-out flag.
- Update tests/catalog: drop the now-default flag, add coverage for the
  default-on rewrite, the `--no-fix` no-touch guarantee, and the opt-out; add
  an opt-out catalog scenario. An invalid `$/…` ref now aborts during the
  default migration pass, so the affected command test asserts that error.

Copilot-Session: c95a173f-d4b8-43a9-9a78-880ec48023d6
@nodeselector
nodeselector requested a review from a team as a code owner July 24, 2026 12:04
Copilot AI review requested due to automatic review settings July 24, 2026 12:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes local-action migration default-on for fix runs, with an explicit opt-out.

Changes:

  • Replaces the opt-in flag with --no-migrate-local-actions.
  • Updates diagnostics and documentation.
  • Adds command and integration coverage for default and opt-out behavior.
Show a summary per file
File Description
README.md Documents automatic migration and opt-out.
cmd/gh-actions-lock/run.go Implements default-on migration and the new flag.
cmd/gh-actions-lock/verify.go Applies default migration to local verification.
cmd/gh-actions-lock/migrate_test.go Updates and extends migration tests.
cmd/gh-actions-lock/selfrepository_test.go Updates invalid-reference expectations.
internal/pipeline/diagnose.go Revises migration remediation text.
test/scenarios/catalog.go Updates fixture documentation.
test/scenarios/catalog.yml Updates default behavior and adds opt-out coverage.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

cmd/gh-actions-lock/migrate_test.go:276

  • This drops the command error, so the opt-out test also passes if the new flag is rejected (or execution fails before reaching migration), because the workflow remains unchanged either way. Require the expected successful command execution before asserting the file contents.
		_, _, _ = runCommandWithHTTP(t, transport, "--no-migrate-local-actions", wf)
  • Files reviewed: 8/8 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread cmd/gh-actions-lock/migrate_test.go Outdated
t.Run("--no-fix leaves file untouched", func(t *testing.T) {
transport := &requestCountingTransport{}
wf := setup(t)
_, _, _ = runCommandWithHTTP(t, transport, "--no-fix", wf)
Comment thread test/scenarios/catalog.yml Outdated
Comment on lines +531 to +533
Default-on migration front-runs diagnosis, so the three self_repository_*
scenarios that feed intentionally-invalid `$/` refs were aborting in the
migration pass instead of reaching --verify-local diagnosis. Their purpose is
to prove the real binary diagnoses bad `$/` refs, and opting out of migration
is now how you reach that path, so add --no-migrate-local-actions to each.
The abort behavior itself stays covered by the Go command tests.

Also acts on review feedback:
- Remove the migrate_local_actions_opt_out catalog scenario. It duplicated the
  deterministic TestMigrateLocalActions_DefaultOnAndOptOut Go test with no
  real-binary delta; the opt-out now gets compiled-binary coverage through the
  self_repository_* scenarios where it has a genuine integration purpose.
- Assert the command result in the --no-fix and --no-migrate-local-actions
  subtests so they prove the guard rather than merely the absence of a write.

Copilot-Session: c95a173f-d4b8-43a9-9a78-880ec48023d6
@nodeselector
nodeselector merged commit 772985b into main Jul 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants