Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion DEVGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ Examples of valid `<REF>` values:
~/gh-aw/gh-aw compile --gh-aw-ref abc123def456 .github/workflows/my-workflow.md
```

This emits action references of the form `github/gh-aw/actions/setup@<REF>` in the compiled `.lock.yml` files. It is exactly equivalent to passing `--action-mode release --action-tag <REF>` and exists as a single, mnemonic flag for the `gh-aw`-developer workflow.
When a branch or tag name is supplied, the compiler resolves it to its commit SHA at compile time using the GitHub API, so the baked-in ref is immutable. Passing a full 40-character SHA skips the resolution call.

This emits action references of the form `github/gh-aw/actions/setup@<SHA>` in the compiled `.lock.yml` files. It is exactly equivalent to passing `--action-mode release --action-tag <sha>` and exists as a single, mnemonic flag for the `gh-aw`-developer workflow.

**When to use**: Running a downstream workflow against an unreleased branch of `gh-aw` to validate changes before merging. This flag is for developers of `gh-aw` itself; end users should rely on released versions instead.

Expand Down
14 changes: 10 additions & 4 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,16 @@ Examples:
ghAwRef, _ := cmd.Flags().GetString("gh-aw-ref")
if ghAwRef != "" {
// --gh-aw-ref is a convenience alias: emit refs like
// `github/gh-aw/actions/setup@<ref>` so external e2e harnesses can
// test the compiled workflows against a specific gh-aw branch/SHA.
// `github/gh-aw/actions/setup@<sha>` so external e2e harnesses can
// test the compiled workflows against a specific gh-aw revision.
// Resolve branch/tag names to their commit SHA so the baked-in ref
// is immutable and not vulnerable to branch/tag mutation.
resolvedRef, resolveErr := workflow.ResolveGhAwRef(cmd.Context(), ghAwRef)
if resolveErr != nil {
return fmt.Errorf("--gh-aw-ref: %w", resolveErr)
}
actionMode = string(workflow.ActionModeRelease)
actionTag = ghAwRef
actionTag = resolvedRef
}
validate, _ := cmd.Flags().GetBool("validate")
watch, _ := cmd.Flags().GetBool("watch")
Expand Down Expand Up @@ -694,7 +700,7 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all
compileCmd.Flags().String("action-mode", "", "Action script inlining mode (inline, dev, release). Auto-detected if not specified")
compileCmd.Flags().String("action-tag", "", "Override action SHA or tag for actions/setup (overrides action-mode to release). Accepts full SHA or tag name")
compileCmd.Flags().String("actions-repo", "", "Override the external actions repository used in action mode (default: github/gh-aw-actions)")
compileCmd.Flags().String("gh-aw-ref", "", "Compile workflows to reference github/gh-aw at the given branch, tag, or SHA (e.g. main, my-feature, abc123). Convenience alias for --action-mode release --action-tag <ref>. Use this to E2E-test workflows compiled by an external repo against a specific gh-aw revision.")
compileCmd.Flags().String("gh-aw-ref", "", "Compile workflows to reference github/gh-aw at the given branch, tag, or SHA (e.g. main, my-feature, abc123). Branch and tag names are resolved to their commit SHA at compile time so the baked-in ref is immutable. Convenience alias for --action-mode release --action-tag <sha>. Use this to E2E-test workflows compiled by an external repo against a specific gh-aw revision.")
compileCmd.Flags().Bool("validate", false, "Enable GitHub Actions workflow schema validation, container image validation, and action SHA validation")
compileCmd.Flags().BoolP("watch", "w", false, "Watch for changes to workflow files and recompile automatically")
compileCmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")
Expand Down
31 changes: 31 additions & 0 deletions pkg/workflow/action_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,34 @@ func (r *ActionResolver) resolveFromGitHub(ctx context.Context, repo, version st

return sha, nil
}

// ResolveGhAwRef resolves a branch, tag, or SHA ref in the github/gh-aw
// repository to its full 40-character commit SHA.
// If ref is already a valid full SHA it is returned unchanged.
// Otherwise the GitHub API commits endpoint is queried, which accepts
// branch names, tag names, and SHAs.
func ResolveGhAwRef(ctx context.Context, ref string) (string, error) {
if gitutil.IsValidFullSHA(ref) {
resolverLog.Printf("--gh-aw-ref %q is already a full SHA, no resolution needed", ref)
return ref, nil
}
Comment thread
dsyme marked this conversation as resolved.
resolverLog.Printf("Resolving --gh-aw-ref %q to commit SHA via GitHub API", ref)
apiPath := fmt.Sprintf("/repos/github/gh-aw/commits/%s", ref)
callCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
Comment thread
dsyme marked this conversation as resolved.
defer cancel()
cmd := ExecGHContext(callCtx, "api", apiPath, "--jq", ".sha")
output, err := cmd.CombinedOutput()
if err != nil {
msg := strings.TrimSpace(string(output))
if msg != "" {
return "", fmt.Errorf("failed to resolve gh-aw ref %q to SHA: %s: %w", ref, msg, err)
}
return "", fmt.Errorf("failed to resolve gh-aw ref %q to SHA: %w", ref, err)
}
sha := strings.TrimSpace(string(output))
if !gitutil.IsValidFullSHA(sha) {
return "", fmt.Errorf("unexpected response resolving gh-aw ref %q: got %q (expected 40-char hex SHA)", ref, sha)
}
resolverLog.Printf("Resolved --gh-aw-ref %q to commit SHA %s", ref, sha)
return sha, nil
}
Loading