{{ message }}
Repository navigation
Commit 8bb4bb6
Trace every locked commit to its recorded ref (#186)
* Trace every locked commit to its recorded ref (#174)
Recover local fix fcdd43df96c77d5a376a3c27de8d03f07f6317c5 and retain both community normalization safeguards.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Align pin fixtures with recorded-ref proof
Recorded tags now re-peel before repair (#174) and branch normalization
needs a head proof (#165), so same-run conflicting repairs can no longer
be planned. Fixtures ported from candidate commit 3eb0100.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Align stub scenarios with recorded-ref proof
Parity now resolves recorded branch heads and fails closed when the
recorded ref is inconclusive (#174). Stub fixtures ported from candidate
commits 3eb0100 and 22e894c.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Describe runner ref lookup without naming internal services
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Lock live checkout fixtures to a commit their v4 ref contains
CHECKOUT_SHA was the actions/checkout v6.0.2 commit while the fixtures
record it under v4 and main. Recorded-ref tracing (#174) correctly rejects
that; use the real v4.2.2 commit the stub tag list already names.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Test that only the SHA a recorded tag peels to is repaired
Restores the #167 same-run scenario with a recorded tag instead of
swapping it for a branch, which only exercised the missing-head exit.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Trim parity command tests to what unit tests can't prove
Keep the original --verify bodies, adjusted for ref-qualified lookups and
fail-closed inconclusive checks; replace the mode cross-products with one
default/--no-fix test, and drop full-SHA and entry-ref cases that
TestParityFinding_FullSHAKey and TestValidEntryRef already cover.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Attribute ref lookup rules to the Actions backend resolver
The backend resolver, not the runner, looks up and rejects lock entry
refs; say so in comments, docs and the missing-ref finding detail.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Check exact tags by history like any other ref
Tags move, and the Actions backend accepts a pin whose commit is still in
its tag's history. Every lock entry ref is now checked by reachability:
a tag that lost the commit still blocks and an inconclusive check still
fails closed, but a tag that moved ahead only warns under --verify.
Dropping the separate tag-equality lookup also saves the extra REST
commit call when a ref still points at its locked commit.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Render warnings by severity and show moved exact tags
An error-severity finding blocks the run, so it never renders as a
warning. Under --verify the terminal now shows an exact tag that moved
ahead of its locked commit, matching the JSON warning, and the
inconclusive-check remediation names the Actions backend.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Reject revision syntax in recorded and resolved refs
A ref like main~1 or v1@{1} is not a tag or branch name, but a commit-ish
lookup evaluates it as a revision. Validate names with git
check-ref-format rules, matching actions-lockfile's RefName: an entry ref
that fails makes the lockfile unreadable, and parity never builds a
lookup expression from one.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Keep fresh-pin parity failures under --relock
--relock drops findings for recorded pins because it replaces them, but
it also dropped them for pins it had just resolved, so it could write a
lock that the next --verify rejects.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Let --accept-moved re-record a full-SHA pin whose ref moved
A full-SHA entry whose recorded tag or branch no longer vouches for it
recommended --accept-moved, which then refused it. --accept-moved now
accepts it as a warning and re-records a tag or branch that contains the
commit, chosen by reverse lookup; a commit no branch contains still fails.
Fresh full-SHA pins are no longer checked against a pre-planning ref.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Never record a branch that a same-named tag shadows
The Actions backend resolver looks a recorded ref up as a tag before a
branch, so reverse lookup now skips a containing branch whose name is
also a tag.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Look up recorded refs by exact name and reject describe names
A ref counts only if a tag or branch exists by exactly that name: GraphQL
also asks ref(qualifiedName:), and REST reads git/ref/{tags|heads}/<name>.
Like the Actions backend, names ending in -g plus four or more hex
digits are not accepted as recorded or uses: refs, so an entry with one
makes the lockfile unreadable and a uses: ref with one is never locked.
Adapted from 2134d14 and 93b2f4a.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Name re-recorded refs and never-recorded refs in the terminal
--accept-moved now prints the old and new recorded ref when it keeps a
full-SHA pin's commit but records a new tag or branch for it. A ref this
run resolved that isn't a tag or branch is titled "Not a tag or branch";
"Ref no longer exists" is kept for a ref the lockfile recorded.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Print tool failures before the run log, without request URLs
A tool failure now prints before the run log path instead of after it.
Inconclusive checks and the Dependabot proxy abort show a short cause on
the terminal, such as "could not check v4 history: GitHub returned 403
Forbidden"; --json and the run log keep the full error.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Title a gone recorded ref as missing, not as lost history
A full-SHA pin whose recorded tag or branch no longer exists was titled
"Pinned commit not in upstream history". It is now "Ref no longer
exists", like any recorded ref that is gone.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Print schema upgrades and pruning before the pin summary
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Show a moved recorded tag beside a full-SHA pin's other warnings
Terminal warnings were grouped by dependency alone, so a full-SHA pin's
sha-as-ref notice hid the --verify warning that its recorded exact tag
moved ahead. Group by dependency and category.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Check a reverse-looked-up branch for a same-named tag by exact name
The shadow check used the tag listing, which reads only its first page,
so a tag beyond it could shadow the branch reverse lookup recorded.
Look the chosen branch's name up as an exact tag instead (through the
same REST paths as parity, including the anonymous and Dependabot
proxy fallbacks) and search again without it if one exists; a lookup
that can't finish fails the run.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Fall back to anonymous compare for a public repo behind SSO
CompareRefs had no anonymous fallback for an SSO-blocked token, unlike
CompareCommits, so a public action reached through the fallback blocked
once its recorded ref moved and its history needed checking.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Never plan a ref the lockfile would refuse, and refuse before writing
Reverse lookup could pick a tag or branch whose name the Actions backend
rejects, and Commit rewrote workflows before the lockfile refused the
entry, leaving them changed with no lock. Reverse lookup now skips such
names, and Commit updates the lockfile in memory before rewriting any
file.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Name a ref-only --accept-moved repair in the summary
When --accept-moved keeps a full-SHA key and its commit (for example
under --no-narrow), the entry is Verified, so the summary never said its
recorded ref changed. Consider verified entries too.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Keep a transitive full-SHA pin blocking under --accept-moved
--accept-moved accepted any full-SHA pin whose recorded ref no longer
vouched for it, but planning doesn't rebuild an unchanged composite's
dependencies, so a transitive one passed with its entry unchanged. Accept
only direct pins; a transitive one stays blocking.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Title describe-name refusals as refused, not missing
A ref shaped like `git describe` output is refused by name and never
looked up, so it may well exist. Say so instead of claiming it is not a
tag or branch, and point the remediation at the name. Wording matches
fc8e493.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Fail on remote uses: values the parser rejects instead of skipping
The lockfile parser returns no ref for a remote-looking uses: it can't
accept, such as owner/repo@main:action.yml, and the workflow scan, the
$/ action scan, local composite scan and remote composite discovery all
skipped it, so a run could lock without it. Those are now errors;
local paths, docker images, expressions, $/ references and reusable
workflows are still not repository actions and are unchanged.
Regression tests adapted from the release-branch reproduction.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Name the lockfile problem instead of calling it unreadable (#166)
An invalid lockfile was reported as "unreadable" even when the file
parsed fine and one entry's contents were wrong, and a fix run offered to
delete and recreate it. Errors now name the file, line, entry and what is
wrong, and suggest restoring the file from version control if it was
edited by hand. The lockfile is never deleted or rewritten; the run still
exits 2.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Search every page of tags and branches before calling a commit off-history
Reverse lookup read one page of tags and three of branches, so a commit
reachable only through a tag or branch past those was reported as a fork
or impostor commit. With no containing branch and no tag on the first
page, it now reads every page of tags, and the branch listing reads every
page. Both go through the same REST paths, including the anonymous and
Dependabot proxy fallbacks; a commit no ref contains still fails.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Fail on reusable workflows referenced from steps
A step-level uses: naming a remote .github/workflows/ file was skipped,
so the run passed with nothing locked for it. Like the Actions backend,
reusable workflows are accepted only at jobs.<job_id>.uses; in a workflow
step or a composite step they now fail with the backend's wording.
Job-level reusable workflows are unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Classify uses: values in one place
ParseActionRef returns nil both for values that aren't repository
actions by design and for references the backend rejects, and each scan
decided separately which nil to skip; that is how malformed references
and step-level reusable workflows slipped through. internal/uses now
returns a typed kind (or an Invalid kind with its error) and the workflow
scan, $/ action scan, local composite scan and remote composite
discovery all use it. Behavior is unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Gather reverse-lookup ref candidates behind one type
Which tag or branch can be recorded for a commit was decided by three
separate filters added one fix at a time: backend name policy, tag
shadowing of branches, and later pages of the tag listing. refCandidates
now owns that question for reverse lookup. Behavior is unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Treat a pin the workflow uses directly as direct in its closure
Closure walked depth-first from the first root, so a pin a composite
listed earlier also used was reported as that composite's child even
though the workflow uses it directly. Directness feeds --accept-moved
scope and remediation, so --accept-moved could refuse a direct pin.
Claim every root before walking children.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Point a composite's broken full-SHA pin at its parent, not --accept-moved
--accept-moved doesn't repair a composite's full-SHA child, yet its
missing-ref and lost-history findings recommended it. Recommend upgrading,
replacing or removing the parent composite instead.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Put exact ref lookups in one layer
Exact tag and branch lookups were spread across parity (restRef,
restRefCommit), the shadow check (TagExists) and the tag-page scan
(TagsAtCommit), each restating the same rules. internal/ghapi/refs.go now
owns them: backend name policy, tag-then-branch order, exact-name match,
fail-closed errors, every page of listings, and the Dependabot proxy and
anonymous SSO fallback through restGet. GraphQL parity uses the same names
via refNames. No behavior or request-count change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Read named branch heads through the shared ref layer
GetBranchHead called git/ref directly, so a public repository behind SSO
never got the anonymous fallback the other ref lookups have, and the
named-branch phase of reverse lookup fell through to a full branch scan.
It now uses the shared exact lookup; its cache and its ok=false-on-error
contract are unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Make ref name policy, ref existence and recordable refs one owner each
The ref-candidates refactor centralized HTTP calls but not decisions, so
Copilot's review found the same cluster again. This commit adds the owners
without changing behavior:
- ghapi.RecordableRefName: the one name predicate; ValidEntryRef uses it.
- ghapi.RefTarget / LookupRefName: whether a tag or branch exists and the
commit it peels to are separate facts.
- resolve.BranchAtCommit: the planner's SHA repair asks reverse lookup's
candidate type instead of reading branch heads itself.
The following commits fix the behaviors on top of these.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Let an existing tag shadow a same-named branch even if it doesn't peel
Tag precedence keyed off the tag peeling to a commit, so a tag that
targets a tree or blob fell through to a same-named branch and parity
checked the branch's history. Precedence now keys off the tag existing,
on both the GraphQL and REST paths; such a tag resolves to no commit.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Apply the full recorded-ref name rules to every candidate, before paging
Reverse lookup filtered tag names with the backend rule only, and after
deciding whether to read more pages. An unrecordable tag on the first page
(release-g1234) then stopped the search for a recordable tag on a later
page, and SHA-shaped or refs/ tag and branch names could be chosen and
rejected later by the lockfile. Candidates now use RecordableRefName, the
same predicate as ValidEntryRef, before any paging or selection.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Never repair a full-SHA uses: to a branch a same-named tag shadows
The planner's SHA repair picked the recorded branch when its head was the
locked commit, without the tag-shadow check reverse lookup does, so
rewriting to @main could name a same-named tag's commit instead. The
repair asks refCandidates, which now also applies the name policy and
the shadow check to that branch.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Keep --accept-moved from downgrading failures in read-only runs
--verify and --no-fix return before planning, so --accept-moved could
pass a full-SHA pin whose recorded ref is gone without ever finding or
validating a replacement. Only runs that write accept it.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Point invalid-entry diagnostics at the dependency entry's line
The line search matched the first occurrence of the key, which is
usually the workflow's list item, or the prefix of a longer key. Match
the whole quoted mapping key instead.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Look each exact ref up once per run
Repairing a full-SHA pin and reverse lookup can both look up the same
recorded ref by exact name. Cache found and missing answers for the
invocation and coalesce concurrent lookups; failed lookups are retried.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Repair SHA pins to any recorded ref at the commit
v0.2.0 rewrote a full-SHA `uses:` to its recorded ref without proof. Since
#174 the repair requires proof, but only checked semver tags and branches:
a non-semver tag (recorded like a branch) was never normalized.
Repair now looks the recorded ref up by exact name, as the backend resolves
it (tag first), and rewrites only when it names the locked commit. A moved
tag, a branch a tag shadows, or a containing branch is left as a SHA.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Name the re-recorded pin, not another pin of its commit
The --accept-moved re-record line matched pinned entries by repository and
commit, so another workflow's pin of the same commit under a different ref
could be reported as the new recorded ref. Match the finding's own lock
key, kept or rewritten from it.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Attribute moved-tag warnings and advise a step that follows the tag
A --verify warning for a tag that moved ahead of a composite's pin did not
name the composite (no required_by), and a full-SHA pin was told to run
--relock, which never changes a full-SHA `uses:`, so the warning stayed.
Name the parent like other parity findings. Advise a full-SHA pin to point
`uses:` at the tag, or, for a composite's pin, to upgrade the composite.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Select the repository's host before exact ref lookups
LookupRefName, and ResolveRefName through it, read refs on the routing
client instead of the repository's selected host, so on a tenant host
SHA-pin repair crashed. Route it like every other repository method, and
test every exported repository method on a tenant client so a new one
can't skip host selection.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Name the host-routing test for tenant hosts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Keep ref case when locating an invalid entry's line
The diagnostic line lookup lowercased the whole key, so with entries for
owner/repo@V1 and owner/repo@v1 it could cite the wrong one. Compare
canonical pin keys instead (parserlock.ParsePin): owner and repo fold,
refs stay case-sensitive, as everywhere else the lockfile is keyed.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>1 parent 582fee1 commit 8bb4bb6
66 files changed
Lines changed: 3917 additions & 759 deletions
File tree
- cmd/gh-actions-lock
- format
- internal
- ghapi
- httpmock
- lockfile
- pin
- pipeline
- checks
- resolve
- uses
- workflowfile
- test
- integration
- scenarios
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
95 | 96 | | |
96 | 97 | | |
97 | 98 | | |
| 99 | + | |
| 100 | + | |
98 | 101 | | |
99 | 102 | | |
100 | 103 | | |
| |||
211 | 214 | | |
212 | 215 | | |
213 | 216 | | |
214 | | - | |
215 | | - | |
216 | | - | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
217 | 222 | | |
218 | 223 | | |
219 | 224 | | |
| |||
250 | 255 | | |
251 | 256 | | |
252 | 257 | | |
| 258 | + | |
253 | 259 | | |
| 260 | + | |
254 | 261 | | |
255 | 262 | | |
256 | 263 | | |
| |||
314 | 321 | | |
315 | 322 | | |
316 | 323 | | |
317 | | - | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
318 | 327 | | |
319 | 328 | | |
320 | 329 | | |
321 | 330 | | |
322 | 331 | | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
| 332 | + | |
| 333 | + | |
328 | 334 | | |
329 | 335 | | |
330 | 336 | | |
331 | 337 | | |
| 338 | + | |
332 | 339 | | |
333 | 340 | | |
334 | 341 | | |
335 | 342 | | |
336 | | - | |
| 343 | + | |
337 | 344 | | |
338 | 345 | | |
339 | 346 | | |
| |||
1477 | 1484 | | |
1478 | 1485 | | |
1479 | 1486 | | |
| 1487 | + | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
147 | 148 | | |
148 | 149 | | |
149 | 150 | | |
150 | | - | |
| 151 | + | |
151 | 152 | | |
152 | 153 | | |
153 | 154 | | |
| |||
176 | 177 | | |
177 | 178 | | |
178 | 179 | | |
179 | | - | |
| 180 | + | |
180 | 181 | | |
181 | 182 | | |
182 | | - | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
183 | 188 | | |
184 | 189 | | |
185 | 190 | | |
| |||
297 | 302 | | |
298 | 303 | | |
299 | 304 | | |
300 | | - | |
| 305 | + | |
301 | 306 | | |
302 | 307 | | |
303 | 308 | | |
| |||
354 | 359 | | |
355 | 360 | | |
356 | 361 | | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
357 | 365 | | |
358 | 366 | | |
359 | 367 | | |
| |||
383 | 391 | | |
384 | 392 | | |
385 | 393 | | |
386 | | - | |
| 394 | + | |
387 | 395 | | |
388 | 396 | | |
389 | 397 | | |
| |||
425 | 433 | | |
426 | 434 | | |
427 | 435 | | |
428 | | - | |
| 436 | + | |
429 | 437 | | |
430 | 438 | | |
431 | 439 | | |
432 | 440 | | |
433 | | - | |
| 441 | + | |
434 | 442 | | |
435 | 443 | | |
436 | 444 | | |
| |||

0 commit comments