GetExecutionSteps returns the GitHub Actions steps for executing Antigravity
(workflowData *WorkflowData, logFile string)
| 151 | |
| 152 | // GetExecutionSteps returns the GitHub Actions steps for executing Antigravity |
| 153 | func (e *AntigravityEngine) GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep { |
| 154 | antigravityLog.Printf("Generating execution steps for Antigravity engine: workflow=%s, firewall=%v", workflowData.Name, isFirewallEnabled(workflowData)) |
| 155 | |
| 156 | var steps []GitHubActionStep |
| 157 | |
| 158 | // Write .antigravity/settings.json with context.includeDirectories and tools.core. |
| 159 | // This step runs after the MCP gateway setup (which may have written mcpServers config) |
| 160 | // and merges the context/tools settings into any existing settings.json. |
| 161 | settingsStep := e.generateAntigravitySettingsStep(workflowData) |
| 162 | steps = append(steps, settingsStep) |
| 163 | |
| 164 | // Build agy CLI arguments based on configuration |
| 165 | var agyArgs []string |
| 166 | |
| 167 | // Model is passed via the native ANTIGRAVITY_MODEL environment variable only when explicitly |
| 168 | // configured. When not configured, the Antigravity CLI uses its built-in default model. |
| 169 | // This avoids embedding the value directly in the shell command (which fails template injection |
| 170 | // validation for GitHub Actions expressions like ${{ inputs.model }}). |
| 171 | modelConfigured := workflowData.EngineConfig != nil && workflowData.EngineConfig.Model != "" |
| 172 | |
| 173 | // Antigravity CLI reads MCP config from .antigravity/settings.json (project-level) |
| 174 | // The conversion script (convert_gateway_config_antigravity.sh) writes settings.json |
| 175 | // during the MCP setup step, so no --mcp-config flag is needed here. |
| 176 | |
| 177 | // Auto-approve all tool executions so non-interactive CI runs don't block on permission prompts. |
| 178 | // agy does not support the Gemini-style --yolo/--skip-trust flags. |
| 179 | // This flag grants broad tool permission inside the workflow sandbox, so it is only used in AWF-managed runs. |
| 180 | agyArgs = append(agyArgs, "--dangerously-skip-permissions") |
| 181 | |
| 182 | // Note: the --prompt argument is appended raw after shellJoinArgs below because it contains |
| 183 | // a shell command substitution ("$(cat ...)") that must NOT go through shellEscapeArg — |
| 184 | // single-quoting it would prevent shell expansion at runtime. |
| 185 | |
| 186 | // Build the command |
| 187 | commandName := "agy" |
| 188 | if workflowData.EngineConfig != nil && workflowData.EngineConfig.Command != "" { |
| 189 | commandName = workflowData.EngineConfig.Command |
| 190 | } |
| 191 | |
| 192 | // Append the prompt arg raw (not through shellJoinArgs) to preserve shell expansion |
| 193 | agyCommand := fmt.Sprintf(`%s %s --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"`, commandName, shellJoinArgs(agyArgs)) |
| 194 | agyCommand = getWorkspaceCommandPrefixFor(workflowData.EngineConfig) + agyCommand |
| 195 | |
| 196 | // Build the full command with AWF wrapping if enabled |
| 197 | var command string |
| 198 | firewallEnabled := isFirewallEnabled(workflowData) |
| 199 | if firewallEnabled { |
| 200 | // Get allowed domains: prefer the pre-warmed cache on WorkflowData to avoid |
| 201 | // re-running the expensive map+sort operation. |
| 202 | var allowedDomains string |
| 203 | if workflowData.CachedAllowedDomainsComputed { |
| 204 | allowedDomains = workflowData.CachedAllowedDomainsStr |
| 205 | } else { |
| 206 | allowedDomains = GetAllowedDomainsForEngine(constants.AntigravityEngine, |
| 207 | workflowData.NetworkPermissions, |
| 208 | workflowData.Tools, |
| 209 | workflowData.Runtimes, |
| 210 | ) |