feat(lockfile): migrate parser package from gh-actions-pin - #1
Merged
Conversation
Migrate pkg/lockfile from github/gh-actions-pin (commit 6c98632, branch nodeselector/fix-sha-pin-destruction) into standalone multi-language repository. Layout: - go/pkg/lockfile/ — Go implementation (module github.com/github/actions-lockfile/go) - schema/ — canonical lockfile JSON schema (single source of truth) - testdata/ — shared test fixtures for all language implementations Key decisions: - Schema deduplication via go:generate (no duplicate JSON in Go tree) - Shared testdata at root, symlinked into Go package for test resolution - go 1.19 floor preserved for downstream consumer compatibility - Security-boundary parser (uses.go) preserved byte-for-byte Removes old prototype code (dev/, pkg/) and CLI test fixtures. Source: github/gh-actions-lock@6c98632 Theme: lockfile-migration Status: builds Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nodeselector
force-pushed
the
nodeselector/migrate-lockfile
branch
from
June 7, 2026 19:33
0415a21 to
e22ea5f
Compare
There was a problem hiding this comment.
⚠️ Not ready to approve
The published schema and uses: parsing need small but important correctness/security hardening fixes before the new lockfile contract is relied on by downstream tooling.
Pull request overview
This PR migrates the lockfile parser (and schema) into a standalone, multi-language actions-lockfile repository, restructuring the Go implementation into a go/ submodule and removing the prior CLI/resolver tooling and its workflow fixtures.
Changes:
- Introduces a published JSON Schema (
schema/lockfile-v0.0.1.json) plus Go-embedded schema generation and drift checks. - Adds a Go lockfile parsing library under
go/pkg/lockfile(pins, actionuses:parsing, schema enforcement, and position-aware errors). - Removes the previous CLI-oriented packages (
pkg/pin,pkg/validate,pkg/resolver) and large workflow fixture corpora.
File summaries
| File | Description |
|---|---|
| testdata/workflows/tampered.yml | Removed legacy workflow fixture used by old CLI validation tests. |
| testdata/workflows/sha-pinned.yml | Removed legacy workflow fixture for SHA-pinned action cases. |
| testdata/workflows/path-action.yml | Removed legacy fixture covering path-based action references. |
| testdata/workflows/nested-composite.yml | Removed legacy fixture for composite recursion depth cases. |
| testdata/workflows/mixed.yml | Removed legacy fixture for mixed uses types (local/docker/repo). |
| testdata/workflows/composite.yml | Removed legacy fixture for composite action recursion. |
| testdata/workflows/basic.yml | Removed legacy “basic” workflow fixture. |
| testdata/real-world/vercel-next.js-build_and_test.yml | Removed large real-world workflow corpus fixture. |
| testdata/real-world/cli-cli-deployment.yml | Removed large real-world workflow corpus fixture. |
| testdata/real-world/astral-sh-uv-ci.yml | Removed large real-world workflow corpus fixture. |
| testdata/node_action.yml | Adds a minimal node action fixture for action metadata parsing tests. |
| testdata/composite_action.yml | Adds a minimal composite action fixture for nested uses: parsing tests. |
| schema/lockfile-v0.0.1.json | Adds the published JSON Schema defining the lockfile format. |
| RELEASING.md | Documents tagging/versioning, Go module floor, schema invariants, and dev workflow. |
| README.md | Repositions the repo as a lockfile parser/schema home; updates usage/docs accordingly. |
| Makefile | Simplifies targets to generation, linting, and testing for the Go submodule. |
| LICENSE | Adds MIT license file. |
| pkg/validate/validate.go | Removed old CLI validate command implementation. |
| pkg/validate/validate_test.go | Removed integration tests tied to old CLI pin/validate flow. |
| pkg/resolver/resolver.go | Removed GraphQL resolver used by the old CLI pin/validate workflow. |
| pkg/resolver/resolver_test.go | Removed placeholder resolver test file. |
| pkg/pin/pin.go | Removed old CLI pin command implementation. |
| pkg/lockfile/lockfile.go | Removed old workflow-YAML mutator/dependencies: section implementation. |
| pkg/lockfile/lockfile_test.go | Removed tests targeting the legacy workflow dependencies: section format. |
| pkg/actionmeta/actionmeta_test.go | Removed legacy actionmeta tests (replaced by new package-local tests). |
| go/go.mod | Adds Go submodule definition (go 1.19) and test dependencies. |
| go/go.sum | Adds Go submodule sums for the new library tests. |
| go.mod | Removes root Go module definition (repo now uses a Go submodule). |
| go.sum | Removes root module sum file. |
| go/pkg/lockfile/doc.go | Adds package docs emphasizing parsing as a security boundary. |
| go/pkg/lockfile/lockfile.go | Adds core lockfile parser with version gating, canonicalization, and positioned errors. |
| go/pkg/lockfile/lockfile_test.go | Adds unit tests for version handling, canonicalization, and position reporting. |
| go/pkg/lockfile/schema/lockfile-v0.0.1.json | (Not changed; schema lives at repo root per RELEASING docs.) |
| go/pkg/lockfile/schema.go | Exposes embedded schema via Schema() and hooks codegen. |
| go/pkg/lockfile/schema_gen.go | Generated embedded schema constant for Go consumers. |
| go/pkg/lockfile/schema_test.go | Ensures embedded schema matches root schema and enforcement invariants. |
| go/pkg/lockfile/internal/cmd/genschema/main.go | Implements schema embedding code generator. |
| go/pkg/lockfile/pin.go | Adds canonical pin parsing/canonicalization utilities and digest validation. |
| go/pkg/lockfile/pin_test.go | Adds pin parsing and invalid-input test coverage. |
| go/pkg/lockfile/nwo.go | Adds owner/repo splitting helper for repo-granularity behavior. |
| go/pkg/lockfile/nwo_test.go | Adds tests for SplitNWO behavior and edge cases. |
| go/pkg/lockfile/uses.go | Adds hardened uses: parsing for repository actions vs non-actions. |
| go/pkg/lockfile/uses_test.go | Adds tests for uses: parsing, reusable workflow rejection, and SHA detection. |
| go/pkg/lockfile/version.go | Adds semver-ish parsing utilities for action tag recommendation logic. |
| go/pkg/lockfile/version_test.go | Adds tests for semver parsing/ordering/mutability logic. |
| go/pkg/lockfile/action_meta.go | Moves action metadata parsing into the lockfile package (ParseActionMeta). |
| go/pkg/lockfile/action_meta_test.go | Adds action metadata parsing tests using package-local fixtures. |
| dev/jobmsg/jobmsg.go | Removed legacy runner job message builder tooling. |
| dev/harness-dotnet/Program.cs | Removed legacy .NET runner harness tool. |
| dev/harness-dotnet/Harness.csproj | Removed legacy .NET harness project file. |
| dev/harness-dotnet/.gitignore | Removed legacy harness ignore file. |
| dev/fakelaunch/server.go | Removed legacy fake Launch server used for runner integration demos. |
| .github/workflows/ci.yml | Adds CI to run generate/lint/test across a Go version matrix. |
Copilot's findings
Files not reviewed (2)
- go/pkg/lockfile/internal/cmd/genschema/main.go: Language not supported
- go/pkg/lockfile/schema_gen.go: Language not supported
- Files reviewed: 49/53 changed files
- Comments generated: 4
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
setup-go looks for go.sum at repo root by default; our module lives under go/. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tests - Schema pin regex: enforce sha1=40 / sha256=64 hex digits (was unbounded) - Parse() doc: clarify structural-only validation scope - ParseActionRef: add isValidPath() for subdirectory charset + traversal guards - Rename isValidOwnerOrRepo → isValidSegment (same charset, used for paths too) - Add test: ref containing @ (foo/bar@a@b → ref=a@b) - Add 5 path-rejection test cases (space, quotes, .., ., //) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cies Address staff + distinguished-engineer review feedback on the migrated lockfile parser. Security boundary (uses.go / doc.go): - isValidSegment now rejects whole-segment "." and ".." (not just charset). - Add isValidRef denylist for the @ref: rejects whitespace, quotes, backtick, backslash, and the ".." sequence (git-invalid, zero valid refs lost) so a ref cannot break out of a quoted literal or smuggle a traversal. Refs still contain "/", so downstream must percent-escape. - ParseActionRef gates the ref via isValidRef. Tightened doc.go contract. Breaking API change (lockfile.go): - Rename File.Actions -> File.Dependencies to match the YAML key. The yaml:"dependencies" tag is unchanged, so the on-disk format is stable; only the Go field name changes. Downstream consumers must update field access. Contract accuracy: - Future-version error message is now tool-agnostic (no hardcoded gh-actions-pin upgrade command); ErrFutureVersion sentinel preserved. - schema.go docstring corrected: the pin pattern constrains pin *values* (workflows/uses arrays), not dependencies map keys, so schema validation alone does not guarantee every dependency key is a pin. - SemVer doc notes API stability (kept exported; consumer relies on it). Tests: add 11 boundary-rejection cases (dot segments, quote/space/ backtick/backslash refs, ".." refs); keep foo/bar@a@b valid. Field renames across lockfile_test, schema_test. Skip-on-missing testdata in action_meta_test to match schema_test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Downstream consumers (github/launch detached-lockfiles) must split a
reusable-workflow uses: ref (OWNER/REPO/.github/workflows/<name>.yml@ref)
into (nwo, subpath, ref) to derive that repo's lockfile path. Hand-rolling
the split with a last-`@` scan mis-parses refs that legitimately contain
`@` (e.g. a branch named "release@2024"), yielding a wrong path and a
silent enforcement downgrade. Centralize the split here, where the uses:
grammar and its telemetry-validated validation already live.
- Add exported ReusableWorkflowRef{Owner,Repo,Path,Ref,Raw} + NWO()/FullName()
and ParseReusableWorkflowRef, the mirror of ParseActionRef for the shape
ParseActionRef rejects. Same prefilters, first-`@` split, and security
validation (charset, traversal, ref metacharacters).
- Extract the shared parse into splitUsesRef returning an unexported usesRef
carrier, so ActionRef's "this is a repository action" contract is never
briefly violated by an unclassified value.
- Tighten reusable-workflow classification: isReusableWorkflow now requires a
single YAML file directly under .github/workflows/ (GitHub's actual
grammar); nested paths like .github/workflows/sub/ci.yml are not reusable.
ParseActionRef's rejection is preserved via the broader isWorkflowFile, so
its behavior is unchanged and the two parsers remain mutually exclusive
(locked in by a property test).
- ParseReusableWorkflowRef rejects local (./...) reusable workflows by design;
IsLocalReusableWorkflow covers that shape.
Tests: full coverage for ParseReusableWorkflowRef incl. the ref-with-`@`
bug case, ref-with-`/`, nested rejection, injection/traversal rejection,
and a mutual-exclusion property test across both parsers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
workflow_dispatch Release workflow with a patch/minor/major dropdown that delegates to script/release. The script regenerates + drift-checks the tree, runs the full build, computes the next go/vX.Y.Z from the latest tag, pushes the tag, cuts a GitHub Release, and warms the module proxy. Runnable locally (RELEASE_DRY_RUN=1 to preview). Guards against v2+ tags without a /vN module path. Replaces local-only tagging. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nodeselector
added a commit
that referenced
this pull request
Jul 8, 2026
feat(lockfile): migrate parser package from gh-actions-pin
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.
Repurposing this repo that housed the initial prototype of the CLI for shared library code to support lockfile parsing. Currently limited to go, but we'll need to support at least typescript for actions/languageservices.