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
2 changes: 0 additions & 2 deletions .github/workflows/issue-classifier.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions .github/workflows/smoke-opencode.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions pkg/workflow/compiler_activation_jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -711,8 +711,20 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) (
// Build job outputs
// Always include model output for reuse in other jobs
outputs := map[string]string{
"model": "${{ steps.generate_aw_info.outputs.model }}",
"secret_verification_result": "${{ steps.validate-secret.outputs.verification_result }}",
"model": "${{ steps.generate_aw_info.outputs.model }}",
}

// Only add secret_verification_result output if the engine adds the validate-secret step
// The validate-secret step is only added by engines that include it in GetInstallationSteps()
engine, err := c.getAgenticEngine(data.AI)
if err != nil {
return nil, fmt.Errorf("failed to get agentic engine: %w", err)
}
if EngineHasValidateSecretStep(engine, data) {
outputs["secret_verification_result"] = "${{ steps.validate-secret.outputs.verification_result }}"
compilerActivationJobsLog.Printf("Added secret_verification_result output (engine includes validate-secret step)")
} else {
compilerActivationJobsLog.Printf("Skipped secret_verification_result output (engine does not include validate-secret step)")
}

// Add safe-output specific outputs if the workflow uses the safe-outputs feature
Expand Down
35 changes: 35 additions & 0 deletions pkg/workflow/engine_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,38 @@ func GetToolBinsEnvArg() []string {
// Pre-wrap in double quotes so shellEscapeArg preserves them (allowing shell expansion)
return []string{"--env", "\"GH_AW_TOOL_BINS=$GH_AW_TOOL_BINS\""}
}

// EngineHasValidateSecretStep checks if the engine's installation steps include the validate-secret step.
// This is used to determine whether the secret_verification_result job output should be added.
//
// The validate-secret step is only added by engines that include it in GetInstallationSteps():
// - Copilot engine: Adds step when GetRequiredSecretNames returns non-empty
// - Claude engine: Adds step when GetRequiredSecretNames returns non-empty
// - Codex engine: Adds step when GetRequiredSecretNames returns non-empty
// - Custom engine: Never adds this step (returns empty from GetInstallationSteps)
//
// Implementation Note:
// This uses simple string matching which is acceptable because:
// - Installation steps are generated by our code, not user input
// - The "id: validate-secret" format is controlled by GenerateMultiSecretValidationStep()
// - GitHubActionStep is already a string slice, not structured YAML
//
// Parameters:
// - engine: The agentic engine to check
// - data: The workflow data (needed for GetInstallationSteps)
//
// Returns:
// - bool: true if the engine includes the validate-secret step, false otherwise
func EngineHasValidateSecretStep(engine CodingAgentEngine, data *WorkflowData) bool {
installSteps := engine.GetInstallationSteps(data)
for _, step := range installSteps {
for _, line := range step {
// String matching is safe here because installation steps are generated by our code
// and follow the format: " id: validate-secret"
if strings.Contains(line, "id: validate-secret") {
return true
}
}
}
return false
}
11 changes: 10 additions & 1 deletion pkg/workflow/notify_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,16 @@ func (c *Compiler) buildConclusionJob(data *WorkflowData, mainJobName string, sa
agentFailureEnvVars = append(agentFailureEnvVars, buildWorkflowMetadataEnvVarsWithTrackerID(data.Name, data.Source, data.TrackerID)...)
agentFailureEnvVars = append(agentFailureEnvVars, " GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n")
agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_AGENT_CONCLUSION: ${{ needs.%s.result }}\n", mainJobName))
agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.%s.outputs.secret_verification_result }}\n", mainJobName))

// Only add secret_verification_result if the engine adds the validate-secret step
// The validate-secret step is only added by engines that include it in GetInstallationSteps()
engine, err := c.getAgenticEngine(data.AI)
if err != nil {
return nil, fmt.Errorf("failed to get agentic engine: %w", err)
}
if EngineHasValidateSecretStep(engine, data) {
agentFailureEnvVars = append(agentFailureEnvVars, fmt.Sprintf(" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.%s.outputs.secret_verification_result }}\n", mainJobName))
}

// Pass assignment error outputs from safe_outputs job if assign-to-agent is configured
if data.SafeOutputs != nil && data.SafeOutputs.AssignToAgent != nil {
Expand Down
Loading