Smoke Codex #63
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # ___ _ _ | |
| # / _ \ | | (_) | |
| # | |_| | __ _ ___ _ __ | |_ _ ___ | |
| # | _ |/ _` |/ _ \ '_ \| __| |/ __| | |
| # | | | | (_| | __/ | | | |_| | (__ | |
| # \_| |_/\__, |\___|_| |_|\__|_|\___| | |
| # __/ | | |
| # _ _ |___/ | |
| # | | | | / _| | | |
| # | | | | ___ _ __ _ __| |_| | _____ ____ | |
| # | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| | |
| # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ | |
| # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ | |
| # | |
| # This file was automatically generated by gh-aw (v0.42.13). DO NOT EDIT. | |
| # | |
| # To update this file, edit the corresponding .md file and run: | |
| # gh aw compile | |
| # For more information: https://github.com/github/gh-aw/blob/main/.github/aw/github-agentic-workflows.md | |
| # | |
| # Smoke test workflow that validates Codex engine functionality by reviewing recent PRs twice daily | |
| # | |
| # Resolved workflow manifest: | |
| # Imports: | |
| # - shared/gh.md | |
| # | |
| # frontmatter-hash: ab168558895776531acc7937557997fba60a9dfebea0c0b3632a7dccdf3d8b61 | |
| name: "Smoke Codex" | |
| "on": | |
| pull_request: | |
| # names: # Label filtering applied via job conditions | |
| # - smoke # Label filtering applied via job conditions | |
| types: | |
| - labeled | |
| schedule: | |
| - cron: "2 */12 * * *" | |
| workflow_dispatch: null | |
| permissions: {} | |
| concurrency: | |
| group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" | |
| cancel-in-progress: true | |
| run-name: "Smoke Codex" | |
| jobs: | |
| activation: | |
| needs: pre_activation | |
| if: > | |
| (needs.pre_activation.outputs.activated == 'true') && (((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && | |
| ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke')))) | |
| runs-on: ubuntu-slim | |
| permissions: | |
| contents: read | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| outputs: | |
| comment_id: ${{ steps.add-comment.outputs.comment-id }} | |
| comment_repo: ${{ steps.add-comment.outputs.comment-repo }} | |
| comment_url: ${{ steps.add-comment.outputs.comment-url }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Check workflow file timestamps | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_WORKFLOW_FILE: "smoke-codex.lock.yml" | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); | |
| await main(); | |
| - name: Add comment with workflow run link | |
| id: add-comment | |
| if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e ๐ฎ *The oracle has spoken through [{workflow_name}]({run_url})*\",\"runStarted\":\"๐ฎ The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"โจ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. ๐\",\"runFailure\":\"๐ The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/add_workflow_run_comment.cjs'); | |
| await main(); | |
| agent: | |
| needs: activation | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: read | |
| pull-requests: read | |
| env: | |
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | |
| GH_AW_ASSETS_ALLOWED_EXTS: "" | |
| GH_AW_ASSETS_BRANCH: "" | |
| GH_AW_ASSETS_MAX_SIZE_KB: 0 | |
| GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs | |
| GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl | |
| GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json | |
| GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json | |
| outputs: | |
| checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} | |
| has_patch: ${{ steps.collect_output.outputs.has_patch }} | |
| model: ${{ steps.generate_aw_info.outputs.model }} | |
| output: ${{ steps.collect_output.outputs.output }} | |
| output_types: ${{ steps.collect_output.outputs.output_types }} | |
| secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Checkout .github and .agents folders | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 | |
| with: | |
| sparse-checkout: | | |
| .github | |
| .agents | |
| depth: 1 | |
| persist-credentials: false | |
| - name: Create gh-aw temp directory | |
| run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh | |
| # Cache memory file share configuration from frontmatter processed below | |
| - name: Create cache-memory directory | |
| run: bash /opt/gh-aw/actions/create_cache_memory_dir.sh | |
| - name: Restore cache-memory file share data | |
| uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 | |
| with: | |
| key: memory-${{ github.workflow }}-${{ github.run_id }} | |
| path: /tmp/gh-aw/cache-memory | |
| restore-keys: | | |
| memory-${{ github.workflow }}- | |
| memory- | |
| - name: Configure Git credentials | |
| env: | |
| REPO_NAME: ${{ github.repository }} | |
| SERVER_URL: ${{ github.server_url }} | |
| run: | | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| # Re-authenticate git with GitHub token | |
| SERVER_URL_STRIPPED="${SERVER_URL#https://}" | |
| git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" | |
| echo "Git configured with standard GitHub Actions identity" | |
| - name: Checkout PR branch | |
| id: checkout-pr | |
| if: | | |
| github.event.pull_request | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); | |
| await main(); | |
| - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret | |
| id: validate-secret | |
| run: /opt/gh-aw/actions/validate_multi_secret.sh CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex | |
| env: | |
| CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 | |
| with: | |
| node-version: '24' | |
| package-manager-cache: false | |
| - name: Install Codex | |
| run: npm install -g --silent @openai/codex@0.98.0 | |
| - name: Install awf binary | |
| run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.13.12 | |
| - name: Determine automatic lockdown mode for GitHub MCP server | |
| id: determine-automatic-lockdown | |
| env: | |
| TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} | |
| if: env.TOKEN_CHECK != '' | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 | |
| with: | |
| script: | | |
| const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); | |
| await determineAutomaticLockdown(github, context, core); | |
| - name: Download container images | |
| run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.13.12 ghcr.io/github/gh-aw-firewall/squid:0.13.12 ghcr.io/github/gh-aw-mcpg:v0.0.103 ghcr.io/github/github-mcp-server:v0.30.3 ghcr.io/github/serena-mcp-server:latest mcr.microsoft.com/playwright/mcp node:lts-alpine | |
| - name: Write Safe Outputs Config | |
| run: | | |
| mkdir -p /opt/gh-aw/safeoutputs | |
| mkdir -p /tmp/gh-aw/safeoutputs | |
| mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs | |
| cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' | |
| {"add_comment":{"max":1},"add_labels":{"allowed":["smoke-codex"],"max":3},"create_issue":{"expires":2,"max":1},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1}} | |
| EOF | |
| cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' | |
| [ | |
| { | |
| "description": "Create a new GitHub issue for tracking bugs, feature requests, or tasks. Use this for actionable work items that need assignment, labeling, and status tracking. For reports, announcements, or status updates that don't require task tracking, use create_discussion instead. CONSTRAINTS: Maximum 1 issue(s) can be created.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "body": { | |
| "description": "Detailed issue description in Markdown. Do NOT repeat the title as a heading since it already appears as the issue's h1. Include context, reproduction steps, or acceptance criteria as appropriate.", | |
| "type": "string" | |
| }, | |
| "labels": { | |
| "description": "Labels to categorize the issue (e.g., 'bug', 'enhancement'). Labels must exist in the repository.", | |
| "items": { | |
| "type": "string" | |
| }, | |
| "type": "array" | |
| }, | |
| "parent": { | |
| "description": "Parent issue number for creating sub-issues. This is the numeric ID from the GitHub URL (e.g., 42 in github.com/owner/repo/issues/42). Can also be a temporary_id (e.g., 'aw_abc123def456') from a previously created issue in the same workflow run.", | |
| "type": [ | |
| "number", | |
| "string" | |
| ] | |
| }, | |
| "temporary_id": { | |
| "description": "Unique temporary identifier for referencing this issue before it's created. Format: 'aw_' followed by 12 hex characters (e.g., 'aw_abc123def456'). Use '#aw_ID' in body text to reference other issues by their temporary_id; these are replaced with actual issue numbers after creation.", | |
| "type": "string" | |
| }, | |
| "title": { | |
| "description": "Concise issue title summarizing the bug, feature, or task. The title appears as the main heading, so keep it brief and descriptive.", | |
| "type": "string" | |
| } | |
| }, | |
| "required": [ | |
| "title", | |
| "body" | |
| ], | |
| "type": "object" | |
| }, | |
| "name": "create_issue" | |
| }, | |
| { | |
| "description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. CONSTRAINTS: Maximum 1 comment(s) can be added.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "body": { | |
| "description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation.", | |
| "type": "string" | |
| }, | |
| "item_number": { | |
| "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", | |
| "type": "number" | |
| } | |
| }, | |
| "required": [ | |
| "body" | |
| ], | |
| "type": "object" | |
| }, | |
| "name": "add_comment" | |
| }, | |
| { | |
| "description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Only these labels are allowed: [smoke-codex].", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "item_number": { | |
| "description": "Issue or PR number to add labels to. This is the numeric ID from the GitHub URL (e.g., 456 in github.com/owner/repo/issues/456). If omitted, adds labels to the item that triggered this workflow.", | |
| "type": "number" | |
| }, | |
| "labels": { | |
| "description": "Label names to add (e.g., ['bug', 'priority-high']). Labels must exist in the repository.", | |
| "items": { | |
| "type": "string" | |
| }, | |
| "type": "array" | |
| } | |
| }, | |
| "type": "object" | |
| }, | |
| "name": "add_labels" | |
| }, | |
| { | |
| "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "alternatives": { | |
| "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", | |
| "type": "string" | |
| }, | |
| "reason": { | |
| "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", | |
| "type": "string" | |
| }, | |
| "tool": { | |
| "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", | |
| "type": "string" | |
| } | |
| }, | |
| "required": [ | |
| "reason" | |
| ], | |
| "type": "object" | |
| }, | |
| "name": "missing_tool" | |
| }, | |
| { | |
| "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "message": { | |
| "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", | |
| "type": "string" | |
| } | |
| }, | |
| "required": [ | |
| "message" | |
| ], | |
| "type": "object" | |
| }, | |
| "name": "noop" | |
| }, | |
| { | |
| "description": "Hide a comment on a GitHub issue, pull request, or discussion. This collapses the comment and marks it as spam, abuse, off-topic, outdated, or resolved. Use this for inappropriate, off-topic, or outdated comments. The comment_id must be a GraphQL node ID (string like 'IC_kwDOABCD123456'), not a numeric REST API comment ID.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "comment_id": { | |
| "description": "GraphQL node ID of the comment to hide (e.g., 'IC_kwDOABCD123456'). This is the GraphQL node ID, not the numeric comment ID from REST API. Can be obtained from GraphQL queries or comment API responses.", | |
| "type": "string" | |
| }, | |
| "reason": { | |
| "description": "Optional reason for hiding the comment. Defaults to SPAM if not provided. Valid values: SPAM (spam content), ABUSE (abusive/harassment content), OFF_TOPIC (not relevant to discussion), OUTDATED (no longer applicable), RESOLVED (issue/question has been resolved).", | |
| "enum": [ | |
| "SPAM", | |
| "ABUSE", | |
| "OFF_TOPIC", | |
| "OUTDATED", | |
| "RESOLVED" | |
| ], | |
| "type": "string" | |
| } | |
| }, | |
| "required": [ | |
| "comment_id" | |
| ], | |
| "type": "object" | |
| }, | |
| "name": "hide_comment" | |
| }, | |
| { | |
| "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", | |
| "inputSchema": { | |
| "additionalProperties": false, | |
| "properties": { | |
| "alternatives": { | |
| "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", | |
| "type": "string" | |
| }, | |
| "context": { | |
| "description": "Additional context about the missing data or where it should come from (max 256 characters).", | |
| "type": "string" | |
| }, | |
| "data_type": { | |
| "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", | |
| "type": "string" | |
| }, | |
| "reason": { | |
| "description": "Explanation of why this data is needed to complete the task (max 256 characters).", | |
| "type": "string" | |
| } | |
| }, | |
| "required": [], | |
| "type": "object" | |
| }, | |
| "name": "missing_data" | |
| } | |
| ] | |
| EOF | |
| cat > /opt/gh-aw/safeoutputs/validation.json << 'EOF' | |
| { | |
| "add_comment": { | |
| "defaultMax": 1, | |
| "fields": { | |
| "body": { | |
| "required": true, | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 65000 | |
| }, | |
| "item_number": { | |
| "issueOrPRNumber": true | |
| } | |
| } | |
| }, | |
| "add_labels": { | |
| "defaultMax": 5, | |
| "fields": { | |
| "item_number": { | |
| "issueOrPRNumber": true | |
| }, | |
| "labels": { | |
| "required": true, | |
| "type": "array", | |
| "itemType": "string", | |
| "itemSanitize": true, | |
| "itemMaxLength": 128 | |
| } | |
| } | |
| }, | |
| "create_issue": { | |
| "defaultMax": 1, | |
| "fields": { | |
| "body": { | |
| "required": true, | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 65000 | |
| }, | |
| "labels": { | |
| "type": "array", | |
| "itemType": "string", | |
| "itemSanitize": true, | |
| "itemMaxLength": 128 | |
| }, | |
| "parent": { | |
| "issueOrPRNumber": true | |
| }, | |
| "repo": { | |
| "type": "string", | |
| "maxLength": 256 | |
| }, | |
| "temporary_id": { | |
| "type": "string" | |
| }, | |
| "title": { | |
| "required": true, | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 128 | |
| } | |
| } | |
| }, | |
| "missing_tool": { | |
| "defaultMax": 20, | |
| "fields": { | |
| "alternatives": { | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 512 | |
| }, | |
| "reason": { | |
| "required": true, | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 256 | |
| }, | |
| "tool": { | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 128 | |
| } | |
| } | |
| }, | |
| "noop": { | |
| "defaultMax": 1, | |
| "fields": { | |
| "message": { | |
| "required": true, | |
| "type": "string", | |
| "sanitize": true, | |
| "maxLength": 65000 | |
| } | |
| } | |
| } | |
| } | |
| EOF | |
| - name: Generate Safe Outputs MCP Server Config | |
| id: safe-outputs-config | |
| run: | | |
| # Generate a secure random API key (360 bits of entropy, 40+ chars) | |
| API_KEY="" | |
| API_KEY=$(openssl rand -base64 45 | tr -d '/+=') | |
| PORT=3001 | |
| # Register API key as secret to mask it from logs | |
| echo "::add-mask::${API_KEY}" | |
| # Set outputs for next steps | |
| { | |
| echo "safe_outputs_api_key=${API_KEY}" | |
| echo "safe_outputs_port=${PORT}" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Safe Outputs MCP server will run on port ${PORT}" | |
| - name: Start Safe Outputs MCP HTTP Server | |
| id: safe-outputs-start | |
| env: | |
| DEBUG: '*' | |
| GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} | |
| GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} | |
| GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json | |
| GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json | |
| GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs | |
| run: | | |
| # Environment variables are set above to prevent template injection | |
| export DEBUG | |
| export GH_AW_SAFE_OUTPUTS_PORT | |
| export GH_AW_SAFE_OUTPUTS_API_KEY | |
| export GH_AW_SAFE_OUTPUTS_TOOLS_PATH | |
| export GH_AW_SAFE_OUTPUTS_CONFIG_PATH | |
| export GH_AW_MCP_LOG_DIR | |
| bash /opt/gh-aw/actions/start_safe_outputs_server.sh | |
| - name: Setup Safe Inputs Config | |
| run: | | |
| mkdir -p /opt/gh-aw/safe-inputs/logs | |
| cat > /opt/gh-aw/safe-inputs/tools.json << 'EOF_TOOLS_JSON' | |
| { | |
| "serverName": "safeinputs", | |
| "version": "1.0.0", | |
| "logDir": "/opt/gh-aw/safe-inputs/logs", | |
| "tools": [ | |
| { | |
| "name": "gh", | |
| "description": "Execute any gh CLI command. This tool is accessible as 'safeinputs-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh \u003cargs\u003e. Use single quotes ' for complex args to avoid shell interpretation issues.", | |
| "inputSchema": { | |
| "properties": { | |
| "args": { | |
| "description": "Arguments to pass to gh CLI (without the 'gh' prefix). Examples: 'pr list --limit 5', 'issue view 123', 'api repos/{owner}/{repo}'", | |
| "type": "string" | |
| } | |
| }, | |
| "required": [ | |
| "args" | |
| ], | |
| "type": "object" | |
| }, | |
| "handler": "gh.sh", | |
| "env": { | |
| "GH_AW_GH_TOKEN": "GH_AW_GH_TOKEN", | |
| "GH_DEBUG": "GH_DEBUG" | |
| }, | |
| "timeout": 60 | |
| } | |
| ] | |
| } | |
| EOF_TOOLS_JSON | |
| cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'EOFSI' | |
| const path = require("path"); | |
| const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); | |
| const configPath = path.join(__dirname, "tools.json"); | |
| const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); | |
| const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; | |
| startHttpServer(configPath, { | |
| port: port, | |
| stateless: true, | |
| logDir: "/opt/gh-aw/safe-inputs/logs" | |
| }).catch(error => { | |
| console.error("Failed to start safe-inputs HTTP server:", error); | |
| process.exit(1); | |
| }); | |
| EOFSI | |
| chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs | |
| - name: Setup Safe Inputs Tool Files | |
| run: | | |
| cat > /opt/gh-aw/safe-inputs/gh.sh << 'EOFSH_gh' | |
| #!/bin/bash | |
| # Auto-generated safe-input tool: gh | |
| # Execute any gh CLI command. This tool is accessible as 'safeinputs-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh <args>. Use single quotes ' for complex args to avoid shell interpretation issues. | |
| set -euo pipefail | |
| echo "gh $INPUT_ARGS" | |
| echo " token: ${GH_AW_GH_TOKEN:0:6}..." | |
| GH_TOKEN="$GH_AW_GH_TOKEN" gh $INPUT_ARGS | |
| EOFSH_gh | |
| chmod +x /opt/gh-aw/safe-inputs/gh.sh | |
| - name: Generate Safe Inputs MCP Server Config | |
| id: safe-inputs-config | |
| run: | | |
| # Generate a secure random API key (360 bits of entropy, 40+ chars) | |
| API_KEY="" | |
| API_KEY=$(openssl rand -base64 45 | tr -d '/+=') | |
| PORT=3000 | |
| # Register API key as secret to mask it from logs | |
| echo "::add-mask::${API_KEY}" | |
| # Set outputs for next steps | |
| { | |
| echo "safe_inputs_api_key=${API_KEY}" | |
| echo "safe_inputs_port=${PORT}" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Safe Inputs MCP server will run on port ${PORT}" | |
| - name: Start Safe Inputs MCP HTTP Server | |
| id: safe-inputs-start | |
| env: | |
| DEBUG: '*' | |
| GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} | |
| GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} | |
| GH_AW_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_DEBUG: 1 | |
| run: | | |
| # Environment variables are set above to prevent template injection | |
| export DEBUG | |
| export GH_AW_SAFE_INPUTS_PORT | |
| export GH_AW_SAFE_INPUTS_API_KEY | |
| bash /opt/gh-aw/actions/start_safe_inputs_server.sh | |
| - name: Start MCP gateway | |
| id: start-mcp-gateway | |
| env: | |
| GH_AW_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} | |
| GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} | |
| GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} | |
| GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} | |
| GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} | |
| GH_DEBUG: 1 | |
| GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} | |
| GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -eo pipefail | |
| mkdir -p /tmp/gh-aw/mcp-config | |
| # Export gateway environment variables for MCP config and gateway script | |
| export MCP_GATEWAY_PORT="80" | |
| export MCP_GATEWAY_DOMAIN="host.docker.internal" | |
| MCP_GATEWAY_API_KEY="" | |
| MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') | |
| export MCP_GATEWAY_API_KEY | |
| export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" | |
| mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" | |
| export DEBUG="*" | |
| # Register API key as secret to mask it from logs | |
| echo "::add-mask::${MCP_GATEWAY_API_KEY}" | |
| export GH_AW_ENGINE="codex" | |
| export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_LOCKDOWN -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GH_AW_GH_TOKEN -e GH_DEBUG -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.0.103' | |
| cat > /tmp/gh-aw/mcp-config/config.toml << EOF | |
| [history] | |
| persistence = "none" | |
| [shell_environment_policy] | |
| inherit = "core" | |
| include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] | |
| [mcp_servers.github] | |
| user_agent = "smoke-codex" | |
| startup_timeout_sec = 120 | |
| tool_timeout_sec = 60 | |
| container = "ghcr.io/github/github-mcp-server:v0.30.3" | |
| env = { "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } | |
| env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] | |
| [mcp_servers.playwright] | |
| container = "mcr.microsoft.com/playwright/mcp" | |
| args = [ | |
| "--init", | |
| "--network", | |
| "host", | |
| ] | |
| entrypointArgs = [ | |
| "--output-dir", | |
| "/tmp/gh-aw/mcp-logs/playwright", | |
| "--allowed-hosts", | |
| "localhost;localhost:*;127.0.0.1;127.0.0.1:*", | |
| "--allowed-origins", | |
| "localhost;localhost:*;127.0.0.1;127.0.0.1:*" | |
| ] | |
| mounts = ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"] | |
| [mcp_servers.safeinputs] | |
| type = "http" | |
| url = "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT" | |
| headers = { Authorization = "$GH_AW_SAFE_INPUTS_API_KEY" } | |
| [mcp_servers.safeoutputs] | |
| type = "http" | |
| url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" | |
| [mcp_servers.safeoutputs.headers] | |
| Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" | |
| [mcp_servers.serena] | |
| container = "ghcr.io/github/serena-mcp-server:latest" | |
| args = [ | |
| "--network", | |
| "host", | |
| ] | |
| entrypoint = "serena" | |
| entrypointArgs = [ | |
| "start-mcp-server", | |
| "--context", | |
| "codex", | |
| "--project", | |
| "${{ github.workspace }}" | |
| ] | |
| mounts = ["${{ github.workspace }}:${{ github.workspace }}:rw"] | |
| EOF | |
| # Generate JSON config for MCP gateway | |
| cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh | |
| { | |
| "mcpServers": { | |
| "github": { | |
| "container": "ghcr.io/github/github-mcp-server:v0.30.3", | |
| "env": { | |
| "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", | |
| "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", | |
| "GITHUB_READ_ONLY": "1", | |
| "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" | |
| } | |
| }, | |
| "playwright": { | |
| "container": "mcr.microsoft.com/playwright/mcp", | |
| "args": [ | |
| "--init", | |
| "--network", | |
| "host" | |
| ], | |
| "entrypointArgs": [ | |
| "--output-dir", | |
| "/tmp/gh-aw/mcp-logs/playwright", | |
| "--allowed-hosts", | |
| "localhost,localhost:*,127.0.0.1,127.0.0.1:*,github.com", | |
| "--allowed-origins", | |
| "localhost;localhost:*;127.0.0.1;127.0.0.1:*;github.com" | |
| ], | |
| "mounts": ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"] | |
| }, | |
| "safeinputs": { | |
| "type": "http", | |
| "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", | |
| "headers": { | |
| "Authorization": "$GH_AW_SAFE_INPUTS_API_KEY" | |
| } | |
| }, | |
| "safeoutputs": { | |
| "type": "http", | |
| "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", | |
| "headers": { | |
| "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" | |
| } | |
| }, | |
| "serena": { | |
| "container": "ghcr.io/github/serena-mcp-server:latest", | |
| "args": [ | |
| "--network", | |
| "host" | |
| ], | |
| "entrypoint": "serena", | |
| "entrypointArgs": [ | |
| "start-mcp-server", | |
| "--context", | |
| "codex", | |
| "--project", | |
| "${{ github.workspace }}" | |
| ], | |
| "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] | |
| } | |
| }, | |
| "gateway": { | |
| "port": $MCP_GATEWAY_PORT, | |
| "domain": "${MCP_GATEWAY_DOMAIN}", | |
| "apiKey": "${MCP_GATEWAY_API_KEY}", | |
| "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" | |
| } | |
| } | |
| MCPCONFIG_EOF | |
| - name: Generate agentic run info | |
| id: generate_aw_info | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const awInfo = { | |
| engine_id: "codex", | |
| engine_name: "Codex", | |
| model: process.env.GH_AW_MODEL_AGENT_CODEX || "", | |
| version: "", | |
| agent_version: "0.98.0", | |
| cli_version: "v0.42.13", | |
| workflow_name: "Smoke Codex", | |
| experimental: false, | |
| supports_tools_allowlist: true, | |
| supports_http_transport: true, | |
| run_id: context.runId, | |
| run_number: context.runNumber, | |
| run_attempt: process.env.GITHUB_RUN_ATTEMPT, | |
| repository: context.repo.owner + '/' + context.repo.repo, | |
| ref: context.ref, | |
| sha: context.sha, | |
| actor: context.actor, | |
| event_name: context.eventName, | |
| staged: false, | |
| allowed_domains: ["api.github.com","defaults","github","playwright"], | |
| firewall_enabled: true, | |
| awf_version: "v0.13.12", | |
| awmg_version: "v0.0.103", | |
| steps: { | |
| firewall: "squid" | |
| }, | |
| created_at: new Date().toISOString() | |
| }; | |
| // Write to /tmp/gh-aw directory to avoid inclusion in PR | |
| const tmpPath = '/tmp/gh-aw/aw_info.json'; | |
| fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); | |
| console.log('Generated aw_info.json at:', tmpPath); | |
| console.log(JSON.stringify(awInfo, null, 2)); | |
| // Set model as output for reuse in other steps/jobs | |
| core.setOutput('model', awInfo.model); | |
| - name: Generate workflow overview | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); | |
| await generateWorkflowOverview(core); | |
| - name: Create prompt with built-in context | |
| env: | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} | |
| GH_AW_GITHUB_ACTOR: ${{ github.actor }} | |
| GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} | |
| GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} | |
| GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} | |
| GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} | |
| GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} | |
| GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} | |
| run: | | |
| bash /opt/gh-aw/actions/create_prompt_first.sh | |
| cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" | |
| <system> | |
| PROMPT_EOF | |
| cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" | |
| cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" | |
| cat "/opt/gh-aw/prompts/playwright_prompt.md" >> "$GH_AW_PROMPT" | |
| cat "/opt/gh-aw/prompts/cache_memory_prompt.md" >> "$GH_AW_PROMPT" | |
| cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" | |
| <safe-outputs> | |
| <description>GitHub API Access Instructions</description> | |
| <important> | |
| The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. | |
| </important> | |
| <instructions> | |
| To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. | |
| Discover available tools from the safeoutputs MCP server. | |
| **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. | |
| **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. | |
| </instructions> | |
| </safe-outputs> | |
| <github-context> | |
| The following GitHub context information is available for this workflow: | |
| {{#if __GH_AW_GITHUB_ACTOR__ }} | |
| - **actor**: __GH_AW_GITHUB_ACTOR__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_REPOSITORY__ }} | |
| - **repository**: __GH_AW_GITHUB_REPOSITORY__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_WORKSPACE__ }} | |
| - **workspace**: __GH_AW_GITHUB_WORKSPACE__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} | |
| - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} | |
| - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} | |
| - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} | |
| - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ | |
| {{/if}} | |
| {{#if __GH_AW_GITHUB_RUN_ID__ }} | |
| - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ | |
| {{/if}} | |
| </github-context> | |
| PROMPT_EOF | |
| cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" | |
| </system> | |
| PROMPT_EOF | |
| cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" | |
| **IMPORTANT**: Always use the `safeinputs-gh` tool for GitHub CLI commands instead of running `gh` directly via bash. The `safeinputs-gh` tool has proper authentication configured with `GITHUB_TOKEN`, while bash commands do not have GitHub CLI authentication by default. | |
| **Correct**: | |
| ``` | |
| Use the safeinputs-gh tool with args: "pr list --limit 5" | |
| Use the safeinputs-gh tool with args: "issue view 123" | |
| ``` | |
| **Incorrect**: | |
| ``` | |
| Use the gh safe-input tool with args: "pr list --limit 5" โ (Wrong tool name - use safeinputs-gh) | |
| Run: gh pr list --limit 5 โ (No authentication in bash) | |
| Execute bash: gh issue view 123 โ (No authentication in bash) | |
| ``` | |
| PROMPT_EOF | |
| cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" | |
| {{#runtime-import .github/workflows/smoke-codex.md}} | |
| PROMPT_EOF | |
| - name: Substitute placeholders | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| GH_AW_CACHE_DESCRIPTION: '' | |
| GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/' | |
| GH_AW_GITHUB_ACTOR: ${{ github.actor }} | |
| GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} | |
| GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} | |
| GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} | |
| GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} | |
| GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} | |
| GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} | |
| with: | |
| script: | | |
| const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); | |
| // Call the substitution function | |
| return await substitutePlaceholders({ | |
| file: process.env.GH_AW_PROMPT, | |
| substitutions: { | |
| GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION, | |
| GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR, | |
| GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, | |
| GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, | |
| GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, | |
| GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, | |
| GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, | |
| GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, | |
| GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, | |
| GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE | |
| } | |
| }); | |
| - name: Interpolate variables and render templates | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} | |
| GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); | |
| await main(); | |
| - name: Validate prompt placeholders | |
| env: | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh | |
| - name: Print prompt | |
| env: | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| run: bash /opt/gh-aw/actions/print_prompt_summary.sh | |
| - name: Run Codex | |
| run: | | |
| set -o pipefail | |
| mkdir -p "$CODEX_HOME/logs" | |
| sudo -E awf --enable-chroot --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.13.12 --skip-pull \ | |
| -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' \ | |
| 2>&1 | tee /tmp/gh-aw/agent-stdio.log | |
| env: | |
| CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} | |
| CODEX_HOME: /tmp/gh-aw/mcp-config | |
| GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml | |
| GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || '' }} | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} | |
| GH_DEBUG: 1 | |
| GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} | |
| OPENAI_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} | |
| RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug | |
| - name: Stop MCP gateway | |
| if: always() | |
| continue-on-error: true | |
| env: | |
| MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} | |
| MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} | |
| GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} | |
| run: | | |
| bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" | |
| - name: Redact secrets in logs | |
| if: always() | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs'); | |
| await main(); | |
| env: | |
| GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' | |
| SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} | |
| SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} | |
| SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} | |
| SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| - name: Upload Safe Outputs | |
| if: always() | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: safe-output | |
| path: ${{ env.GH_AW_SAFE_OUTPUTS }} | |
| if-no-files-found: warn | |
| - name: Ingest agent output | |
| id: collect_output | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} | |
| GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" | |
| GITHUB_SERVER_URL: ${{ github.server_url }} | |
| GITHUB_API_URL: ${{ github.api_url }} | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs'); | |
| await main(); | |
| - name: Upload sanitized agent output | |
| if: always() && env.GH_AW_AGENT_OUTPUT | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: agent-output | |
| path: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| if-no-files-found: warn | |
| - name: Upload engine output files | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: agent_outputs | |
| path: | | |
| /tmp/gh-aw/mcp-config/logs/ | |
| /tmp/gh-aw/redacted-urls.log | |
| if-no-files-found: ignore | |
| - name: Parse agent logs for step summary | |
| if: always() | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/parse_codex_log.cjs'); | |
| await main(); | |
| - name: Parse safe-inputs logs for step summary | |
| if: always() | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/parse_safe_inputs_logs.cjs'); | |
| await main(); | |
| - name: Parse MCP gateway logs for step summary | |
| if: always() | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); | |
| await main(); | |
| - name: Print firewall logs | |
| if: always() | |
| continue-on-error: true | |
| env: | |
| AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs | |
| run: | | |
| # Fix permissions on firewall logs so they can be uploaded as artifacts | |
| # AWF runs with sudo, creating files owned by root | |
| sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true | |
| awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" | |
| - name: Upload cache-memory data as artifact | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| if: always() | |
| with: | |
| name: cache-memory | |
| path: /tmp/gh-aw/cache-memory | |
| - name: Upload agent artifacts | |
| if: always() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: agent-artifacts | |
| path: | | |
| /tmp/gh-aw/aw-prompts/prompt.txt | |
| /tmp/gh-aw/aw_info.json | |
| /tmp/gh-aw/mcp-logs/ | |
| /tmp/gh-aw/safe-inputs/logs/ | |
| /tmp/gh-aw/sandbox/firewall/logs/ | |
| /tmp/gh-aw/agent-stdio.log | |
| /tmp/gh-aw/agent/ | |
| if-no-files-found: ignore | |
| conclusion: | |
| needs: | |
| - activation | |
| - agent | |
| - detection | |
| - safe_outputs | |
| - update_cache_memory | |
| if: (always()) && (needs.agent.result != 'skipped') | |
| runs-on: ubuntu-slim | |
| permissions: | |
| contents: read | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| outputs: | |
| noop_message: ${{ steps.noop.outputs.noop_message }} | |
| tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} | |
| total_count: ${{ steps.missing_tool.outputs.total_count }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Debug job inputs | |
| env: | |
| COMMENT_ID: ${{ needs.activation.outputs.comment_id }} | |
| COMMENT_REPO: ${{ needs.activation.outputs.comment_repo }} | |
| AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} | |
| AGENT_CONCLUSION: ${{ needs.agent.result }} | |
| run: | | |
| echo "Comment ID: $COMMENT_ID" | |
| echo "Comment Repo: $COMMENT_REPO" | |
| echo "Agent Output Types: $AGENT_OUTPUT_TYPES" | |
| echo "Agent Conclusion: $AGENT_CONCLUSION" | |
| - name: Download agent output artifact | |
| continue-on-error: true | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: agent-output | |
| path: /tmp/gh-aw/safeoutputs/ | |
| - name: Setup agent output environment variable | |
| run: | | |
| mkdir -p /tmp/gh-aw/safeoutputs/ | |
| find "/tmp/gh-aw/safeoutputs/" -type f -print | |
| echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" | |
| - name: Process No-Op Messages | |
| id: noop | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| GH_AW_NOOP_MAX: 1 | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/noop.cjs'); | |
| await main(); | |
| - name: Record Missing Tool | |
| id: missing_tool | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); | |
| await main(); | |
| - name: Handle Agent Failure | |
| id: handle_agent_failure | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} | |
| GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} | |
| GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} | |
| GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e ๐ฎ *The oracle has spoken through [{workflow_name}]({run_url})*\",\"runStarted\":\"๐ฎ The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"โจ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. ๐\",\"runFailure\":\"๐ The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); | |
| await main(); | |
| - name: Update reaction comment with completion status | |
| id: conclusion | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} | |
| GH_AW_COMMENT_REPO: ${{ needs.activation.outputs.comment_repo }} | |
| GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} | |
| GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.result }} | |
| GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e ๐ฎ *The oracle has spoken through [{workflow_name}]({run_url})*\",\"runStarted\":\"๐ฎ The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"โจ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. ๐\",\"runFailure\":\"๐ The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/notify_comment_error.cjs'); | |
| await main(); | |
| detection: | |
| needs: agent | |
| if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| timeout-minutes: 10 | |
| outputs: | |
| success: ${{ steps.parse_results.outputs.success }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Download agent artifacts | |
| continue-on-error: true | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: agent-artifacts | |
| path: /tmp/gh-aw/threat-detection/ | |
| - name: Download agent output artifact | |
| continue-on-error: true | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: agent-output | |
| path: /tmp/gh-aw/threat-detection/ | |
| - name: Echo agent output types | |
| env: | |
| AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} | |
| run: | | |
| echo "Agent output-types: $AGENT_OUTPUT_TYPES" | |
| - name: Setup threat detection | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| WORKFLOW_NAME: "Smoke Codex" | |
| WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Codex engine functionality by reviewing recent PRs twice daily" | |
| HAS_PATCH: ${{ needs.agent.outputs.has_patch }} | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs'); | |
| await main(); | |
| - name: Ensure threat-detection directory and log | |
| run: | | |
| mkdir -p /tmp/gh-aw/threat-detection | |
| touch /tmp/gh-aw/threat-detection/detection.log | |
| - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret | |
| id: validate-secret | |
| run: /opt/gh-aw/actions/validate_multi_secret.sh CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex | |
| env: | |
| CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 | |
| with: | |
| node-version: '24' | |
| package-manager-cache: false | |
| - name: Install Codex | |
| run: npm install -g --silent @openai/codex@0.98.0 | |
| - name: Run Codex | |
| run: | | |
| set -o pipefail | |
| INSTRUCTION="$(cat "$GH_AW_PROMPT")" | |
| mkdir -p "$CODEX_HOME/logs" | |
| codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log | |
| env: | |
| CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} | |
| CODEX_HOME: /tmp/gh-aw/mcp-config | |
| GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml | |
| GH_AW_MODEL_DETECTION_CODEX: ${{ vars.GH_AW_MODEL_DETECTION_CODEX || '' }} | |
| GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt | |
| GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} | |
| OPENAI_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} | |
| RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug | |
| - name: Parse threat detection results | |
| id: parse_results | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs'); | |
| await main(); | |
| - name: Upload threat detection log | |
| if: always() | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: threat-detection.log | |
| path: /tmp/gh-aw/threat-detection/detection.log | |
| if-no-files-found: ignore | |
| pre_activation: | |
| if: > | |
| ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && | |
| ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) | |
| runs-on: ubuntu-slim | |
| permissions: | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| outputs: | |
| activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Add hooray reaction for immediate feedback | |
| id: react | |
| if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_REACTION: "hooray" | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/add_reaction.cjs'); | |
| await main(); | |
| - name: Check team membership for workflow | |
| id: check_membership | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_REQUIRED_ROLES: admin,maintainer,write | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); | |
| await main(); | |
| safe_outputs: | |
| needs: | |
| - agent | |
| - detection | |
| if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') | |
| runs-on: ubuntu-slim | |
| permissions: | |
| contents: read | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| timeout-minutes: 15 | |
| env: | |
| GH_AW_ENGINE_ID: "codex" | |
| GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e ๐ฎ *The oracle has spoken through [{workflow_name}]({run_url})*\",\"runStarted\":\"๐ฎ The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"โจ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. ๐\",\"runFailure\":\"๐ The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" | |
| GH_AW_WORKFLOW_ID: "smoke-codex" | |
| GH_AW_WORKFLOW_NAME: "Smoke Codex" | |
| outputs: | |
| create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} | |
| create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} | |
| process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} | |
| process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Download agent output artifact | |
| continue-on-error: true | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: agent-output | |
| path: /tmp/gh-aw/safeoutputs/ | |
| - name: Setup agent output environment variable | |
| run: | | |
| mkdir -p /tmp/gh-aw/safeoutputs/ | |
| find "/tmp/gh-aw/safeoutputs/" -type f -print | |
| echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" | |
| - name: Process Safe Outputs | |
| id: process_safe_outputs | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} | |
| GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"smoke-codex\"]},\"create_issue\":{\"expires\":2,\"max\":1},\"hide_comment\":{\"max\":5},\"missing_data\":{},\"missing_tool\":{}}" | |
| with: | |
| github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); | |
| setupGlobals(core, github, context, exec, io); | |
| const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); | |
| await main(); | |
| update_cache_memory: | |
| needs: | |
| - agent | |
| - detection | |
| if: always() && needs.detection.outputs.success == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - name: Setup Scripts | |
| uses: github/gh-aw/actions/setup@94662b1dee8ce96c876ba9f33b3ab8be32de82a4 # v0.42.13 | |
| with: | |
| destination: /opt/gh-aw/actions | |
| - name: Download cache-memory artifact (default) | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| continue-on-error: true | |
| with: | |
| name: cache-memory | |
| path: /tmp/gh-aw/cache-memory | |
| - name: Save cache-memory to cache (default) | |
| uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 | |
| with: | |
| key: memory-${{ github.workflow }}-${{ github.run_id }} | |
| path: /tmp/gh-aw/cache-memory | |