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: 2 additions & 2 deletions docs/src/content/docs/labs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ These are experimental agentic workflows used by the GitHub Next team to learn,
| [Glossary Maintainer](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/glossary-maintainer.md) | copilot | [![Glossary Maintainer](https://github.com/githubnext/gh-aw/actions/workflows/glossary-maintainer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/glossary-maintainer.lock.yml) | `0 10 * * 1-5` | - |
| [Go Fan](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-fan.md) | claude | [![Go Fan](https://github.com/githubnext/gh-aw/actions/workflows/go-fan.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-fan.lock.yml) | `0 7 * * 1-5` | - |
| [Go Logger Enhancement](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-logger.md) | claude | [![Go Logger Enhancement](https://github.com/githubnext/gh-aw/actions/workflows/go-logger.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-logger.lock.yml) | `0 12 * * *` | - |
| [Go Pattern Detector](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-pattern-detector.md) | claude | [![Go Pattern Detector](https://github.com/githubnext/gh-aw/actions/workflows/go-pattern-detector.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-pattern-detector.lock.yml) | - | - |
| [Go Pattern Detector](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-pattern-detector.md) | claude | [![Go Pattern Detector](https://github.com/githubnext/gh-aw/actions/workflows/go-pattern-detector.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-pattern-detector.lock.yml) | `0 14 * * 1-5` | - |
| [Grumpy Code Reviewer 🔥](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/grumpy-reviewer.md) | copilot | [![Grumpy Code Reviewer 🔥](https://github.com/githubnext/gh-aw/actions/workflows/grumpy-reviewer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/grumpy-reviewer.lock.yml) | - | `/grumpy` |
| [Instructions Janitor](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/instructions-janitor.md) | claude | [![Instructions Janitor](https://github.com/githubnext/gh-aw/actions/workflows/instructions-janitor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/instructions-janitor.lock.yml) | `0 9 * * *` | - |
| [Issue Arborist](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/issue-arborist.md) | codex | [![Issue Arborist](https://github.com/githubnext/gh-aw/actions/workflows/issue-arborist.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/issue-arborist.lock.yml) | `0 9 * * *` | - |
Expand Down Expand Up @@ -84,9 +84,9 @@ These are experimental agentic workflows used by the GitHub Next team to learn,
| [Semantic Function Refactoring](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/semantic-function-refactor.md) | claude | [![Semantic Function Refactoring](https://github.com/githubnext/gh-aw/actions/workflows/semantic-function-refactor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/semantic-function-refactor.lock.yml) | `0 8 * * *` | - |
| [Smoke Claude](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-claude.md) | claude | [![Smoke Claude](https://github.com/githubnext/gh-aw/actions/workflows/smoke-claude.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-claude.lock.yml) | `0 0,6,12,18 * * *` | - |
| [Smoke Codex](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-codex.md) | codex | [![Smoke Codex](https://github.com/githubnext/gh-aw/actions/workflows/smoke-codex.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-codex.lock.yml) | `0 0,6,12,18 * * *` | - |
| [Smoke Copilot](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-copilot-playwright.md) | copilot | [![Smoke Copilot](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-playwright.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-playwright.lock.yml) | `0 0,6,12,18 * * *` | - |
| [Smoke Copilot](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-copilot.md) | copilot | [![Smoke Copilot](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot.lock.yml) | `0 0,7,13,19 * * *` | - |
| [Smoke Copilot No Firewall](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-copilot-no-firewall.md) | copilot | [![Smoke Copilot No Firewall](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-no-firewall.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-no-firewall.lock.yml) | `0 0,6,12,18 * * *` | - |
| [Smoke Copilot Playwright](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-copilot-playwright.md) | copilot | [![Smoke Copilot Playwright](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-playwright.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-copilot-playwright.lock.yml) | `0 0,6,12,18 * * *` | - |
| [Smoke Detector - Smoke Test Failure Investigator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-detector.md) | claude | [![Smoke Detector - Smoke Test Failure Investigator](https://github.com/githubnext/gh-aw/actions/workflows/smoke-detector.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-detector.lock.yml) | - | - |
| [Smoke SRT](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-srt.md) | copilot | [![Smoke SRT](https://github.com/githubnext/gh-aw/actions/workflows/smoke-srt.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-srt.lock.yml) | - | - |
| [Smoke SRT Custom Config](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/smoke-srt-custom-config.md) | copilot | [![Smoke SRT Custom Config](https://github.com/githubnext/gh-aw/actions/workflows/smoke-srt-custom-config.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/smoke-srt-custom-config.lock.yml) | - | - |
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ require (
github.com/thlib/go-timezone-local v0.0.7 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.38.0 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
Expand Down
29 changes: 10 additions & 19 deletions pkg/workflow/claude_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,16 @@ func NewClaudeEngine() *ClaudeEngine {
func (e *ClaudeEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep {
claudeLog.Printf("Generating installation steps for Claude engine: workflow=%s", workflowData.Name)

var steps []GitHubActionStep

// Add secret validation step - Claude supports both CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY as fallback
secretValidation := GenerateMultiSecretValidationStep(
[]string{"CLAUDE_CODE_OAUTH_TOKEN", "ANTHROPIC_API_KEY"},
"Claude Code",
"https://githubnext.github.io/gh-aw/reference/engines/#anthropic-claude-code",
)
steps = append(steps, secretValidation)

// Use shared helper for standard npm installation
npmSteps := BuildStandardNpmEngineInstallSteps(
"@anthropic-ai/claude-code",
string(constants.DefaultClaudeCodeVersion),
"Install Claude Code CLI",
"claude",
workflowData,
)
steps = append(steps, npmSteps...)
// Use base installation steps (secret validation + npm install)
steps := GetBaseInstallationSteps(EngineInstallConfig{
Secrets: []string{"CLAUDE_CODE_OAUTH_TOKEN", "ANTHROPIC_API_KEY"},
DocsURL: "https://githubnext.github.io/gh-aw/reference/engines/#anthropic-claude-code",
NpmPackage: "@anthropic-ai/claude-code",
Version: string(constants.DefaultClaudeCodeVersion),
Name: "Claude Code",
CliName: "claude",
InstallStepName: "Install Claude Code CLI",
}, workflowData)

// Check if network permissions are configured (only for Claude engine)
if workflowData.EngineConfig != nil && ShouldEnforceNetworkPermissions(workflowData.NetworkPermissions) {
Expand Down
29 changes: 10 additions & 19 deletions pkg/workflow/codex_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,16 @@ func NewCodexEngine() *CodexEngine {

func (e *CodexEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep {
codexEngineLog.Printf("Generating installation steps for Codex engine: workflow=%s", workflowData.Name)
var steps []GitHubActionStep

// Add secret validation step - Codex supports both CODEX_API_KEY and OPENAI_API_KEY as fallback
secretValidation := GenerateMultiSecretValidationStep(
[]string{"CODEX_API_KEY", "OPENAI_API_KEY"},
"Codex",
"https://githubnext.github.io/gh-aw/reference/engines/#openai-codex",
)
steps = append(steps, secretValidation)

npmSteps := BuildStandardNpmEngineInstallSteps(
"@openai/codex",
string(constants.DefaultCodexVersion),
"Install Codex",
"codex",
workflowData,
)
steps = append(steps, npmSteps...)
return steps

// Use base installation steps (secret validation + npm install)
return GetBaseInstallationSteps(EngineInstallConfig{
Secrets: []string{"CODEX_API_KEY", "OPENAI_API_KEY"},
DocsURL: "https://githubnext.github.io/gh-aw/reference/engines/#openai-codex",
NpmPackage: "@openai/codex",
Version: string(constants.DefaultCodexVersion),
Name: "Codex",
CliName: "codex",
}, workflowData)
}

// GetDeclaredOutputFiles returns the output files that Codex may produce
Expand Down
33 changes: 22 additions & 11 deletions pkg/workflow/copilot_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,27 @@ func (e *CopilotEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHu

var steps []GitHubActionStep

// Add secret validation step with fallback to old secret name for backward compatibility
// Define engine configuration for shared validation
config := EngineInstallConfig{
Secrets: []string{"COPILOT_GITHUB_TOKEN", "COPILOT_CLI_TOKEN"},
DocsURL: "https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default",
NpmPackage: "@github/copilot",
Version: string(constants.DefaultCopilotVersion),
Name: "GitHub Copilot CLI",
CliName: "copilot",
InstallStepName: "Install GitHub Copilot CLI",
}

// Add secret validation step
secretValidation := GenerateMultiSecretValidationStep(
[]string{"COPILOT_GITHUB_TOKEN", "COPILOT_CLI_TOKEN"},
"GitHub Copilot CLI",
"https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default",
config.Secrets,
config.Name,
config.DocsURL,
)
steps = append(steps, secretValidation)

// Determine Copilot version
copilotVersion := string(constants.DefaultCopilotVersion)
copilotVersion := config.Version
if workflowData.EngineConfig != nil && workflowData.EngineConfig.Version != "" {
copilotVersion = workflowData.EngineConfig.Version
}
Expand All @@ -68,20 +79,20 @@ func (e *CopilotEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHu
var npmSteps []GitHubActionStep
if installGlobally {
npmSteps = BuildStandardNpmEngineInstallSteps(
"@github/copilot",
config.NpmPackage,
copilotVersion,
"Install GitHub Copilot CLI",
"copilot",
config.InstallStepName,
config.CliName,
workflowData,
)
} else {
// For SRT: install locally without -g flag
copilotLog.Print("Using local Copilot installation for SRT compatibility")
npmSteps = GenerateNpmInstallStepsWithScope(
"@github/copilot",
config.NpmPackage,
copilotVersion,
"Install GitHub Copilot CLI",
"copilot",
config.InstallStepName,
config.CliName,
true, // Include Node.js setup
false, // Install locally, not globally
)
Expand Down
62 changes: 62 additions & 0 deletions pkg/workflow/engine_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,68 @@ import (

var engineHelpersLog = logger.New("workflow:engine_helpers")

// EngineInstallConfig contains configuration for engine installation steps.
// This struct centralizes the configuration needed to generate the common
// installation steps shared by all engines (secret validation and npm installation).
type EngineInstallConfig struct {
// Secrets is a list of secret names to validate (at least one must be set)
Secrets []string
// DocsURL is the documentation URL shown when secret validation fails
DocsURL string
// NpmPackage is the npm package name (e.g., "@github/copilot")
NpmPackage string
// Version is the default version of the npm package
Version string
// Name is the engine display name for secret validation messages (e.g., "Claude Code")
Name string
// CliName is the CLI name used for cache key prefix (e.g., "copilot")
CliName string
// InstallStepName is the display name for the npm install step (e.g., "Install Claude Code CLI")
InstallStepName string
}

// GetBaseInstallationSteps returns the common installation steps for an engine.
// This includes secret validation and npm package installation steps that are
// shared across all engines.
//
// Parameters:
// - config: Engine-specific configuration for installation
// - workflowData: The workflow data containing engine configuration
//
// Returns:
// - []GitHubActionStep: The base installation steps (secret validation + npm install)
func GetBaseInstallationSteps(config EngineInstallConfig, workflowData *WorkflowData) []GitHubActionStep {
engineHelpersLog.Printf("Generating base installation steps for %s engine: workflow=%s", config.Name, workflowData.Name)

var steps []GitHubActionStep

// Add secret validation step
secretValidation := GenerateMultiSecretValidationStep(
config.Secrets,
config.Name,
config.DocsURL,
)
steps = append(steps, secretValidation)

// Determine step name - use InstallStepName if provided, otherwise default to "Install <Name>"
stepName := config.InstallStepName
if stepName == "" {
stepName = fmt.Sprintf("Install %s", config.Name)
}

// Add npm package installation steps
npmSteps := BuildStandardNpmEngineInstallSteps(
config.NpmPackage,
config.Version,
stepName,
config.CliName,
workflowData,
)
steps = append(steps, npmSteps...)

return steps
}

// ExtractAgentIdentifier extracts the agent identifier (filename without extension) from an agent file path.
// This is used by the Copilot CLI which expects agent identifiers, not full paths.
//
Expand Down
Loading