Repository navigation
Replace --rescan with sticky locks and runner-parity checks - #145
Open
nodeselector wants to merge 8 commits into
Open
nodeselector wants to merge 8 commits into
nodeselector wants to merge 8 commits into
Conversation
A pinned commit fixes the dependencies it declares, so every run now re-checks the recorded closure in one flat batch instead of walking it: same repository identity, commit still present, and exact-version tags still at the locked commit. Mutable refs stay locked until --relock. --verify becomes the frozen mode.
Generation followed repository renames silently, so a transferred action was pinned on the first run and only flagged on the next. Fresh pins now join the same parity batch as locked ones; a blocking finding keeps the workflow out of the write.
Treat repo_id as the only identity: a redirect with the same repo ID warns with the replacement uses: line, while a missing repository or a repo ID mismatch blocks. Any blocking parity finding now skips the commit, so --relock can no longer write a reclaimed repository's SHA. Walk the closure only from live roots, print parity findings in the default run, and reuse the Phase 2 resolution for fresh closures.
…tity Align with repo-ID lockfile identity: resolution follows renames and transfers, compares repo IDs, and rewrites `uses:` plus the lockfile key to the canonical name when the ID matches. A redirect inside a remote composite blocks with the parent named. Fresh pins whose identity can't be confirmed are not written. --verify warns on same-ID redirects. Cache only definitive anonymous SSO probe answers; rate limits and 5xx retry, and a rate-limited fallback surfaces SSO guidance instead of the bare SAML 403.
…rom repo-replaced
This was referenced Oct 9, 2026
nodeselector
marked this pull request as ready for review
October 9, 2026 22:26
nodeselector
added this pull request to stack #146
October 9, 2026 22:30
There was a problem hiding this comment.
🟡 Changes recommended
Case-sensitive refs can bypass fresh-pin parity, and several rename and fallback edge cases can produce incomplete or incorrect behavior.
4 open findings
What changed in this PR
Replaces --rescan with sticky locks, explicit --relock, and batched runner-parity validation.
Changes:
- Adds repository identity, commit, and immutable-tag parity checks.
- Rewrites renamed repository references while preserving locked commits.
- Updates fallback behavior, documentation, integration fixtures, and tests.
| File | Description |
|---|---|
test/scenarios/catalog.yml |
Updates CLI and parity scenarios. |
test/integration/run.rb |
Adds parity stubs and rename fixtures. |
test/integration/harness.rb |
Replaces rescan commands with relock. |
README.md |
Documents sticky locks and verification. |
internal/workflowfile/rewrite.go |
Validates mandatory reference rewrites. |
internal/resolve/resolver.go |
Redirects cached dependencies after renames. |
internal/resolve/discovery.go |
Tracks original redirected references. |
internal/pipeline/run.go |
Integrates sticky resolution and parity. |
internal/pipeline/run_test.go |
Removes obsolete fast-path tests. |
internal/pipeline/parity.go |
Implements parity checking and findings. |
internal/pipeline/parity_test.go |
Tests parity finding classification. |
internal/pipeline/doc_urls.go |
Maps repository findings to guidance. |
internal/pipeline/checks/parsed.go |
Updates immutable-ref semantics. |
internal/pipeline/checks/finding.go |
Handles rename validity and warnings. |
internal/pipeline/checks/category.go |
Adds repository parity categories. |
internal/pipeline/checks/category_test.go |
Freezes new category names. |
internal/pin/record.go |
Records required rename rewrites. |
internal/pin/plan.go |
Plans canonical-name migrations. |
internal/pin/commit.go |
Validates required rewrites before writing. |
internal/lockfile/state.go |
Traverses closures and carries renamed entries. |
internal/lockfile/state_test.go |
Tests transitive closure traversal. |
internal/lockfile/direct_tracker.go |
Recognizes redirected direct references. |
internal/ghapi/tagsource.go |
Improves SSO error reporting. |
internal/ghapi/rest_fallback.go |
Adds rate-limit handling and canonicalization. |
internal/ghapi/rest_fallback_test.go |
Tests fallback retries and guidance. |
internal/ghapi/repos.go |
Retrieves canonical repository metadata. |
internal/ghapi/graphql_parity.go |
Implements batched GraphQL/REST parity queries. |
internal/ghapi/graphql_parity_test.go |
Tests batching, parsing, and REST parity. |
internal/ghapi/graphql_action_files.go |
Canonicalizes redirected action results. |
internal/dep/dependency.go |
Tracks and merges original references. |
cmd/gh-actions-lock/verify.go |
Makes verify a frozen read-only check. |
cmd/gh-actions-lock/verify_test.go |
Updates verify flag tests. |
cmd/gh-actions-lock/selfrepository_test.go |
Accommodates parity requests. |
cmd/gh-actions-lock/run.go |
Removes rescan and wires relock/parity. |
cmd/gh-actions-lock/prune_workflow_test.go |
Stubs parity during pruning. |
cmd/gh-actions-lock/proxima_test.go |
Uses verify and supports SHA checks. |
cmd/gh-actions-lock/pin_summary.go |
Reports repository rewrites and errors. |
cmd/gh-actions-lock/parity_test.go |
Adds end-to-end parity coverage. |
cmd/gh-actions-lock/migrate_test.go |
Migrates rescan usage to relock. |
cmd/gh-actions-lock/format/terminal.go |
Renders repository parity findings. |
cmd/gh-actions-lock/command_test.go |
Updates command fixtures for parity. |
cmd/gh-actions-lock/check_json_golden_test.go |
Updates JSON tests to use relock. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+522
to
+523
| if len(dep.OriginalRefs) > 0 { | ||
| entry.RenamedFrom = dep.OriginalRefs[0].NWO() + "@" + dep.OriginalRefs[0].Ref |
Comment on lines
+69
to
+81
| switch { | ||
| case resp.StatusCode == http.StatusOK: | ||
| anonRateLimited.Delete(key) | ||
| anonProbeCache.Store(key, true) | ||
| return true | ||
| case isRateLimited(resp): | ||
| anonRateLimited.Store(key, struct{}{}) | ||
| return false | ||
| case resp.StatusCode >= 500: | ||
| return false | ||
| } | ||
| anonProbeCache.Store(key, false) | ||
| return false |
Comment on lines
+30
to
+31
| if err := validateRequiredRewrites(rec.Workflows); err != nil { | ||
| return err |
Comment on lines
+176
to
+178
| byKey[strings.ToLower(k)] = append(byKey[strings.ToLower(k)], d) | ||
| for _, p := range parents[k] { | ||
| children[strings.ToLower(p)] = append(children[strings.ToLower(p)], d) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


This drops
--rescanso a lock stays put until you--relock, and every run (or--verify) checks locked pins against their repository ID in one batched query, which ends up cheaper than what we had. When a repo was renamed or transferred we now rewriteuses:to the new name and keep the locked commit, and if the old name points at a different repo we stop instead of trusting it. New pins don't get written if we can't confirm who they belong to, since that's exactly when a takeover would slip in.