feat: move actions-lock.json to .github/workflows/aw-lock.json#25110
feat: move actions-lock.json to .github/workflows/aw-lock.json#25110
Conversation
…w YAML format - Change CacheFileName to aw-lock.yml in .github/workflows/ (was actions-lock.json in .github/aw/) - Add LegacyCacheFileName constant for backward-compat loading - Extend format: version, actions (was entries), containers sections - Add ContainerPinEntry struct for future container pin support - Keep backward compat: Load() falls back to old .github/aw/actions-lock.json - Add MarkDirty() method to force save after legacy load - Add codemod_actions_lock_migration.go: MigrateActionsLockFile() for fix --write - Wire migration into fix_command.go and fix_codemods.go registry - Update update_actions.go, update_command.go, upgrade_command.go references - Update Makefile sync-action-pins to use Go script that converts YAML→JSON - Add scripts/sync-action-pins/main.go for the conversion - Migrate .github/aw/actions-lock.json → .github/workflows/aw-lock.yml - Migrate pkg/workflow/.github/aw/actions-lock.json → pkg/workflow/.github/workflows/aw-lock.yml - Update tests: action_cache_test.go, update_command_test.go, compile_integration_test.go - Update docs and scratchpad references Agent-Logs-Url: https://github.com/github/gh-aw/sessions/14c1b3fc-d16d-42e6-9307-d403b1bf6880 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/14c1b3fc-d16d-42e6-9307-d403b1bf6880 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot keep format in JSON aw-lock.json , not YML |
Per feedback, keep the lock file in JSON format (not YAML). - CacheFileName = "aw-lock.json" (was "aw-lock.yml") - Save/Load use JSON marshaling, new schema has version + actions + containers fields - Convert .github/workflows/aw-lock.yml → aw-lock.json - Convert pkg/workflow/.github/workflows/aw-lock.yml → aw-lock.json - Update all docs, comments, and tests accordingly Agent-Logs-Url: https://github.com/github/gh-aw/sessions/648f89f3-a5e5-4dc2-96c1-aea60ffa8be3 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — reverted to JSON format. The file is now |
There was a problem hiding this comment.
Pull request overview
Moves the action pin cache to a new canonical location (.github/workflows/aw-lock.json), introduces a versioned/extendable JSON schema, and adds migration + tooling updates to keep embedded fallback pins in sync.
Changes:
- Relocates
actions-lock.jsonto.github/workflows/aw-lock.jsonand updates the on-disk schema (version,actions, futurecontainers). - Adds backward-compatible loading + a
fix --writecodemod to migrate legacy caches. - Updates build tooling to regenerate the embedded
pkg/workflow/data/action_pins.jsonfrom the lock file via a Go script.
Show a summary per file
| File | Description |
|---|---|
scripts/sync-action-pins/main.go |
New Go sync tool to generate embedded action_pins.json from aw-lock.json/legacy cache. |
Makefile |
Switches sync-action-pins to run the new Go sync tool. |
pkg/workflow/action_cache.go |
Implements new cache filename/location, versioned schema, container pins scaffold, sorted JSON marshaling, and legacy fallback loading. |
pkg/workflow/action_cache_test.go |
Updates tests for new cache path and schema (actions map). |
pkg/workflow/action_sha_validation_test.go |
Updates expected cache path under .github/workflows/. |
pkg/workflow/.github/workflows/aw-lock.json |
Migrates fixture lock file to new schema (version + actions). |
.github/workflows/aw-lock.json |
Migrates repository lock file to new schema (version + actions). |
pkg/cli/update_actions.go |
Updates action-update logic to prefer new path and recognize legacy path. |
pkg/cli/update_command.go |
Updates user-facing messaging to reference aw-lock.json. |
pkg/cli/update_command_test.go |
Updates tests to read new cache path and assert new JSON keys. |
pkg/cli/upgrade_command.go |
Updates command help text to reference new lock location. |
pkg/cli/fix_command.go |
Runs the migration step during fix --write. |
pkg/cli/fix_codemods.go |
Registers the new actions-lock migration codemod. |
pkg/cli/codemod_actions_lock_migration.go |
New migration implementation for legacy → new cache location/schema. |
pkg/cli/compile_integration_test.go |
Updates integration tests to use new cache filename constant and new path. |
pkg/workflow/compiler_types.go |
Updates comments around action cache creation behavior. |
pkg/workflow/safe_outputs_actions.go |
Updates comments about safe-outputs action input caching location. |
pkg/workflow/data/action_pins.json |
Updates embedded pins JSON content to match regenerated format (e.g., removes descriptions). |
docs/src/content/docs/setup/cli.md |
Updates docs references from actions-lock.json to aw-lock.json. |
docs/src/content/docs/reference/releases.md |
Updates docs references and example commands for new lock file name/location. |
docs/src/content/docs/reference/faq.md |
Updates FAQ wording and paths for the new lock file. |
docs/src/content/docs/reference/compilation-process.md |
Updates compilation/pinning docs to reference new cache file. |
docs/src/content/docs/introduction/architecture.mdx |
Updates architecture diagram label to aw-lock.json. |
scratchpad/layout.md |
Updates scratchpad layout references to the new filename. |
scratchpad/debugging-action-pinning.md |
Updates debugging guide paths to the new cache location. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (5)
pkg/cli/compile_integration_test.go:75
- These test comments and log strings mention
aw-lock.yml, but the cache file isaw-lock.json. Updating these strings will keep the test output and documentation aligned with the actual filename.
This issue also appears on line 1282 of the same file.
}
// Clean up any action cache files created during tests
// Tests may create .github/workflows/aw-lock.yml in the pkg/cli directory
actionCacheDir := filepath.Join(wd, ".github")
if _, err := os.Stat(actionCacheDir); err == nil {
_ = os.RemoveAll(actionCacheDir)
}
pkg/cli/compile_integration_test.go:1293
- The assertions here are correct (they use workflow.CacheFileName), but the surrounding comments and log strings say
aw-lock.ymleven though the file isaw-lock.json. Please update the wording to match the real filename to reduce confusion when reading test failures/logs.
// Verify aw-lock.yml is created at the repository root (.github/workflows/aw-lock.yml)
// NOT at .github/workflows/.github/workflows/aw-lock.yml
expectedLockPath := filepath.Join(setup.tempDir, ".github", "workflows", workflow.CacheFileName)
wrongLockPath := filepath.Join(setup.workflowsDir, ".github", "workflows", workflow.CacheFileName)
// Check if aw-lock.yml exists (it may or may not, depending on whether actions were pinned)
// The important part is that if it exists, it's in the right place
if _, err := os.Stat(expectedLockPath); err == nil {
t.Logf("aw-lock.yml correctly created at repo root: %s", expectedLockPath)
} else if !os.IsNotExist(err) {
t.Fatalf("Failed to check for aw-lock.yml at expected path: %v", err)
}
pkg/workflow/safe_outputs_actions.go:224
- This comment references
aw-lock.yml, but the cache file isaw-lock.json(see workflow.CacheFileName). Please update the extension to avoid confusion.
// Check the ActionCache for previously-fetched inputs before going to the network.
// The cache key uses the original version tag from the `uses:` field (ref.Ref, e.g.
// "v1") which matches the key stored in aw-lock.yml.
if data.ActionCache != nil {
scratchpad/layout.md:387
- This directory tree still shows
aw-lock.jsonunder.github/aw/, but the canonical path is now.github/workflows/aw-lock.json(with.github/aw/actions-lock.jsonas legacy). Please update the tree so it matches the new layout.
.github/
├── agents/ # Custom agent definitions
│ └── test-agent.md
├── aw/ # Workflow configuration
│ └── aw-lock.json
└── workflows/ # Workflow files
├── *.md # Source workflows
scratchpad/debugging-action-pinning.md:381
- These jq commands still reference
.entries, but aw-lock.json now uses.actionsas the top-level map. Please update the filters (and any nearby examples) so they work with the new schema.
Check for unexpected cache entries:
```bash
# List all SHAs with their version tags
jq -r '.entries | to_entries[] | "\(.value.sha) \(.value.version) \(.key)"' .github/workflows/aw-lock.json | sort
# Find duplicate SHAs
jq -r '.entries | to_entries[] | .value.sha' .github/workflows/aw-lock.json | sort | uniq -d
</details>
- **Files reviewed:** 25/25 changed files
- **Comments generated:** 6
pkg/workflow/safe_outputs_actions.go
Outdated
| // Resolution priority (highest wins): | ||
| // 1. Inputs already specified in the frontmatter (config.Inputs != nil) | ||
| // 2. Inputs cached in the ActionCache (actions-lock.json) | ||
| // 2. Inputs cached in the ActionCache (aw-lock.yml) |
There was a problem hiding this comment.
The comments/log strings here refer to aw-lock.yml, but the cache file is aw-lock.json (see workflow.CacheFileName). This should be updated to avoid confusing users and to match the actual on-disk filename.
This issue also appears on line 221 of the same file.
| // 2. Inputs cached in the ActionCache (aw-lock.yml) | |
| // 2. Inputs cached in the ActionCache (aw-lock.json) |
pkg/workflow/compiler_types.go
Outdated
|
|
||
| // Auto-detect git repository root for action cache path resolution | ||
| // This ensures actions-lock.json is created at repo root regardless of CWD | ||
| // This ensures aw-lock.yml is created at repo root regardless of CWD |
There was a problem hiding this comment.
This inline comment says aw-lock.yml, but the action cache file is JSON (aw-lock.json). Please update the filename/extension in the comment to match the new cache location and format.
| // This ensures aw-lock.yml is created at repo root regardless of CWD | |
| // This ensures aw-lock.json is created at repo root regardless of CWD |
scripts/sync-action-pins/main.go
Outdated
| cache := workflow.NewActionCache(".") | ||
| if err := cache.Load(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Warning: failed to load action cache: %v\n", err) | ||
| // Continue with empty cache — action_pins.json will be written empty. |
There was a problem hiding this comment.
If the action cache file is missing, ActionCache.Load() returns nil and cache.Entries stays empty, so this script will overwrite pkg/workflow/data/action_pins.json with an empty entries object without warning. Consider explicitly checking for the presence of either .github/workflows/aw-lock.json or .github/aw/actions-lock.json and skipping (or failing) instead of clobbering the embedded fallback data.
| cache := workflow.NewActionCache(".") | |
| if err := cache.Load(); err != nil { | |
| fmt.Fprintf(os.Stderr, "Warning: failed to load action cache: %v\n", err) | |
| // Continue with empty cache — action_pins.json will be written empty. | |
| sourcePaths := []string{ | |
| ".github/workflows/aw-lock.json", | |
| ".github/aw/actions-lock.json", | |
| } | |
| foundSource := false | |
| for _, path := range sourcePaths { | |
| if _, err := os.Stat(path); err == nil { | |
| foundSource = true | |
| break | |
| } else if !os.IsNotExist(err) { | |
| fmt.Fprintf(os.Stderr, "Error checking %s: %v\n", path, err) | |
| os.Exit(1) | |
| } | |
| } | |
| if !foundSource { | |
| fmt.Fprintf(os.Stderr, "Error: no action cache source file found; expected one of %q or %q\n", sourcePaths[0], sourcePaths[1]) | |
| os.Exit(1) | |
| } | |
| cache := workflow.NewActionCache(".") | |
| if err := cache.Load(); err != nil { | |
| fmt.Fprintf(os.Stderr, "Error: failed to load action cache: %v\n", err) | |
| os.Exit(1) |
| The action cache is stored at `.github/workflows/aw-lock.json`. Examine it for duplicate entries: | ||
|
|
||
| ```bash | ||
| # Pretty-print the cache | ||
| cat .github/aw/actions-lock.json | jq . | ||
| cat .github/workflows/aw-lock.json | jq . | ||
|
|
||
| # Find entries for a specific action | ||
| cat .github/aw/actions-lock.json | jq '.entries | to_entries[] | select(.value.repo == "actions/github-script")' | ||
| cat .github/workflows/aw-lock.json | jq '.entries | to_entries[] | select(.value.repo == "actions/github-script")' | ||
|
|
||
| # Check for duplicate SHAs | ||
| cat .github/aw/actions-lock.json | jq -r '.entries | to_entries[] | "\(.value.sha) \(.key)"' | sort | uniq -d -w 40 | ||
| cat .github/workflows/aw-lock.json | jq -r '.entries | to_entries[] | "\(.value.sha) \(.key)"' | sort | uniq -d -w 40 | ||
| ``` |
There was a problem hiding this comment.
The jq filters still reference .entries, but the new aw-lock.json schema uses top-level actions (and version). These commands should be updated to query .actions so the debugging guide works with the migrated file.
This issue also appears on line 373 of the same file.
See below for a potential fix:
cat .github/workflows/aw-lock.json | jq '.actions | to_entries[] | select(.value.repo == "actions/github-script")'
# Check for duplicate SHAs
cat .github/workflows/aw-lock.json | jq -r '.actions | to_entries[] | "\(.value.sha) \(.key)"' | sort | uniq -d -w 40
scratchpad/layout.md
Outdated
| |------|------|-------------|---------------| | ||
| | `.github/workflows/` | Directory | Workflow definition directory | Contains all `.md` and `.lock.yml` workflow files | | ||
| | `.github/aw/` | Directory | Agentic workflow configuration | Contains `actions-lock.json` and other configs | | ||
| | `.github/aw/` | Directory | Agentic workflow configuration | Contains `aw-lock.json` and other configs | |
There was a problem hiding this comment.
This table/tree still describes aw-lock.json as living under .github/aw/, but the PR moves it to .github/workflows/aw-lock.json (with .github/aw/actions-lock.json only as a legacy path). Please update this layout doc to reflect the new canonical location.
This issue also appears on line 381 of the same file.
| | `.github/aw/` | Directory | Agentic workflow configuration | Contains `aw-lock.json` and other configs | | |
| | `.github/workflows/aw-lock.json` | File | Canonical actions lock file | Primary location for the workflow lock configuration | | |
| | `.github/aw/` | Directory | Agentic workflow configuration | Contains other configs and legacy `.github/aw/actions-lock.json` path | |
| // If the new file already exists, skip migration to avoid overwriting. | ||
| if _, err := os.Stat(newPath); err == nil { | ||
| // Both files exist: warn and remove the legacy file. | ||
| fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage( | ||
| fmt.Sprintf("%s already exists; removing legacy %s", newPath, legacyPath))) | ||
| if err := os.Remove(legacyPath); err != nil { | ||
| return false, fmt.Errorf("removing legacy %s: %w", legacyPath, err) | ||
| } | ||
| return true, nil |
There was a problem hiding this comment.
When the new file already exists, this migration path deletes the legacy file unconditionally. That can lose data if the new file is stale/partial (or created by a newer tool with different contents). Safer options: keep the legacy file and return a warning, or compare/merge contents before deleting, or rename the legacy file to a backup instead of removing it.
| // If the new file already exists, skip migration to avoid overwriting. | |
| if _, err := os.Stat(newPath); err == nil { | |
| // Both files exist: warn and remove the legacy file. | |
| fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage( | |
| fmt.Sprintf("%s already exists; removing legacy %s", newPath, legacyPath))) | |
| if err := os.Remove(legacyPath); err != nil { | |
| return false, fmt.Errorf("removing legacy %s: %w", legacyPath, err) | |
| } | |
| return true, nil | |
| // If the new file already exists, skip migration to avoid overwriting or | |
| // discarding the legacy file without verifying the contents match. | |
| if _, err := os.Stat(newPath); err == nil { | |
| fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage( | |
| fmt.Sprintf("%s already exists; leaving legacy %s in place and skipping migration", newPath, legacyPath))) | |
| return false, nil |
|
@copilot review comments |
…ers, layout doc, safe migration - pkg/workflow/safe_outputs_actions.go: fix two comments still saying 'aw-lock.yml' - pkg/workflow/compiler_types.go: fix comment saying 'aw-lock.yml' - scratchpad/debugging-action-pinning.md: update jq filters from .entries to .actions (x4) - scratchpad/layout.md: update table and directory tree to show aw-lock.json in .github/workflows/ - pkg/cli/codemod_actions_lock_migration.go: when new file already exists, skip migration instead of deleting the legacy file - scripts/sync-action-pins/main.go: fail with error when no source cache file is found (instead of silently writing empty action_pins.json) Agent-Logs-Url: https://github.com/github/gh-aw/sessions/1c9e14dd-0ab3-48a8-8390-a4ce974fd972 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
All review comments addressed in commit
|
Summary
Moves the action pin cache from
.github/aw/actions-lock.jsonto.github/workflows/aw-lock.jsonand extends the schema for future extensibility, keeping the JSON format.Changes
New file format (
aw-lock.json){ "version": "1", "actions": { "actions/checkout@v6.0.2": { "repo": "actions/checkout", "version": "v6.0.2", "sha": "de0fac2e4500dabe0009e67214ff5f5447ce83dd" } } }The new format adds:
versionfield for schema versioningactionssection (wasentriesin the old format)containerssection (new, for future container image pin support)Core changes
pkg/workflow/action_cache.go: New constants (CacheFileName = "aw-lock.json",LegacyCacheFileName = "actions-lock.json"), newContainerPinEntrystruct, JSON marshaling with sorted keys, backward-compatLoad()(falls back to legacy path),MarkDirty()methodpkg/cli/codemod_actions_lock_migration.go: NewMigrateActionsLockFile()that moves and converts the old file to the new location/schema; wired intofix --writeand the codemod registryMakefile: Updatedsync-action-pinsto use a Go script that readsaw-lock.jsonand writes the embeddedaction_pins.jsonfallback (no external tooling required)scripts/sync-action-pins/main.go: New Go script for syncing the action pin dataBackward compatibility
Load()automatically falls back to.github/aw/actions-lock.jsonif the new file doesn't existgh aw fix --writemigrates the old file to the new locationUpdateActionschecks both paths before deciding to skipFiles migrated in this PR
.github/aw/actions-lock.json→.github/workflows/aw-lock.jsonpkg/workflow/.github/aw/actions-lock.json→pkg/workflow/.github/workflows/aw-lock.jsonTests updated
pkg/workflow/action_cache_test.go: new path, JSON format assertionspkg/cli/update_command_test.go: new path, JSON content checkspkg/cli/compile_integration_test.go: new path referencespkg/workflow/action_sha_validation_test.go: new pathDocs updated
All references to
actions-lock.jsonindocs/, scratchpad, and code comments updated toaw-lock.json.