diff --git a/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.lock.yml b/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.lock.yml new file mode 100644 index 00000000..ef07e1e8 --- /dev/null +++ b/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.lock.yml @@ -0,0 +1,1473 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Daily detector for 'Resource not accessible by integration' across long-term branches +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/network-ecosystems.md +# - gh-aw-fragments/previous-findings.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b6ba8cee4eb0375c45e815c6ab950a04253ddd1b30752434ff14c08d25ead129"} + +name: "Resource Not Accessible By Integration Detector" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + issue-title-prefix: + default: "[resource-not-accessible-by-integration]" + description: Title prefix for created issue (e.g. '[resource-not-accessible-by-integration]') + required: false + type: string + long-term-branches: + default: "" + description: Space-separated list of long-term branch names to scan in addition to the default branch (e.g. 'main 8.x 7.17') + required: false + type: string + look-back-days: + default: 1 + description: Number of days to look back when scanning failed workflow runs + required: false + type: number + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: estc-actions-resource-not-accessible-detector + +run-name: "Resource Not Accessible By Integration Detector" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@3c15f58f43054a10fa3173200611a0a76182c446 + with: + destination: /opt/gh-aw/actions + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Validate context variables + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-estc-actions-resource-not-accessible-detector.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: 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_EXPR_3A5062C8: ${{ inputs.look-back-days }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_922C262D: ${{ inputs.long-term-branches }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + 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_EVENT_REPOSITORY_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + 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 << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" + cat "/opt/gh-aw/prompts/markdown.md" + cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_EOF' + + Tools: create_issue, missing_tool, missing_data, noop + + + 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}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before submitting any output, re-read it as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + - Be thorough, spend the time to investigate and verify. There is no rush. Do your best work. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked). + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Previous Findings + + Before filing a new issue, check `/tmp/previous-findings.json` for issues this agent has already filed. + + - Run `cat /tmp/previous-findings.json` to read the list of previously filed issue numbers and titles. + - If your finding closely matches an open or recently-closed issue in that list, call `noop` instead of filing a duplicate. + - Only file a new issue when the finding is genuinely distinct from all previous findings. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + # Resource Not Accessible By Integration Detector + + Use the prescan output to investigate only workflows that already matched `Resource not accessible by integration`, then create a single tracking issue with the combined analysis. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + - **Default Branch**: __GH_AW_GITHUB_EVENT_REPOSITORY_DEFAULT_BRANCH__ + - **Additional long-term branches**: __GH_AW_EXPR_922C262D__ + - **Look-back days**: __GH_AW_EXPR_3A5062C8__ + - **Error pattern**: `Resource not accessible by integration` + - **Prescan summary**: `/tmp/gh-aw/agent/resource-not-accessible-summary.txt` + - **Prescan findings**: `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv` + ## Constraints + + - **CAN**: Read files, search code, run commands, create one issue. + - **CANNOT**: Push changes or open PRs in this workflow. + - Only investigate workflows listed in `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv`. + - Do not file a duplicate issue if an open `__GH_AW_EXPR_CE96317F__` issue already tracks the same workflows and failure pattern. + + ## Permission reference + + `Resource not accessible by integration` means the `GITHUB_TOKEN` lacks a required scope. Common causes: + + | Failed operation | Required permission | + | --- | --- | + | Create/update issues | `issues: write` | + | Create/update pull requests | `pull-requests: write` | + | Push code or tags | `contents: write` | + | Create releases | `contents: write` | + | Publish packages | `packages: write` | + | Trigger other workflows | `actions: write` | + | Manage deployments | `deployments: write` | + | Create/update checks | `checks: write` | + | Comment on PRs | `pull-requests: write` | + + Common root causes: + - **Missing `permissions:` block** — the workflow relies on the repo/org default token permissions which are too restrictive. + - **Fork PRs** — `pull_request` from forks always gets a read-only token. Use `pull_request_target` (with caution) or a GitHub App token. + - **Organization policies** — org-level settings may cap the maximum token permissions. + + The fix is to add an explicit `permissions:` block at the workflow or job level granting only the minimum required scopes. For each affected workflow, read its source file under `.github/workflows/`, identify the operation that failed from the evidence, and recommend the specific permission to add. + + ## Step 1: Gather context + + 1. Call `generate_agents_md` to get repository conventions (if it fails, continue). + 2. Read `/tmp/gh-aw/agent/resource-not-accessible-summary.txt`. + 3. Read `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv`. + + ## Step 2: Decide whether to noop + + - If the findings file has no data rows, call `noop` with: + `No 'Resource not accessible by integration' failures found in the configured look-back window — nothing to report`. + - Check open issues for `__GH_AW_EXPR_CE96317F__` in the title and compare workflow paths/evidence. + - If an existing open issue already tracks the same findings, call `noop` and reference the existing issue number. + + ## Step 3: Investigate each affected workflow + + For each workflow in the findings file: + 1. Read the workflow source file from `.github/workflows/`. + 2. Identify which operation failed from the evidence lines. + 3. Check if the workflow already has a `permissions:` block and what scopes are granted. + 4. Determine the minimum permission fix needed. + + ## Step 4: Produce combined analysis issue + + Call `create_issue` exactly once with: + + - **Title**: A short descriptive title summarizing the affected workflows (do NOT repeat the issue-title-prefix in the title) + - **Body**: + + ```` + ## Scan Summary + + - Look-back days: + - Since: + - Matched workflows: + - Matched runs: + + ## Affected Workflows + + | Workflow file | Branches | Runs | + | --- | --- | --- | + | | | [](), ... | + + ## Evidence + + For each workflow include one or more verbatim evidence lines from the findings file. + + ## Root Cause Assessment + + For each workflow, explain which operation failed and why the current permissions are insufficient. + + ## Remediation + + For each workflow, provide the exact `permissions:` block to add or modify. Use before/after YAML snippets. Grant only the minimum required scopes. + + ## Next Steps + + - Apply the permission fixes manually under `.github/workflows/`. + ```` + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_REPOSITORY_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + GH_AW_EXPR_922C262D: ${{ inputs.long-term-branches }} + GH_AW_EXPR_3A5062C8: ${{ inputs.look-back-days }} + 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: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_3A5062C8: ${{ inputs.look-back-days }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_922C262D: ${{ inputs.long-term-branches }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + 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_EVENT_REPOSITORY_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + + 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_EXPR_3A5062C8: process.env.GH_AW_EXPR_3A5062C8, + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_922C262D: process.env.GH_AW_EXPR_922C262D, + GH_AW_EXPR_CE96317F: process.env.GH_AW_EXPR_CE96317F, + 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_EVENT_REPOSITORY_DEFAULT_BRANCH: process.env.GH_AW_GITHUB_EVENT_REPOSITORY_DEFAULT_BRANCH, + 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, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - 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: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + 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 + GH_AW_WORKFLOW_ID_SANITIZED: ghawestcactionsresourcenotaccessibledetector + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + 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 }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@3c15f58f43054a10fa3173200611a0a76182c446 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + GH_TOKEN: ${{ github.token }} + TITLE_PREFIX: ${{ inputs.title-prefix }} + name: List previous findings + run: "set -euo pipefail\ngh issue list \\\n --repo \"$GITHUB_REPOSITORY\" \\\n --search \"in:title \\\"$TITLE_PREFIX\\\"\" \\\n --state all \\\n --limit 100 \\\n --json number,title,state \\\n > /tmp/previous-findings.json || { echo \"::warning::Failed to fetch previous findings — dedup will be skipped\"; echo \"[]\" > /tmp/previous-findings.json; }" + - env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_TOKEN: ${{ github.token }} + LONG_TERM_BRANCHES: ${{ inputs.long-term-branches }} + LOOK_BACK_DAYS: ${{ inputs.look-back-days }} + name: Prescan failed runs for target error + run: "set -euo pipefail\nmkdir -p /tmp/gh-aw/agent\n\nsince=\"$(date -u -d \"${LOOK_BACK_DAYS} days ago\" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v-\"${LOOK_BACK_DAYS}\"d '+%Y-%m-%dT%H:%M:%SZ')\"\nfindings_file=\"/tmp/gh-aw/agent/resource-not-accessible-findings.tsv\"\nprintf \"workflow_path\\tbranch\\trun_id\\trun_url\\tcreated_at\\tevidence\\n\" > \"$findings_file\"\n\nbranches=()\nfor branch in \"$DEFAULT_BRANCH\" $LONG_TERM_BRANCHES; do\n [ -n \"$branch\" ] || continue\n skip=false\n for existing in \"${branches[@]:-}\"; do\n if [ \"$existing\" = \"$branch\" ]; then\n skip=true\n break\n fi\n done\n if [ \"$skip\" = false ]; then\n branches+=(\"$branch\")\n fi\ndone\n\nruns_file=\"/tmp/gh-aw/agent/resource-not-accessible-runs.tsv\"\n: > \"$runs_file\"\nfor branch in \"${branches[@]}\"; do\n gh api \"repos/$GITHUB_REPOSITORY/actions/runs\" \\\n --method GET \\\n -f branch=\"$branch\" \\\n -f status=failure \\\n -f created=\">=${since}\" \\\n --paginate \\\n --jq '.workflow_runs[] | [.id, .html_url, .path, .head_branch, .created_at] | @tsv' \\\n >> \"$runs_file\" || true\ndone\n\nwhile IFS=$'\\t' read -r run_id run_url workflow_path head_branch created_at; do\n [ -n \"${run_id:-}\" ] || continue\n zip_file=\"/tmp/gh-aw/agent/workflow-logs-${run_id}.zip\"\n log_dir=\"/tmp/gh-aw/agent/workflow-logs-${run_id}\"\n\n if ! gh api \"repos/$GITHUB_REPOSITORY/actions/runs/${run_id}/logs\" -H \"Accept: application/vnd.github+json\" > \"$zip_file\" 2>/dev/null; then\n continue\n fi\n rm -rf \"$log_dir\"\n if ! unzip -o \"$zip_file\" -d \"$log_dir\" >/dev/null 2>&1; then\n continue\n fi\n\n match=\"$(grep -R -n -m 3 \"Resource not accessible by integration\" \"$log_dir\" 2>/dev/null || true)\"\n if [ -n \"$match\" ]; then\n evidence=\"${match//$'\\t'/ }\"\n evidence=\"${evidence//$'\\n'/ | }\"\n printf \"%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n\" \"$workflow_path\" \"$head_branch\" \"$run_id\" \"$run_url\" \"$created_at\" \"$evidence\" >> \"$findings_file\"\n fi\n rm -rf \"$log_dir\" \"$zip_file\"\ndone < \"$runs_file\"\n\nmatches=\"$(tail -n +2 \"$findings_file\" | wc -l | tr -d ' ')\"\nworkflows=\"$(tail -n +2 \"$findings_file\" | cut -f1 | sort -u | wc -l | tr -d ' ')\"\n{\n echo \"since=${since}\"\n echo \"look_back_days=${LOOK_BACK_DAYS}\"\n echo \"matched_runs=${matches}\"\n echo \"matched_workflows=${workflows}\"\n echo \"findings_file=${findings_file}\"\n} > /tmp/gh-aw/agent/resource-not-accessible-summary.txt\n" + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - 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]" + git config --global am.keepcr true + # 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) || (github.event.issue.pull_request) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + 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: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.419", + workflow_name: "Resource Not Accessible By Integration Detector", + experimental: false, + supports_tools_allowlist: 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: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","clojure","cloud.elastic.co","containers","dart","defaults","dotnet","ela.st","elastic.co","elastic.dev","elastic.github.io","elixir","fonts","github","github-actions","go","haskell","java","kotlin","linux-distros","node","node-cdns","perl","php","playwright","public-code-search.fastmcp.app","python","ruby","rust","scala","swift","terraform","www.elastic.co","zig"], + firewall_enabled: true, + awf_version: "v0.23.0", + awmg_version: "v0.1.6", + 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: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.419 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.23.0 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + 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.23.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.23.0 ghcr.io/github/gh-aw-firewall/squid:0.23.0 ghcr.io/github/gh-aw-mcpg:v0.1.6 ghcr.io/github/github-mcp-server:v0.31.0 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 << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' + {"create_issue":{"expires":168,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_EOF + cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_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. Title will be prefixed with \"${{ inputs.issue-title-prefix }} \".", + "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_abc123', 'aw_Test123') 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 3 to 8 alphanumeric characters (e.g., 'aw_abc1', 'aw_Test123'). Use '#aw_ID' in body text to reference other issues by their temporary_id; these are replaced with actual issue numbers after creation.", + "pattern": "^aw_[A-Za-z0-9]{3,8}$", + "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": "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": "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" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "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_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "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 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_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) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # 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: Start MCP Gateway + id: start-mcp-gateway + env: + 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 }} + 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=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -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.1.6' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,actions" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - 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]" + git config --global am.keepcr true + # 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: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - 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 + 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: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + 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 }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" + 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 + 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 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/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 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + 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 + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + 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/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + # --- Threat Detection (inline) --- + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }} + HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP configuration for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + WORKFLOW_DESCRIPTION: "Daily detector for 'Resource not accessible by integration' across long-term branches" + HAS_PATCH: ${{ steps.collect_output.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 + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_detection_results + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + 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() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Set detection conclusion + id: detection_conclusion + if: always() + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }} + run: | + if [[ "$RUN_DETECTION" != "true" ]]; then + echo "conclusion=skipped" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection was not needed, marking as skipped" + elif [[ "$DETECTION_SUCCESS" == "true" ]]; then + echo "conclusion=success" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection passed successfully" + else + echo "conclusion=failure" >> "$GITHUB_OUTPUT" + echo "success=false" >> "$GITHUB_OUTPUT" + echo "Detection found issues" + fi + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: 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@3c15f58f43054a10fa3173200611a0a76182c446 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + 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 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + 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 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + 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 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "gh-aw-estc-actions-resource-not-accessible-detector" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\",\"activationComments\":\"false\"}" + GH_AW_GROUP_REPORTS: "false" + 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: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + 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_noop_message.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@3c15f58f43054a10fa3173200611a0a76182c446 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + 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 + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\",\"activationComments\":\"false\"}" + GH_AW_WORKFLOW_ID: "gh-aw-estc-actions-resource-not-accessible-detector" + GH_AW_WORKFLOW_NAME: "Resource Not Accessible By Integration Detector" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + 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@3c15f58f43054a10fa3173200611a0a76182c446 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + 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 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":false,\"expires\":168,\"max\":1,\"title_prefix\":\"${{ inputs.issue-title-prefix }} \"},\"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(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.md b/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.md new file mode 100644 index 00000000..9c47a961 --- /dev/null +++ b/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.md @@ -0,0 +1,272 @@ +--- +inlined-imports: true +description: "Daily detector for 'Resource not accessible by integration' across long-term branches" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-issue.md + - gh-aw-fragments/previous-findings.md + - gh-aw-fragments/network-ecosystems.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + long-term-branches: + description: "Space-separated list of long-term branch names to scan in addition to the default branch (e.g. 'main 8.x 7.17')" + type: string + required: false + default: "" + look-back-days: + description: "Number of days to look back when scanning failed workflow runs" + type: number + required: false + default: 1 + issue-title-prefix: + description: "Title prefix for created issue (e.g. '[resource-not-accessible-by-integration]')" + type: string + required: false + default: "[resource-not-accessible-by-integration]" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: estc-actions-resource-not-accessible-detector + cancel-in-progress: true +permissions: + actions: read + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, actions] + bash: true +strict: false +safe-outputs: + activation-comments: false + noop: + create-issue: + max: 1 + title-prefix: "${{ inputs.issue-title-prefix }} " + close-older-issues: false + expires: 7d +timeout-minutes: 90 +steps: + - name: Prescan failed runs for target error + env: + GH_TOKEN: ${{ github.token }} + LOOK_BACK_DAYS: ${{ inputs.look-back-days }} + LONG_TERM_BRANCHES: ${{ inputs.long-term-branches }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + mkdir -p /tmp/gh-aw/agent + + since="$(date -u -d "${LOOK_BACK_DAYS} days ago" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v-"${LOOK_BACK_DAYS}"d '+%Y-%m-%dT%H:%M:%SZ')" + findings_file="/tmp/gh-aw/agent/resource-not-accessible-findings.tsv" + printf "workflow_path\tbranch\trun_id\trun_url\tcreated_at\tevidence\n" > "$findings_file" + + branches=() + for branch in "$DEFAULT_BRANCH" $LONG_TERM_BRANCHES; do + [ -n "$branch" ] || continue + skip=false + for existing in "${branches[@]:-}"; do + if [ "$existing" = "$branch" ]; then + skip=true + break + fi + done + if [ "$skip" = false ]; then + branches+=("$branch") + fi + done + + runs_file="/tmp/gh-aw/agent/resource-not-accessible-runs.tsv" + : > "$runs_file" + for branch in "${branches[@]}"; do + gh api "repos/$GITHUB_REPOSITORY/actions/runs" \ + --method GET \ + -f branch="$branch" \ + -f status=failure \ + -f created=">=${since}" \ + --paginate \ + --jq '.workflow_runs[] | [.id, .html_url, .path, .head_branch, .created_at] | @tsv' \ + >> "$runs_file" || true + done + + while IFS=$'\t' read -r run_id run_url workflow_path head_branch created_at; do + [ -n "${run_id:-}" ] || continue + zip_file="/tmp/gh-aw/agent/workflow-logs-${run_id}.zip" + log_dir="/tmp/gh-aw/agent/workflow-logs-${run_id}" + + if ! gh api "repos/$GITHUB_REPOSITORY/actions/runs/${run_id}/logs" -H "Accept: application/vnd.github+json" > "$zip_file" 2>/dev/null; then + continue + fi + rm -rf "$log_dir" + if ! unzip -o "$zip_file" -d "$log_dir" >/dev/null 2>&1; then + continue + fi + + match="$(grep -R -n -m 3 "Resource not accessible by integration" "$log_dir" 2>/dev/null || true)" + if [ -n "$match" ]; then + evidence="${match//$'\t'/ }" + evidence="${evidence//$'\n'/ | }" + printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$workflow_path" "$head_branch" "$run_id" "$run_url" "$created_at" "$evidence" >> "$findings_file" + fi + rm -rf "$log_dir" "$zip_file" + done < "$runs_file" + + matches="$(tail -n +2 "$findings_file" | wc -l | tr -d ' ')" + workflows="$(tail -n +2 "$findings_file" | cut -f1 | sort -u | wc -l | tr -d ' ')" + { + echo "since=${since}" + echo "look_back_days=${LOOK_BACK_DAYS}" + echo "matched_runs=${matches}" + echo "matched_workflows=${workflows}" + echo "findings_file=${findings_file}" + } > /tmp/gh-aw/agent/resource-not-accessible-summary.txt + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +# Resource Not Accessible By Integration Detector + +Use the prescan output to investigate only workflows that already matched `Resource not accessible by integration`, then create a single tracking issue with the combined analysis. + +## Context + +- **Repository**: ${{ github.repository }} +- **Default Branch**: ${{ github.event.repository.default_branch }} +- **Additional long-term branches**: ${{ inputs.long-term-branches }} +- **Look-back days**: ${{ inputs.look-back-days }} +- **Error pattern**: `Resource not accessible by integration` +- **Prescan summary**: `/tmp/gh-aw/agent/resource-not-accessible-summary.txt` +- **Prescan findings**: `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv` +## Constraints + +- **CAN**: Read files, search code, run commands, create one issue. +- **CANNOT**: Push changes or open PRs in this workflow. +- Only investigate workflows listed in `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv`. +- Do not file a duplicate issue if an open `${{ inputs.issue-title-prefix }}` issue already tracks the same workflows and failure pattern. + +## Permission reference + +`Resource not accessible by integration` means the `GITHUB_TOKEN` lacks a required scope. Common causes: + +| Failed operation | Required permission | +| --- | --- | +| Create/update issues | `issues: write` | +| Create/update pull requests | `pull-requests: write` | +| Push code or tags | `contents: write` | +| Create releases | `contents: write` | +| Publish packages | `packages: write` | +| Trigger other workflows | `actions: write` | +| Manage deployments | `deployments: write` | +| Create/update checks | `checks: write` | +| Comment on PRs | `pull-requests: write` | + +Common root causes: +- **Missing `permissions:` block** — the workflow relies on the repo/org default token permissions which are too restrictive. +- **Fork PRs** — `pull_request` from forks always gets a read-only token. Use `pull_request_target` (with caution) or a GitHub App token. +- **Organization policies** — org-level settings may cap the maximum token permissions. + +The fix is to add an explicit `permissions:` block at the workflow or job level granting only the minimum required scopes. For each affected workflow, read its source file under `.github/workflows/`, identify the operation that failed from the evidence, and recommend the specific permission to add. + +## Step 1: Gather context + +1. Call `generate_agents_md` to get repository conventions (if it fails, continue). +2. Read `/tmp/gh-aw/agent/resource-not-accessible-summary.txt`. +3. Read `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv`. + +## Step 2: Decide whether to noop + +- If the findings file has no data rows, call `noop` with: + `No 'Resource not accessible by integration' failures found in the configured look-back window — nothing to report`. +- Check open issues for `${{ inputs.issue-title-prefix }}` in the title and compare workflow paths/evidence. +- If an existing open issue already tracks the same findings, call `noop` and reference the existing issue number. + +## Step 3: Investigate each affected workflow + +For each workflow in the findings file: +1. Read the workflow source file from `.github/workflows/`. +2. Identify which operation failed from the evidence lines. +3. Check if the workflow already has a `permissions:` block and what scopes are granted. +4. Determine the minimum permission fix needed. + +## Step 4: Produce combined analysis issue + +Call `create_issue` exactly once with: + +- **Title**: A short descriptive title summarizing the affected workflows (do NOT repeat the issue-title-prefix in the title) +- **Body**: + + ```` + ## Scan Summary + + - Look-back days: + - Since: + - Matched workflows: + - Matched runs: + + ## Affected Workflows + + | Workflow file | Branches | Runs | + | --- | --- | --- | + | | | [](), ... | + + ## Evidence + + For each workflow include one or more verbatim evidence lines from the findings file. + + ## Root Cause Assessment + + For each workflow, explain which operation failed and why the current permissions are insufficient. + + ## Remediation + + For each workflow, provide the exact `permissions:` block to add or modify. Use before/after YAML snippets. Grant only the minimum required scopes. + + ## Next Steps + + - Apply the permission fixes manually under `.github/workflows/`. + ```` + +${{ inputs.additional-instructions }} + diff --git a/docs/workflows/gh-agent-workflows.md b/docs/workflows/gh-agent-workflows.md index cfbfdb31..bcd6cbf2 100644 --- a/docs/workflows/gh-agent-workflows.md +++ b/docs/workflows/gh-agent-workflows.md @@ -122,6 +122,7 @@ These workflows are tailored for Elastic's internal tooling and documentation pl | Workflow | Trigger | Description | | --- | --- | --- | | [Downstream Health (Elastic-specific)](gh-agent-workflows/estc-downstream-health.md) | Daily schedule | Monitor downstream Elastic repo quality | +| [Resource Not Accessible Detector (Elastic-specific)](gh-agent-workflows/estc-actions-resource-not-accessible-detector.md) | Daily schedule | Detect `Resource not accessible by integration` CI errors and file one combined tracking issue | ## Secrets diff --git a/gh-agent-workflows/README.md b/gh-agent-workflows/README.md index 6bb7f3e0..22a67c2b 100644 --- a/gh-agent-workflows/README.md +++ b/gh-agent-workflows/README.md @@ -31,7 +31,6 @@ Pre-built workflows with domain-specific prompts. These import the same base fra - [Product Manager Impersonator](product-manager-impersonator/) — propose well-researched new feature ideas - [Refactor Opportunist](refactor-opportunist/) — pitch proven refactors with partial implementations - [Stale Issues](stale-issues/) — detect stale issues - **Fixers** (create PRs): - [Bug Exterminator](bug-exterminator/) — fix bug-hunter issues - [Text Beautifier](text-beautifier/) — fix text-auditor issues @@ -90,4 +89,4 @@ These workflows are tailored for Elastic's internal tooling, documentation platf - [Docs Patrol External (Elastic-specific)](estc-docs-patrol-external/) — detect stale published Elastic documentation - [Newbie Contributor Patrol External (Elastic-specific)](estc-newbie-contributor-patrol-external/) — cross-reference repo docs against published Elastic documentation - [Downstream Health (Elastic-specific)](estc-downstream-health/) — monitor downstream Elastic repositories using AI workflows - +- [Resource Not Accessible Detector (Elastic-specific)](estc-actions-resource-not-accessible-detector/) — detect `Resource not accessible by integration` CI errors and file one combined tracking issue diff --git a/gh-agent-workflows/estc-actions-resource-not-accessible-detector/README.md b/gh-agent-workflows/estc-actions-resource-not-accessible-detector/README.md new file mode 100644 index 00000000..28a07552 --- /dev/null +++ b/gh-agent-workflows/estc-actions-resource-not-accessible-detector/README.md @@ -0,0 +1,77 @@ +# Resource Not Accessible By Integration Detector + +Daily detector that scans for `Resource not accessible by integration` errors across long-term branches and opens one combined tracking issue. + +## How it works + +Runs once every 24 hours (or manually). A prescan script runs before the agent prompt: it queries failed workflow runs from the configured look-back window on the default branch and any configured long-term (release) branches, downloads logs, searches for the exact error text `Resource not accessible by integration`, and writes matches to `/tmp/gh-aw/agent/resource-not-accessible-findings.tsv`. The agent then analyzes only those prescanned workflows and opens **one combined issue** with the results. If no matching failures are found, the run ends with `noop`. + +The generated issue: +- includes grouped workflow/run links plus verbatim evidence lines; +- provides a root-cause assessment and remediation guidance; +- avoids reposting when an equivalent open issue already exists. + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/estc-actions-resource-not-accessible-detector/example.yml \ + -o .github/workflows/estc-actions-resource-not-accessible-detector.yml +``` + +See [example.yml](example.yml) for the full workflow file. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Daily (06:00 UTC) | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `long-term-branches` | Space-separated list of long-term branch names to scan in addition to the default branch (e.g. `'8.x 7.17'`) | No | `""` | +| `look-back-days` | Number of days to look back when scanning failed workflow runs | No | `1` | +| `issue-title-prefix` | Title prefix used for the combined issue and dedup checks | No | `[resource-not-accessible-by-integration]` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | + +## Safe Outputs + +- `create-issue` — open one combined issue with analysis for all affected workflows +- `noop` — emitted when no matching failures are found + +## Behavior details + +| Scenario | Outcome | +| --- | --- | +| No `Resource not accessible by integration` failures in look-back window | `noop` — no issue opened | +| One workflow fails on one branch | Combined issue includes one workflow entry | +| Same workflow fails on multiple branches | Combined issue includes all affected branches/runs under one workflow | +| Multiple distinct workflows fail | Combined issue includes all workflows in one report | +| Findings already tracked by an open prefixed issue | `noop` — avoid duplicate repost | + +## Remediation guidance + +The agent includes a built-in permission reference table mapping failed GitHub API operations to required `GITHUB_TOKEN` scopes. For each affected workflow it reads the source file, identifies the failing operation from log evidence, and recommends the minimum `permissions:` block to add. + +## Similar behavior with base Scheduled Audit + +If you prefer a generic setup, you can get similar behavior with [Scheduled Audit](../scheduled-audit/) by: +- setting an issue title prefix dedicated to this error class, +- adding instructions to prescan recent failed runs/logs for `Resource not accessible by integration`, +- emitting one combined issue and `noop` when no findings or already tracked findings exist. + +## Required permissions + +The caller workflow must grant: + +```yaml +permissions: + actions: read + contents: read + issues: write +``` diff --git a/gh-agent-workflows/estc-actions-resource-not-accessible-detector/example.yml b/gh-agent-workflows/estc-actions-resource-not-accessible-detector/example.yml new file mode 100644 index 00000000..83ab7727 --- /dev/null +++ b/gh-agent-workflows/estc-actions-resource-not-accessible-detector/example.yml @@ -0,0 +1,24 @@ +name: ESTC Actions Resource Not Accessible Detector +on: + schedule: + - cron: "0 6 * * *" + workflow_dispatch: + inputs: + look-back-days: + description: "Number of look-back days for failed-run scan" + required: false + default: "1" + +permissions: + actions: read + issues: write + contents: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-estc-actions-resource-not-accessible-detector.lock.yml@v0 + with: + long-term-branches: "" + look-back-days: ${{ inputs.look-back-days || 1 }} + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/mkdocs.yml b/mkdocs.yml index 30cf0047..d2188d59 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,6 +74,7 @@ nav: - Docs Patrol External (Elastic-specific): workflows/gh-agent-workflows/estc-docs-patrol-external.md - Newbie Contributor Patrol External (Elastic-specific): workflows/gh-agent-workflows/estc-newbie-contributor-patrol-external.md - Downstream Health (Elastic-specific): workflows/gh-agent-workflows/estc-downstream-health.md + - Resource Not Accessible Detector (Elastic-specific): workflows/gh-agent-workflows/estc-actions-resource-not-accessible-detector.md - Legacy: - Claude Workflows: workflows/claude-workflows.md - Migration Guide: migration-guide.md diff --git a/scripts/dogfood.sh b/scripts/dogfood.sh index f644b3e0..23d02186 100755 --- a/scripts/dogfood.sh +++ b/scripts/dogfood.sh @@ -18,6 +18,7 @@ cd "$REPO_ROOT" # Workflows that are not dogfooded in this repository. EXCLUDED_WORKFLOWS=( + "estc-actions-resource-not-accessible-detector" "estc-docs-patrol-external" "estc-newbie-contributor-patrol-external" "flaky-test-investigator"