GenerateMultiSecretValidationStep creates a GitHub Actions step that validates at least one of multiple secrets is available. secretNames: slice of secret names to validate (e.g., []string{"CODEX_API_KEY", "OPENAI_API_KEY"}) engineName: the display name of the engine (e.g., "Codex") docsURL: URL to
(secretNames []string, engineName, docsURL string, envOverrides map[string]string)
| 177 | // the overridden expression is used instead of the default "${{ secrets.KEY }}" so the |
| 178 | // validation step checks the user-provided secret reference rather than the default one. |
| 179 | func GenerateMultiSecretValidationStep(secretNames []string, engineName, docsURL string, envOverrides map[string]string) GitHubActionStep { |
| 180 | if len(secretNames) == 0 { |
| 181 | // This is a programming error - engine configurations should always provide secrets |
| 182 | // Log the error and return empty step to avoid breaking compilation |
| 183 | engineHelpersLog.Printf("ERROR: GenerateMultiSecretValidationStep called with empty secretNames for engine %s", engineName) |
| 184 | return GitHubActionStep{} |
| 185 | } |
| 186 | |
| 187 | // Build the step name |
| 188 | stepName := fmt.Sprintf(" - name: Validate %s secret", strings.Join(secretNames, " or ")) |
| 189 | |
| 190 | // Build the command to call the validation script |
| 191 | // The script expects: SECRET_NAME1 [SECRET_NAME2 ...] ENGINE_NAME DOCS_URL |
| 192 | // Use shellJoinArgs to properly escape multi-word engine names and special characters |
| 193 | scriptArgs := append(secretNames, engineName, docsURL) |
| 194 | scriptArgsStr := shellJoinArgs(scriptArgs) |
| 195 | |
| 196 | stepLines := []string{ |
| 197 | stepName, |
| 198 | " id: validate-secret", |
| 199 | " run: bash \"${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh\" " + scriptArgsStr, |
| 200 | " env:", |
| 201 | } |
| 202 | |
| 203 | // Add env section with all secrets. When engine.env provides an override for a key, |
| 204 | // use that expression (e.g. "${{ secrets.MY_ORG_TOKEN }}") so the validation step |
| 205 | // validates the user-supplied secret instead of the default one. |
| 206 | for _, secretName := range secretNames { |
| 207 | expr := fmt.Sprintf("${{ secrets.%s }}", secretName) |
| 208 | if envOverrides != nil { |
| 209 | if override, ok := envOverrides[secretName]; ok { |
| 210 | expr = override |
| 211 | } |
| 212 | } |
| 213 | stepLines = appendEnvVarLine(stepLines, secretName, expr) |
| 214 | } |
| 215 | |
| 216 | return GitHubActionStep(stepLines) |
| 217 | } |
| 218 | |
| 219 | // BuildDefaultSecretValidationStep returns a secret validation step for the given engine |
| 220 | // configuration, or an empty step when a custom command is specified. This consolidates |