Skip to content

Commit a0cb66d

Browse files
CopilotCopilot
andcommitted
Replace hardcoded /opt/gh-aw paths with dynamic GH_AW_HOME expressions
- Add GhAwHome, GhAwHomeJS, GhAwHomeExpr, GhAwHomeExprDefault constants - Add JsRequireGhAw() helper for JS require() expressions - Update SetupActionDestination to use GhAwHomeExpr - Add GhAwHomeDefault constant to pkg/constants - Update DefaultGhAwMount to use shell expansion - Add GH_AW_HOME to job-level env in agent, safe-outputs, conclusion, push_repo_memory, and update_cache_memory jobs - Replace all hardcoded /opt/gh-aw paths in 30+ source files - Update test assertions to match new dynamic path expressions - Fix insertIndex calculation in compiler_safe_outputs_job.go to use hasCustomTokenSafeOutputs() for accurate line counting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8f37359 commit a0cb66d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+214
-171
lines changed

pkg/constants/constants.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,13 @@ const DefaultAlpineImage = "alpine:latest"
435435
// This image is built during workflow execution and includes the gh-aw binary and dependencies
436436
const DevModeGhAwImage = "localhost/gh-aw:dev"
437437

438+
// GhAwHomeDefault is the default value for GH_AW_HOME when the env var is not set
439+
const GhAwHomeDefault = "/opt/gh-aw"
440+
438441
// DefaultGhAwMount is the mount path for the gh-aw directory in containerized MCP servers
439-
// The gh-aw binary and supporting files are mounted read-only from /opt/gh-aw
440-
const DefaultGhAwMount = "/opt/gh-aw:/opt/gh-aw:ro"
442+
// Uses shell expansion so docker gets the resolved path at runtime.
443+
// GH_AW_HOME is always set in the job-level env, so no fallback is needed here.
444+
const DefaultGhAwMount = "\\${GH_AW_HOME}:\\${GH_AW_HOME}:ro"
441445

442446
// DefaultGhBinaryMount is the mount path for the gh CLI binary in containerized MCP servers
443447
// The gh CLI is required for agentic-workflows MCP server to run gh commands

pkg/workflow/agentic_output_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ This workflow tests the agentic output collection functionality.
6262
lockContent := string(content)
6363

6464
// Verify GH_AW_SAFE_OUTPUTS is set at job level with fixed path
65-
if !strings.Contains(lockContent, "GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl") {
66-
t.Error("Expected 'GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl' environment variable in generated workflow")
65+
if !strings.Contains(lockContent, "GH_AW_SAFE_OUTPUTS: "+GhAwHomeExpr+"/safeoutputs/outputs.jsonl") {
66+
t.Error("Expected 'GH_AW_SAFE_OUTPUTS: " + GhAwHomeExpr + "/safeoutputs/outputs.jsonl' environment variable in generated workflow")
6767
}
6868

6969
if !strings.Contains(lockContent, "- name: Ingest agent output") {
@@ -171,8 +171,8 @@ This workflow tests that Codex engine gets GH_AW_SAFE_OUTPUTS but not engine out
171171
lockContent := string(content)
172172

173173
// Verify that Codex workflow DOES have GH_AW_SAFE_OUTPUTS functionality at job level
174-
if !strings.Contains(lockContent, "GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl") {
175-
t.Error("Codex workflow should have 'GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl' environment variable (GH_AW_SAFE_OUTPUTS functionality)")
174+
if !strings.Contains(lockContent, "GH_AW_SAFE_OUTPUTS: "+GhAwHomeExpr+"/safeoutputs/outputs.jsonl") {
175+
t.Error("Codex workflow should have 'GH_AW_SAFE_OUTPUTS: " + GhAwHomeExpr + "/safeoutputs/outputs.jsonl' environment variable (GH_AW_SAFE_OUTPUTS functionality)")
176176
}
177177

178178
if !strings.Contains(lockContent, "- name: Ingest agent output") {

pkg/workflow/agentic_workflow_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ func TestAgenticWorkflowsInstallStepIncludesGHToken(t *testing.T) {
162162
"install step should include command to verify gh-aw installation")
163163

164164
// Verify the binary copy command is present for MCP server containerization
165-
assert.Contains(t, result, "cp \"$GH_AW_BIN\" /opt/gh-aw/gh-aw",
166-
"install step should copy gh-aw binary to /opt/gh-aw for MCP server containerization")
165+
assert.Contains(t, result, "cp \"$GH_AW_BIN\" "+GhAwHome+"/gh-aw",
166+
"install step should copy gh-aw binary to "+GhAwHome+" for MCP server containerization")
167167
}
168168

169169
func TestAgenticWorkflowsInstallStepSkippedWithImport(t *testing.T) {

pkg/workflow/aw_info_tmp_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ This workflow tests that aw_info.json is generated in /tmp directory.
5656
lockStr := string(lockContent)
5757

5858
// Test 1: Verify the step uses the generate_aw_info.cjs module
59-
if !strings.Contains(lockStr, "require('/opt/gh-aw/actions/generate_aw_info.cjs')") {
59+
if !strings.Contains(lockStr, "require("+JsRequireGhAw("actions/generate_aw_info.cjs")+")") {
6060
t.Error("Expected step to require generate_aw_info.cjs module")
6161
}
6262

pkg/workflow/cache.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func generateCacheMemorySteps(builder *strings.Builder, data *WorkflowData) {
360360
if useBackwardCompatiblePaths {
361361
// For single default cache, use the original directory for backward compatibility
362362
builder.WriteString(" - name: Create cache-memory directory\n")
363-
builder.WriteString(" run: bash /opt/gh-aw/actions/create_cache_memory_dir.sh\n")
363+
builder.WriteString(" run: bash " + GhAwHome + "/actions/create_cache_memory_dir.sh\n")
364364
} else {
365365
fmt.Fprintf(builder, " - name: Create cache-memory directory (%s)\n", cache.ID)
366366
builder.WriteString(" run: |\n")
@@ -498,9 +498,9 @@ func generateCacheMemoryValidation(builder *strings.Builder, data *WorkflowData)
498498

499499
// Build validation script
500500
var validationScript strings.Builder
501-
validationScript.WriteString(" const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');\n")
501+
validationScript.WriteString(" const { setupGlobals } = require(" + JsRequireGhAw("actions/setup_globals.cjs") + ");\n")
502502
validationScript.WriteString(" setupGlobals(core, github, context, exec, io);\n")
503-
validationScript.WriteString(" const { validateMemoryFiles } = require('/opt/gh-aw/actions/validate_memory_files.cjs');\n")
503+
validationScript.WriteString(" const { validateMemoryFiles } = require(" + JsRequireGhAw("actions/validate_memory_files.cjs") + ");\n")
504504
fmt.Fprintf(&validationScript, " const allowedExtensions = %s;\n", allowedExtsJSON)
505505
fmt.Fprintf(&validationScript, " const result = validateMemoryFiles('%s', 'cache', allowedExtensions);\n", cacheDir)
506506
validationScript.WriteString(" if (!result.valid) {\n")
@@ -770,9 +770,9 @@ func (c *Compiler) buildUpdateCacheMemoryJob(data *WorkflowData, threatDetection
770770

771771
// Build validation script
772772
var validationScript strings.Builder
773-
validationScript.WriteString(" const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');\n")
773+
validationScript.WriteString(" const { setupGlobals } = require(" + JsRequireGhAw("actions/setup_globals.cjs") + ");\n")
774774
validationScript.WriteString(" setupGlobals(core, github, context, exec, io);\n")
775-
validationScript.WriteString(" const { validateMemoryFiles } = require('/opt/gh-aw/actions/validate_memory_files.cjs');\n")
775+
validationScript.WriteString(" const { validateMemoryFiles } = require(" + JsRequireGhAw("actions/validate_memory_files.cjs") + ");\n")
776776
fmt.Fprintf(&validationScript, " const allowedExtensions = %s;\n", allowedExtsJSON)
777777
fmt.Fprintf(&validationScript, " const result = validateMemoryFiles('%s', 'cache', allowedExtensions);\n", cacheDir)
778778
validationScript.WriteString(" if (!result.valid) {\n")
@@ -844,11 +844,11 @@ func (c *Compiler) buildUpdateCacheMemoryJob(data *WorkflowData, threatDetection
844844
}
845845

846846
// Set GH_AW_WORKFLOW_ID_SANITIZED so cache keys match those used in the agent job
847-
var jobEnv map[string]string
847+
jobEnv := map[string]string{
848+
"GH_AW_HOME": GhAwHomeExprDefault,
849+
}
848850
if data.WorkflowID != "" {
849-
jobEnv = map[string]string{
850-
"GH_AW_WORKFLOW_ID_SANITIZED": SanitizeWorkflowIDForCacheKey(data.WorkflowID),
851-
}
851+
jobEnv["GH_AW_WORKFLOW_ID_SANITIZED"] = SanitizeWorkflowIDForCacheKey(data.WorkflowID)
852852
}
853853

854854
job := &Job{

pkg/workflow/cache_memory_integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ tools:
4242
"uses: actions/cache@",
4343
"key: memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}",
4444
"path: /tmp/gh-aw/cache-memory",
45-
"cat \"/opt/gh-aw/prompts/cache_memory_prompt.md\"",
45+
"cat \"" + GhAwHome + "/prompts/cache_memory_prompt.md\"",
4646
"GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/'",
4747
"GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR",
4848
},

pkg/workflow/codex_engine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func TestCodexEngineRenderMCPConfig(t *testing.T) {
208208
"GH_AW_MCP_CONFIG_EOF",
209209
"",
210210
"# Generate JSON config for MCP gateway",
211-
"cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh",
211+
"cat << GH_AW_MCP_CONFIG_EOF | bash " + GhAwHome + "/actions/start_mcp_gateway.sh",
212212
"{",
213213
"\"mcpServers\": {",
214214
"\"github\": {",

pkg/workflow/compiler_custom_actions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ Test workflow with script mode.
247247
}
248248

249249
// 5. Setup step should have INPUT_DESTINATION environment variable
250-
if !strings.Contains(lockStr, "INPUT_DESTINATION: /opt/gh-aw/actions") {
250+
if !strings.Contains(lockStr, "INPUT_DESTINATION: "+SetupActionDestination) {
251251
t.Error("Expected INPUT_DESTINATION environment variable in setup step for script mode")
252252
}
253253

pkg/workflow/compiler_main_job.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,23 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) (
174174
}
175175
}
176176

177-
// Build job-level environment variables for safe outputs
178-
var env map[string]string
179-
if data.SafeOutputs != nil {
180-
env = make(map[string]string)
177+
// Build job-level environment variables
178+
// Use GhAwHomeExprDefault so callers can override GH_AW_HOME via workflow/repo env
179+
env := map[string]string{
180+
"GH_AW_HOME": GhAwHomeExprDefault,
181+
}
181182

182-
// Set GH_AW_SAFE_OUTPUTS to path in /opt (read-only mount for agent container)
183-
// The MCP server writes agent outputs to this file during execution
184-
// This file is in /opt to prevent the agent container from having write access
185-
env["GH_AW_SAFE_OUTPUTS"] = "/opt/gh-aw/safeoutputs/outputs.jsonl"
183+
if data.SafeOutputs != nil {
184+
// Set GH_AW_SAFE_OUTPUTS and related paths as job-level env vars.
185+
// Using GhAwHomeExpr so paths adapt when GH_AW_HOME is overridden.
186+
env["GH_AW_SAFE_OUTPUTS"] = GhAwHomeExpr + "/safeoutputs/outputs.jsonl"
187+
env["GH_AW_SAFE_OUTPUTS_CONFIG_PATH"] = GhAwHomeExpr + "/safeoutputs/config.json"
188+
env["GH_AW_SAFE_OUTPUTS_TOOLS_PATH"] = GhAwHomeExpr + "/safeoutputs/tools.json"
186189

187190
// Set GH_AW_MCP_LOG_DIR for safe outputs MCP server logging
188191
// Store in mcp-logs directory so it's included in mcp-logs artifact
189192
env["GH_AW_MCP_LOG_DIR"] = "/tmp/gh-aw/mcp-logs/safeoutputs"
190193

191-
// Set config and tools paths (readonly files in /opt/gh-aw)
192-
env["GH_AW_SAFE_OUTPUTS_CONFIG_PATH"] = "/opt/gh-aw/safeoutputs/config.json"
193-
env["GH_AW_SAFE_OUTPUTS_TOOLS_PATH"] = "/opt/gh-aw/safeoutputs/tools.json"
194-
195194
// Add asset-related environment variables
196195
// These must always be set (even to empty) because awmg v0.0.12+ validates ${VAR} references
197196
if data.SafeOutputs.UploadAssets != nil {
@@ -214,9 +213,6 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) (
214213
// This contains the workflow ID with all hyphens removed and lowercased
215214
// Used in cache keys to avoid spaces and special characters
216215
if data.WorkflowID != "" {
217-
if env == nil {
218-
env = make(map[string]string)
219-
}
220216
sanitizedID := SanitizeWorkflowIDForCacheKey(data.WorkflowID)
221217
env["GH_AW_WORKFLOW_ID_SANITIZED"] = sanitizedID
222218
}

pkg/workflow/compiler_safe_outputs_job.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,12 @@ func (c *Compiler) buildConsolidatedSafeOutputsJob(data *WorkflowData, mainJobNa
268268
if len(c.generateCheckoutActionsFolder(data)) > 0 {
269269
insertIndex += 6 // Checkout step (6 lines: name, uses, with, sparse-checkout header, actions, persist-credentials)
270270
}
271-
insertIndex += 4 // Setup step (4 lines: name, uses, with, destination)
271+
enableCustomTokensForInsert := c.hasCustomTokenSafeOutputs(data.SafeOutputs)
272+
if enableCustomTokensForInsert {
273+
insertIndex += 4 // Setup step with custom tokens (4 lines: name, uses, with, safe-output-custom-tokens)
274+
} else {
275+
insertIndex += 2 // Setup step without custom tokens (2 lines: name, uses)
276+
}
272277
}
273278

274279
// Add artifact download steps count
@@ -385,6 +390,10 @@ func (c *Compiler) buildConsolidatedSafeOutputsJob(data *WorkflowData, mainJobNa
385390
func (c *Compiler) buildJobLevelSafeOutputEnvVars(data *WorkflowData, workflowID string) map[string]string {
386391
envVars := make(map[string]string)
387392

393+
// Set GH_AW_HOME so steps can use $GH_AW_HOME without the :-fallback syntax.
394+
// Use GhAwHomeExprDefault so callers can override via workflow/repo env.
395+
envVars["GH_AW_HOME"] = GhAwHomeExprDefault
396+
388397
// Set GH_AW_WORKFLOW_ID to the workflow ID (filename without extension)
389398
// This is used for branch naming in create_pull_request and other operations
390399
envVars["GH_AW_WORKFLOW_ID"] = fmt.Sprintf("%q", workflowID)

0 commit comments

Comments
 (0)