Documentation
¶
Overview ¶
Package lockfile manages CLI lockfile state: loading, saving, and converting the on-disk format.
Index ¶
- Variables
- func CanonicalRef(ref string) string
- func EntryKey(p parserlock.Pin) string
- func RecordsOwnSHA(pin parserlock.Pin, ref string) bool
- func RootUse(refs []parserlock.ActionRef) func(pin parserlock.Pin, commit string) (parserlock.ActionRef, bool)
- func Seedable(d dep.Dependency) bool
- func UsedRoot(refs []parserlock.ActionRef) func(pin parserlock.Pin, commit string) bool
- func UsesCycle(f parserlock.File, workflowKey string) []string
- func ValidEntryRef(pin parserlock.Pin, ref string) bool
- type DirectTracker
- type GraphFault
- type LockedPin
- type MetadataResolver
- type OwnSHAEntry
- type State
- func (s *State) AllDeps() []dep.Dependency
- func (s *State) Closure(workflowKey string, live func(parserlock.Pin, parserlock.Action) bool) []LockedPin
- func (s *State) Descendants(key string) []LockedPin
- func (s *State) Entry(key string) (parserlock.Action, bool)
- func (s *State) File() parserlock.File
- func (s *State) GC()
- func (s *State) Get(workflowKey string) ([]dep.Dependency, error)
- func (s *State) HasWorkflow(workflowKey string) bool
- func (s *State) KeepEdges(workflowKeys []string)
- func (s *State) OriginalVersion() string
- func (s *State) OwnSHAEntries() []OwnSHAEntry
- func (s *State) Preview() *State
- func (s *State) PruneWorkflows(keep map[string]bool, refs ...parserlock.ActionRef) []string
- func (s *State) RecordedRepoID(owner, repo string) int64
- func (s *State) RecordsOwnSHA(owner, repo, sha string) bool
- func (s *State) Save() error
- func (s *State) Set(ctx context.Context, workflowKey string, deps []dep.Dependency, ...) error
- func (s *State) SetEntryRef(key, ref string) error
- func (s *State) SetHostname(hostname string) error
- func (s *State) SetMetadataResolver(meta MetadataResolver)
- func (s *State) UsedBy(key string) []string
- func (s *State) VerifyHosts(ctx context.Context, workflowKeys []string) error
- func (s *State) WorkflowKeys() []string
Constants ¶
This section is empty.
Variables ¶
var ErrCorruptLockfile = errors.New("invalid lockfile")
ErrCorruptLockfile reports that a lockfile exists on disk but its contents can't be used: malformed YAML, unknown fields, a dependency entry missing a required key, or an entry ref the Actions backend wouldn't accept. It is distinct from a missing lockfile (legitimately empty) and from a future-version lockfile (ErrFutureVersion). Loading must never silently discard such a lockfile and overwrite it. Match it with errors.Is; the error text names the actual problem instead.
Functions ¶
func CanonicalRef ¶ added in v0.3.0
CanonicalRef spells a full commit SHA in lowercase and returns any other ref unchanged. The Actions backend matches a `uses:` ref to its lockfile key exactly, so a full SHA has one spelling in both.
func EntryKey ¶ added in v0.3.0
func EntryKey(p parserlock.Pin) string
EntryKey is a pin's on-disk key.
func RecordsOwnSHA ¶ added in v0.3.0
func RecordsOwnSHA(pin parserlock.Pin, ref string) bool
RecordsOwnSHA reports whether a full-SHA key's entry records that same SHA as its ref. The Actions backend rejects it, but a run can re-record the tag or branch the commit came from, so such an entry loads instead of failing the lockfile. It stays recorded and tracked; only ref seeding (Seedable) and parity's ref lookup skip it.
func RootUse ¶ added in v0.3.0
func RootUse(refs []parserlock.ActionRef) func(pin parserlock.Pin, commit string) (parserlock.ActionRef, bool)
RootUse returns the lookup of the use in refs, a workflow's current `uses:`, that still uses a recorded root: the use naming its key, else one naming its commit as a full SHA, since rewriting `uses:` to the commit keeps the tag-keyed entry. SHAs compare case-insensitively; other refs are case-sensitive. commit is the entry's algo-hex commit.
func Seedable ¶ added in v0.3.0
func Seedable(d dep.Dependency) bool
Seedable reports whether a recorded dependency (from Get or AllDeps) may seed ref resolution or branch hints. One whose entry records its own SHA names no tag or branch, so it is resolved afresh; its host and repository identity still bind.
func UsedRoot ¶ added in v0.3.0
func UsedRoot(refs []parserlock.ActionRef) func(pin parserlock.Pin, commit string) bool
UsedRoot returns the test for whether a workflow's recorded root is still used by refs, the workflow's current `uses:` (see RootUse).
func UsesCycle ¶ added in v0.3.0
func UsesCycle(f parserlock.File, workflowKey string) []string
UsesCycle returns a `uses:` cycle in workflowKey's recorded closure, as the keys along it with the first repeated last, or nil. The lockfile parser rejects any cycle, so a write must check for one first.
func ValidEntryRef ¶ added in v0.3.0
func ValidEntryRef(pin parserlock.Pin, ref string) bool
ValidEntryRef reports whether ref is a lock entry ref the Actions backend resolver accepts for pin: a short tag or branch name it accepts (never a SHA, a refs/ name, revision syntax like main~1, or a `git describe` name), and the key's own ref unless the key is a full SHA. The resolver looks it up as refs/tags/<ref>, then refs/heads/<ref>, and requires the locked commit in its history.
Types ¶
type DirectTracker ¶
type DirectTracker struct {
// contains filtered or unexported fields
}
DirectTracker captures, by dep index, which resolved deps correspond to a workflow's direct uses: refs. Build it from the freshly resolved deps (before any narrowing/normalization mutates dep.Ref), then read the final NWO@Ref direct-key set back with Keys after mutation.
Keys takes the (possibly reassigned) deps slice so callers that swap the slice for an index-aligned copy — e.g. PreserveRefs — still resolve to the post-mutation refs. The index alignment is the contract: every transform between NewDirectTracker and Keys must preserve dep order and length.
Directness is determined by the workflow file's own uses: refs, not by the resolver parent map. A dep that is both a direct use and a composite transitive dep (e.g. actions/setup-go used directly and also pulled in by a composite) has a parent in the parent map but must still be recorded as a workflow-direct pin — otherwise it is perpetually re-flagged as not-pinned.
func NewDirectTracker ¶
func NewDirectTracker(refs []parserlock.ActionRef, deps []dep.Dependency) DirectTracker
NewDirectTracker records which entries of deps match one of the workflow's direct refs, by NWO@Ref, at the deps' current (pre-mutation) refs.
func (DirectTracker) IsDirect ¶ added in v0.0.14
func (t DirectTracker) IsDirect(i int) bool
IsDirect reports whether the dep at index i is a workflow-direct use. Out-of-range indices are treated as transitive (false) so callers can gate ref-rewriting on directness without bounds-checking.
func (DirectTracker) Keys ¶
func (t DirectTracker) Keys(deps []dep.Dependency) map[string]bool
Keys returns the set of workflow-direct NWO@Ref keys, reading each dep's current (post-mutation) Key() from the supplied index-aligned slice.
type GraphFault ¶ added in v0.3.0
GraphFault is a recorded edge whose Child has no dependencies entry. Parent is empty for an edge from the workflow itself. The lockfile parser rejects cycles, so a loaded graph has none to report.
func GraphFaults ¶ added in v0.3.0
func GraphFaults(f parserlock.File, workflowKey string, live func(parserlock.Pin, parserlock.Action) bool) []GraphFault
GraphFaults reports the edges of workflowKey's recorded closure, rooted at the pins live accepts, whose child has no entry.
func (GraphFault) String ¶ added in v0.3.0
func (g GraphFault) String() string
type LockedPin ¶ added in v0.2.0
type LockedPin struct {
Pin parserlock.Pin
Action parserlock.Action
// Parent is the canonical key of the composite action that pulls this
// pin in; empty for the workflow's direct pins.
Parent string
}
LockedPin is one entry in a workflow's recorded closure.
type MetadataResolver ¶
type MetadataResolver interface {
RepoIDs(ctx context.Context, hostname, owner, repo string) (ownerID, repoID int64, err error)
}
MetadataResolver fetches the owner/repo numeric IDs for a NWO. The store needs these to populate the dependencies: section on every write.
type OwnSHAEntry ¶ added in v0.3.0
OwnSHAEntry is an entry that records its own SHA as its ref, with the workflows that list it directly and the entries whose `uses:` reach it, both sorted. An entry with neither is an orphan the next Save drops.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State wraps the on-disk dependency lockfile for the current invocation. Save garbage-collects orphan dependencies: entries — entries still referenced by an out-of-scope workflow are preserved, so partial invocations (e.g. `upgrade workflows/foo.yml`) stay noop on unrelated workflows.
State is safe for concurrent use: Set/Save/Get/File/AllDeps/lookupIDs all take the same mutex, allowing parallel pin and upgrade workers to share a single store instance without external synchronization.
func LoadState ¶
func LoadState(repoRoot string, meta MetadataResolver) (*State, error)
LoadState reads the lockfile at repoRoot, returning an empty in-memory file when none exists on disk. A lockfile that exists but cannot be parsed is surfaced as ErrCorruptLockfile rather than being silently treated as empty.
func LoadStateAt ¶
func LoadStateAt(lockfilePath string, meta MetadataResolver) (*State, error)
LoadStateAt reads the lockfile at the given path, returning an empty in-memory file when none exists on disk. Use this when the lockfile lives outside the standard .github/workflows/ location.
func (*State) AllDeps ¶
func (s *State) AllDeps() []dep.Dependency
AllDeps returns every action entry in the lockfile as a Dependency, populated with Tag and Branch inferred from the action's ref field. Order is undefined. Intended for callers that need the union of recorded pins across all workflows (e.g. seeding resolver caches on startup); filter ref seeding with Seedable.
func (*State) Closure ¶ added in v0.2.0
func (s *State) Closure(workflowKey string, live func(parserlock.Pin, parserlock.Action) bool) []LockedPin
Closure returns the workflow's recorded pins, direct and transitive, by walking the `uses:` list of each direct pin that live accepts. Stale roots are skipped so their children are not reported. Each pin appears once; a pin the workflow uses directly is always reported as direct (no Parent), even when a composite also uses it.
func (*State) Descendants ¶ added in v0.3.0
Descendants returns the recorded entries below the entry stored under key, each with the entry whose `uses:` reached it as Parent. A write that keeps the entry keeps them too.
func (*State) Entry ¶ added in v0.3.0
func (s *State) Entry(key string) (parserlock.Action, bool)
Entry returns the action recorded under an on-disk key.
func (*State) File ¶
func (s *State) File() parserlock.File
File returns the in-memory parser-level lockfile snapshot. Intended for consumers that drive the workflow-parser diagnostics engine directly and need the whole file (workflow keys + actions metadata) in one shot.
func (*State) GC ¶ added in v0.3.0
func (s *State) GC()
GC drops entries no workflow reaches, as Save does.
func (*State) Get ¶
func (s *State) Get(workflowKey string) ([]dep.Dependency, error)
Get returns the dependencies recorded for workflowKey (e.g. ".github/workflows/ci.yml"). Returns nil when the workflow has no entry.
func (*State) HasWorkflow ¶
HasWorkflow reports whether the lockfile's workflows{} map already contains an entry for workflowKey. Used by `upgrade --no-onboard` to refuse silently onboarding a previously-untracked workflow during a Dependabot run.
func (*State) KeepEdges ¶ added in v0.3.0
KeepEdges makes Set keep the recorded edges of every entry the recorded closures of workflowKeys reach. Call it with the workflows a run doesn't write: a manifest read covers only the sub-actions this run uses, and those workflows may use others of the same entry.
func (*State) OriginalVersion ¶ added in v0.1.0
OriginalVersion returns the version string that was on disk before the lockfile was loaded and migrated. Empty when the file did not exist.
func (*State) OwnSHAEntries ¶ added in v0.3.0
func (s *State) OwnSHAEntries() []OwnSHAEntry
OwnSHAEntries returns every entry that records its own SHA as its ref, sorted by key.
func (*State) Preview ¶ added in v0.3.0
Preview returns an in-memory copy of s for computing what a write would leave on disk. It never reaches the network or the file: an owner/repo ID missing from s's cache gets a placeholder in the preview's own cache, and Save refuses. So a preview matches the real write in its keys, refs, commits, edges and workflow lists, which no ID decides, but not in its IDs. Writes to the preview leave s alone.
func (*State) PruneWorkflows ¶ added in v0.1.6
PruneWorkflows removes every workflow entry whose key is not in keep and returns the removed keys in sorted order. Orphaned dependencies are removed from memory too, so they cannot seed caches or block identity verification. refs preserves pins still used by newly added or renamed workflows.
Callers must only pass a keep set derived from a full-directory scan. A partial invocation (an explicit subset of workflow paths) has no authority to decide a workflow is deleted and must not call this.
func (*State) RecordedRepoID ¶ added in v0.2.0
RecordedRepoID returns the repo ID recorded for owner/repo, or 0. It never hits the network.
func (*State) RecordsOwnSHA ¶ added in v0.3.0
RecordsOwnSHA reports whether the lockfile's entry for owner/repo@sha records that SHA as its ref (see the RecordsOwnSHA function).
func (*State) Save ¶
Save persists the lockfile to disk, garbage-collecting orphan action entries (pins referenced by no workflow). When the in-memory file is empty after GC, the on-disk file is removed.
func (*State) Set ¶
func (s *State) Set(ctx context.Context, workflowKey string, deps []dep.Dependency, parentMap map[string][]string, directKeys map[string]bool) error
Set replaces the workflow's direct-dependency entry and upserts the per-action metadata for every pin in the resolved closure. The workflow entry holds only the action refs that appear in the workflow file itself (its direct uses); per-action `uses:` lists encode the transitive graph, so a reader walks from each direct pin to reconstruct the full closure — the npm/cargo lockfile model.
parentMap is the resolver's child → []parent map (Dependency.Key() form: NWO@Ref, without the SHA suffix), as returned by Resolver.ParentMap. Set uses it to build per-action `uses:` lists by inversion. Both sides are translated into canonical pin keys (NWO@Ref:algo-hex). A dep whose manifest this run read gets the edges it found; one taken from the lockfile unread keeps its recorded edges (see admitUses).
directKeys is the set of Dependency.Key() values (NWO@Ref) that the workflow file uses directly. It is authoritative for the workflow's direct-pin list: a dep is recorded as workflow-direct iff its key is in directKeys. This correctly handles deps that are both a direct use and a composite-transitive dep (e.g. actions/setup-go used directly and also pulled in by a composite) — such a dep has a parent in parentMap but must still appear in the workflow's direct list. When directKeys is nil, Set falls back to treating any dep with no parent in parentMap as direct.
Resolution of owner/repo numeric IDs happens lazily per NWO and is cached for the lifetime of the store.
func (*State) SetEntryRef ¶ added in v0.3.0
SetEntryRef records ref for the existing entry key, which must be one the Actions backend accepts.
func (*State) SetHostname ¶ added in v0.2.0
SetHostname binds omitted v0.0.3 hostnames to the invocation's home host. Legacy pins retain the SDK's explicit github.com binding.
func (*State) SetMetadataResolver ¶ added in v0.1.0
func (s *State) SetMetadataResolver(meta MetadataResolver)
SetMetadataResolver sets the resolver used by lookupIDs to fetch owner/repo numeric IDs. This allows loading the lockfile before auth is available, then wiring in the resolver once the API client is ready.
func (*State) UsedBy ¶ added in v0.3.0
UsedBy returns the keys of the entries whose recorded `uses:` lists key, sorted.
func (*State) VerifyHosts ¶ added in v0.2.0
VerifyHosts confirms that the pins reachable from workflowKeys can be looked up on their recorded host before they are trusted on Proxima. Older producers used omission for dotcom, not the home tenant. Only inconclusive lookups fail here; a missing repository or a changed repo ID is left to the parity pass, which reports repo-unavailable or repo-replaced.
func (*State) WorkflowKeys ¶ added in v0.1.6
WorkflowKeys returns the workflow paths currently recorded in the lockfile's workflows{} map. Order is undefined. Intended for callers that need to reconcile the recorded set against the workflows present on disk.