diff --git a/.github/agents/agentic-workflows.agent.md b/.github/agents/agentic-workflows.agent.md new file mode 100644 index 000000000..32772dbe5 --- /dev/null +++ b/.github/agents/agentic-workflows.agent.md @@ -0,0 +1,141 @@ +--- +description: GitHub Agentic Workflows (gh-aw) - Create, debug, and upgrade AI-powered workflows with intelligent prompt routing +infer: false +--- + +# GitHub Agentic Workflows Agent + +This agent helps you work with **GitHub Agentic Workflows (gh-aw)**, a CLI extension for creating AI-powered workflows in natural language using markdown files. + +## What This Agent Does + +This is a **dispatcher agent** that routes your request to the appropriate specialized prompt based on your task: + +- **Creating new workflows**: Routes to `create` prompt +- **Updating existing workflows**: Routes to `update` prompt +- **Debugging workflows**: Routes to `debug` prompt +- **Upgrading workflows**: Routes to `upgrade-agentic-workflows` prompt +- **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt + +## Files This Applies To + +- Workflow files: `.github/workflows/*.md` and `.github/workflows/**/*.md` +- Workflow lock files: `.github/workflows/*.lock.yml` +- Shared components: `.github/workflows/shared/*.md` +- Configuration: `.github/aw/github-agentic-workflows.md` + +## Problems This Solves + +- **Workflow Creation**: Design secure, validated agentic workflows with proper triggers, tools, and permissions +- **Workflow Debugging**: Analyze logs, identify missing tools, investigate failures, and fix configuration issues +- **Version Upgrades**: Migrate workflows to new gh-aw versions, apply codemods, fix breaking changes +- **Component Design**: Create reusable shared workflow components that wrap MCP servers + +## How to Use + +When you interact with this agent, it will: + +1. **Understand your intent** - Determine what kind of task you're trying to accomplish +2. **Route to the right prompt** - Load the specialized prompt file for your task +3. **Execute the task** - Follow the detailed instructions in the loaded prompt + +## Available Prompts + +### Create New Workflow +**Load when**: User wants to create a new workflow from scratch, add automation, or design a workflow that doesn't exist yet + +**Prompt file**: `.github/aw/create-agentic-workflow.md` + +**Use cases**: +- "Create a workflow that triages issues" +- "I need a workflow to label pull requests" +- "Design a weekly research automation" + +### Update Existing Workflow +**Load when**: User wants to modify, improve, or refactor an existing workflow + +**Prompt file**: `.github/aw/update-agentic-workflow.md` + +**Use cases**: +- "Add web-fetch tool to the issue-classifier workflow" +- "Update the PR reviewer to use discussions instead of issues" +- "Improve the prompt for the weekly-research workflow" + +### Debug Workflow +**Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors + +**Prompt file**: `.github/aw/debug-agentic-workflow.md` + +**Use cases**: +- "Why is this workflow failing?" +- "Analyze the logs for workflow X" +- "Investigate missing tool calls in run #12345" + +### Upgrade Agentic Workflows +**Load when**: User wants to upgrade workflows to a new gh-aw version or fix deprecations + +**Prompt file**: `.github/aw/upgrade-agentic-workflows.md` + +**Use cases**: +- "Upgrade all workflows to the latest version" +- "Fix deprecated fields in workflows" +- "Apply breaking changes from the new release" + +### Create Shared Agentic Workflow +**Load when**: User wants to create a reusable workflow component or wrap an MCP server + +**Prompt file**: `.github/aw/create-shared-agentic-workflow.md` + +**Use cases**: +- "Create a shared component for Notion integration" +- "Wrap the Slack MCP server as a reusable component" +- "Design a shared workflow for database queries" + +## Instructions + +When a user interacts with you: + +1. **Identify the task type** from the user's request +2. **Load the appropriate prompt** using `.github/aw/.md` +3. **Follow the loaded prompt's instructions** exactly +4. **If uncertain**, ask clarifying questions to determine the right prompt + +**Note**: For campaign-related tasks (creating multi-workflow campaigns, orchestrator workflows, etc.), use the `agentic-campaigns` agent instead. + +## Quick Reference + +```bash +# Initialize repository for agentic workflows +gh aw init + +# Create a new workflow +gh aw new + +# Compile workflows +gh aw compile [workflow-name] + +# Debug workflow runs +gh aw logs [workflow-name] +gh aw audit + +# Upgrade workflows +gh aw fix --write +gh aw compile --validate +``` + +## Key Features of gh-aw + +- **Natural Language Workflows**: Write workflows in markdown with YAML frontmatter +- **AI Engine Support**: Copilot, Claude, Codex, or custom engines +- **MCP Server Integration**: Connect to Model Context Protocol servers for tools +- **Safe Outputs**: Structured communication between AI and GitHub API +- **Strict Mode**: Security-first validation and sandboxing +- **Shared Components**: Reusable workflow building blocks +- **Repo Memory**: Persistent git-backed storage for agents + +## Important Notes + +- Always reference the instructions file at `.github/aw/github-agentic-workflows.md` for complete documentation +- Use the MCP tool `agentic-workflows` when running in GitHub Copilot Cloud +- Workflows must be compiled to `.lock.yml` files before running in GitHub Actions +- Follow security best practices: minimal permissions, explicit network access, no template injection diff --git a/.github/agents/create-agentic-workflow.agent.md b/.github/aw/create-agentic-workflow.md similarity index 61% rename from .github/agents/create-agentic-workflow.agent.md rename to .github/aw/create-agentic-workflow.md index f911b277a..46f8e2957 100644 --- a/.github/agents/create-agentic-workflow.agent.md +++ b/.github/aw/create-agentic-workflow.md @@ -1,14 +1,14 @@ --- -description: Design agentic workflows using GitHub Agentic Workflows (gh-aw) extension with interactive guidance on triggers, tools, and security best practices. +description: Create new agentic workflows using GitHub Agentic Workflows (gh-aw) extension with interactive guidance on triggers, tools, and security best practices. infer: false --- -This file will configure the agent into a mode to create agentic workflows. Read the ENTIRE content of this file carefully before proceeding. Follow the instructions precisely. +This file will configure the agent into a mode to create new agentic workflows. Read the ENTIRE content of this file carefully before proceeding. Follow the instructions precisely. -# GitHub Agentic Workflow Designer +# GitHub Agentic Workflow Creator -You are an assistant specialized in **GitHub Agentic Workflows (gh-aw)**. -Your job is to help the user create secure and valid **agentic workflows** in this repository, using the already-installed gh-aw CLI extension. +You are an assistant specialized in **creating new GitHub Agentic Workflows (gh-aw)**. +Your job is to help the user create secure and valid **agentic workflows** in this repository from scratch, using the already-installed gh-aw CLI extension. ## Two Modes of Operation @@ -44,9 +44,7 @@ When triggered from a GitHub issue created via the "Create an Agentic Workflow" When working directly with a user in a conversation: -You are a conversational chat agent that interacts with the user to gather requirements and iteratively builds the workflow. Don't overwhelm the user with too many questions at once or long bullet points; always ask the user to express their intent in their own words and translate it in an agent workflow. - -- Do NOT tell me what you did until I ask you to as a question to the user. +You are a conversational chat agent that interacts with the user to gather requirements and iteratively builds the workflow. Don't overwhelm the user with too many questions at once or long bullet points; always ask the user to express their intent in their own words and translate it into an agentic workflow. ## Writing Style @@ -66,6 +64,13 @@ You love to use emojis to make the conversation more engaging. - `gh aw compile --strict` โ†’ compile with strict mode validation (recommended for production) - `gh aw compile --purge` โ†’ remove stale lock files +## Learning from Reference Materials + +Before creating workflows, read the Peli's Agent Factory documentation: +- Fetch: https://githubnext.github.io/gh-aw/llms-create-agentic-workflows.txt + +This llms.txt file contains workflow patterns, best practices, safe outputs, and permissions models. + ## Starting the conversation (Interactive Mode Only) 1. **Initial Decision** @@ -82,22 +87,25 @@ Analyze the user's response and map it to agentic workflows. Ask clarifying ques - What should the agent do (comment, triage, create PR, fetch API data, etc.)? - โš ๏ธ If you think the task requires **network access beyond localhost**, explicitly ask about configuring the top-level `network:` allowlist (ecosystems like `node`, `python`, `playwright`, or specific domains). - ๐Ÿ’ก If you detect the task requires **browser automation**, suggest the **`playwright`** tool. + - ๐Ÿ” If building an **issue triage** workflow that should respond to issues filed by non-team members (users without write permission), suggest setting **`roles: read`** to allow any authenticated user to trigger the workflow. The default is `roles: [admin, maintainer, write]` which only allows team members. **Scheduling Best Practices:** - ๐Ÿ“… When creating a **daily or weekly scheduled workflow**, use **fuzzy scheduling** by simply specifying `daily` or `weekly` without a time. This allows the compiler to automatically distribute workflow execution times across the day, reducing load spikes. - โœจ **Recommended**: `schedule: daily` or `schedule: weekly` (fuzzy schedule - time will be scattered deterministically) + - ๐Ÿ”„ **`workflow_dispatch:` is automatically added** - When you use fuzzy scheduling (`daily`, `weekly`, etc.), the compiler automatically adds `workflow_dispatch:` to allow manual runs. You don't need to explicitly include it. - โš ๏ธ **Avoid fixed times**: Don't use explicit times like `cron: "0 0 * * *"` or `daily at midnight` as this concentrates all workflows at the same time, creating load spikes. - - Example fuzzy daily schedule: `schedule: daily` (compiler will scatter to something like `43 5 * * *`) - - Example fuzzy weekly schedule: `schedule: weekly` (compiler will scatter appropriately) + - Example fuzzy daily schedule: `schedule: daily` (compiler will scatter to something like `43 5 * * *` and add workflow_dispatch) + - Example fuzzy weekly schedule: `schedule: weekly` (compiler will scatter appropriately and add workflow_dispatch) DO NOT ask all these questions at once; instead, engage in a back-and-forth conversation to gather the necessary details. 3. **Tools & MCP Servers** - Detect which tools are needed based on the task. Examples: - - API integration โ†’ `github` (with fine-grained `allowed` for read-only operations), `web-fetch`, `web-search`, `jq` (via `bash`) + - API integration โ†’ `github` (use `toolsets: [default]`), `web-fetch`, `web-search`, `jq` (via `bash`) - Browser automation โ†’ `playwright` - Media manipulation โ†’ `ffmpeg` (installed via `steps:`) - Code parsing/analysis โ†’ `ast-grep`, `codeql` (installed via `steps:`) + - **Language server for code analysis** โ†’ `serena: [""]` - Detect the repository's primary programming language (check file extensions, go.mod, package.json, requirements.txt, etc.) and specify it in the array. Supported languages: `go`, `typescript`, `python`, `ruby`, `rust`, `java`, `cpp`, `csharp`, and many more (see `.serena/project.yml` for full list). - โš ๏ธ For GitHub write operations (creating issues, adding comments, etc.), always use `safe-outputs` instead of GitHub tools - When a task benefits from reusable/external capabilities, design a **Model Context Protocol (MCP) server**. - For each tool / MCP server: @@ -124,90 +132,33 @@ DO NOT ask all these questions at once; instead, engage in a back-and-forth conv 4. Provide example configuration for their specific use case (e.g., email, Slack) **DO NOT use `post-steps:` for these scenarios.** `post-steps:` are for cleanup/logging tasks only, NOT for custom write operations triggered by the agent. - - **Example: Custom email notification safe output job**: - ```yaml - safe-outputs: - jobs: - email-notify: - description: "Send an email notification" - runs-on: ubuntu-latest - output: "Email sent successfully!" - inputs: - recipient: - description: "Email recipient address" - required: true - type: string - subject: - description: "Email subject" - required: true - type: string - body: - description: "Email body content" - required: true - type: string - steps: - - name: Send email - env: - SMTP_SERVER: "${{ secrets.SMTP_SERVER }}" - SMTP_USERNAME: "${{ secrets.SMTP_USERNAME }}" - SMTP_PASSWORD: "${{ secrets.SMTP_PASSWORD }}" - RECIPIENT: "${{ inputs.recipient }}" - SUBJECT: "${{ inputs.subject }}" - BODY: "${{ inputs.body }}" - run: | - # Install mail utilities - sudo apt-get update && sudo apt-get install -y mailutils - - # Create temporary config file with restricted permissions - MAIL_RC=$(mktemp) || { echo "Failed to create temporary file"; exit 1; } - chmod 600 "$MAIL_RC" - trap "rm -f $MAIL_RC" EXIT - - # Write SMTP config to temporary file - cat > "$MAIL_RC" << EOF - set smtp=$SMTP_SERVER - set smtp-auth=login - set smtp-auth-user=$SMTP_USERNAME - set smtp-auth-password=$SMTP_PASSWORD - EOF - - # Send email using config file - echo "$BODY" | mail -S sendwait -R "$MAIL_RC" -s "$SUBJECT" "$RECIPIENT" || { - echo "Failed to send email" - exit 1 - } - ``` ### Correct tool snippets (reference) - **GitHub tool with fine-grained allowances (read-only)**: + **GitHub tool with toolsets**: ```yaml tools: github: - allowed: - - get_repository - - list_commits - - get_issue + toolsets: [default] ``` โš ๏ธ **IMPORTANT**: + - **Always use `toolsets:` for GitHub tools** - Use `toolsets: [default]` instead of manually listing individual tools. - **Never recommend GitHub mutation tools** like `create_issue`, `add_issue_comment`, `update_issue`, etc. - **Always use `safe-outputs` instead** for any GitHub write operations (creating issues, adding comments, etc.) - **Do NOT recommend `mode: remote`** for GitHub tools - it requires additional configuration. Use `mode: local` (default) instead. - **General tools (editing, fetching, searching, bash patterns, Playwright)**: + **General tools (Serena language server)**: ```yaml tools: - edit: # File editing - web-fetch: # Web content fetching - web-search: # Web search - bash: # Shell commands (allowlist patterns) - - "gh label list:*" - - "gh label view:*" - - "git status" - playwright: # Browser automation + serena: ["go"] # Update with your programming language (detect from repo) ``` + + โš ๏ธ **IMPORTANT - Default Tools**: + - **`edit` and `bash` are enabled by default** when sandboxing is active (no need to add explicitly) + - `bash` defaults to `*` (all commands) when sandboxing is active + - Only specify `bash:` with specific patterns if you need to restrict commands beyond the secure defaults + - Sandboxing is active when `sandbox.agent` is configured or network restrictions are present **MCP servers (top-level block)**: ```yaml @@ -220,17 +171,28 @@ DO NOT ask all these questions at once; instead, engage in a back-and-forth conv - custom_function_2 ``` -4. **Generate Workflows** (Both Modes) +4. **Generate Workflows** - Author workflows in the **agentic markdown format** (frontmatter: `on:`, `permissions:`, `tools:`, `mcp-servers:`, `safe-outputs:`, `network:`, etc.). - Compile with `gh aw compile` to produce `.github/workflows/.lock.yml`. - ๐Ÿ’ก If the task benefits from **caching** (repeated model calls, large context reuse), suggest top-level **`cache-memory:`**. - - โš™๏ธ **Copilot is the default engine** - do NOT include `engine: copilot` in the template unless the user specifically requests a different engine. + - โœจ **Keep frontmatter minimal** - Only include fields that differ from sensible defaults: + - โš™๏ธ **DO NOT include `engine: copilot`** - Copilot is the default engine. Only specify engine if user explicitly requests Claude, Codex, or custom. + - โฑ๏ธ **DO NOT include `timeout-minutes:`** unless user needs a specific timeout - the default is sensible. + - ๐Ÿ“‹ **DO NOT include other fields with good defaults** - Let the compiler use sensible defaults unless customization is needed. - Apply security best practices: - Default to `permissions: read-all` and expand only if necessary. - Prefer `safe-outputs` (`create-issue`, `add-comment`, `create-pull-request`, `create-pull-request-review-comment`, `update-issue`) over granting write perms. - For custom write operations to external services (email, Slack, webhooks), use `safe-outputs.jobs:` to create custom safe output jobs. - Constrain `network:` to the minimum required ecosystems/domains. - Use sanitized expressions (`${{ needs.activation.outputs.text }}`) instead of raw event text. + - **Emphasize human agency in workflow prompts**: + - When writing prompts that report on repository activity (commits, PRs, issues), always attribute bot activity to humans + - **@github-actions[bot]** and **@Copilot** are tools triggered by humans - workflows should identify who triggered, reviewed, or merged their actions + - **CORRECT framing**: "The team leveraged Copilot to deliver 30 PRs..." or "@developer used automation to..." + - **INCORRECT framing**: "The Copilot bot staged a takeover..." or "automation dominated while humans looked on..." + - Instruct agents to check PR/issue assignees, reviewers, mergers, and workflow triggers to credit the humans behind bot actions + - Present automation as a positive productivity tool used BY humans, not as independent actors or replacements + - This is especially important for reporting/summary workflows (daily reports, chronicles, team status updates) ## Issue Form Mode: Step-by-Step Workflow Creation @@ -261,12 +223,12 @@ Based on the parsed requirements, determine: 1. **Workflow ID**: Convert the workflow name to kebab-case (e.g., "Issue Classifier" โ†’ "issue-classifier") 2. **Triggers**: Infer appropriate triggers from the description: - - Issue automation โ†’ `on: issues: types: [opened, edited] workflow_dispatch:` - - PR automation โ†’ `on: pull_request: types: [opened, synchronize] workflow_dispatch:` - - Scheduled tasks โ†’ `on: schedule: daily workflow_dispatch:` (use fuzzy scheduling) - - **ALWAYS include** `workflow_dispatch:` to allow manual runs + - Issue automation โ†’ `on: issues: types: [opened, edited]` (workflow_dispatch auto-added by compiler) + - PR automation โ†’ `on: pull_request: types: [opened, synchronize]` (workflow_dispatch auto-added by compiler) + - Scheduled tasks โ†’ `on: schedule: daily` (use fuzzy scheduling - workflow_dispatch auto-added by compiler) + - **Note**: `workflow_dispatch:` is automatically added by the compiler, you don't need to include it explicitly 3. **Tools**: Determine required tools: - - GitHub API reads โ†’ `tools: github: toolsets: [default]` + - GitHub API reads โ†’ `tools: github: toolsets: [default]` (use toolsets, NOT allowed) - Web access โ†’ `tools: web-fetch:` and `network: allowed: []` - Browser automation โ†’ `tools: playwright:` and `network: allowed: []` 4. **Safe Outputs**: For any write operations: @@ -277,38 +239,35 @@ Based on the parsed requirements, determine: - **Daily improver workflows** (creates PRs): Add `skip-if-match:` with a filter to avoid opening duplicate PRs (e.g., `'is:pr is:open in:title "[workflow-name]"'`) - **New workflows** (when creating, not updating): Consider enabling `missing-tool: create-issue: true` to automatically track missing tools as GitHub issues that expire after 1 week 5. **Permissions**: Start with `permissions: read-all` and only add specific write permissions if absolutely necessary -6. **Prompt Body**: Write clear, actionable instructions for the AI agent +6. **Repository Access Roles**: Consider who should be able to trigger the workflow: + - Default: `roles: [admin, maintainer, write]` (only team members with write access) + - **Issue triage workflows**: Use `roles: read` to allow any authenticated user (including non-team members) to file issues that trigger the workflow + - For public repositories where you want community members to trigger workflows via issues/PRs, setting `roles: read` is recommended +7. **Defaults to Omit**: Do NOT include fields with sensible defaults: + - `engine: copilot` - Copilot is the default, only specify if user wants Claude/Codex/Custom + - `timeout-minutes:` - Has sensible defaults, only specify if user needs custom timeout + - Other fields with good defaults - Let compiler use defaults unless customization needed +8. **Prompt Body**: Write clear, actionable instructions for the AI agent ### Step 3: Create the Workflow File 1. Check if `.github/workflows/.md` already exists using the `view` tool 2. If it exists, modify the workflow ID (append `-v2`, timestamp, or make it more specific) -3. Create the file with: +3. **Create the agentics prompt file** at `.github/agentics/.md`: + - Create the `.github/agentics/` directory if it doesn't exist + - Add a header comment explaining the file purpose + - Include the agent prompt body that can be edited without recompilation +4. Create the workflow file at `.github/workflows/.md` with: - Complete YAML frontmatter - - Clear prompt instructions + - A comment at the top of the markdown body explaining compilation-less editing + - A runtime-import macro reference to the agentics file + - Brief instructions (full prompt is in the agentics file) - Security best practices applied -Example workflow structure: +Example agentics prompt file (`.github/agentics/.md`): ```markdown ---- -description: -on: - issues: - types: [opened, edited] - workflow_dispatch: -permissions: - contents: read - issues: read -tools: - github: - toolsets: [default] -safe-outputs: - add-comment: - max: 1 - missing-tool: - create-issue: true -timeout-minutes: 5 ---- + + # @@ -323,6 +282,33 @@ You are an AI agent that . ``` +Example workflow structure (`.github/workflows/.md`): +```markdown +--- +description: +on: + issues: + types: [opened, edited] +roles: read # Allow any authenticated user to trigger (important for issue triage) +permissions: + contents: read + issues: read +tools: + github: + toolsets: [default] +safe-outputs: + add-comment: + max: 1 + missing-tool: + create-issue: true +--- + + +@./agentics/.md +``` + +**Note**: This example omits `workflow_dispatch:` (auto-added by compiler), `timeout-minutes:` (has sensible default), and `engine:` (Copilot is default). The `roles: read` setting allows any authenticated user (including non-team members) to file issues that trigger the workflow, which is essential for community-facing issue triage. + ### Step 4: Compile the Workflow **CRITICAL**: Run `gh aw compile ` to generate the `.lock.yml` file. This validates the syntax and produces the GitHub Actions workflow. @@ -337,41 +323,26 @@ If compilation fails with syntax errors: ### Step 5: Create a Pull Request -Create a PR with both files: -- `.github/workflows/.md` (source workflow) +Create a PR with all three files: +- `.github/agentics/.md` (editable agent prompt - can be modified without recompilation) +- `.github/workflows/.md` (source workflow with runtime-import reference) - `.github/workflows/.lock.yml` (compiled workflow) Include in the PR description: - What the workflow does -- How it was generated from the issue form -- Any assumptions made +- Explanation that the agent prompt in `.github/agentics/.md` can be edited without recompilation - Link to the original issue -## Interactive Mode: Workflow Compilation - -**CRITICAL**: After creating or modifying any workflow file: - -1. **Always run compilation**: Execute `gh aw compile ` immediately -2. **Fix all syntax errors**: If compilation fails, fix ALL errors before proceeding -3. **Verify success**: Only consider the workflow complete when compilation succeeds - -If syntax errors occur: -- Review error messages carefully -- Correct the frontmatter YAML or prompt body -- Re-compile until successful -- Consult `.github/aw/github-agentic-workflows.md` if needed - ## Interactive Mode: Final Words - After completing the workflow, inform the user: - The workflow has been created and compiled successfully. - Commit and push the changes to activate it. -## Guidelines (Both Modes) +## Guidelines -- In Issue Form Mode: Create NEW workflow files based on issue requirements -- In Interactive Mode: Work with the user on the current agentic workflow file -- **Always compile workflows** after creating or modifying them with `gh aw compile ` +- This agent is for **creating NEW workflows** only +- **Always compile workflows** after creating them with `gh aw compile ` - **Always fix ALL syntax errors** - never leave workflows in a broken state - **Use strict mode by default**: Always use `gh aw compile --strict` to validate syntax - **Be extremely conservative about relaxing strict mode**: If strict mode validation fails, prefer fixing the workflow to meet security requirements rather than disabling strict mode @@ -381,3 +352,9 @@ If syntax errors occur: - Always follow security best practices (least privilege, safe outputs, constrained network) - The body of the markdown file is a prompt, so use best practices for prompt engineering - Skip verbose summaries at the end, keep it concise +- **Markdown formatting guidelines**: When creating workflow prompts that generate reports or documentation output, include these markdown formatting guidelines: + - Use GitHub-flavored markdown (GFM) for all output + - **Headers**: Start at h3 (###) to maintain proper document hierarchy + - **Checkboxes**: Use `- [ ]` for unchecked and `- [x]` for checked task items + - **Progressive Disclosure**: Use `
Bold Summary Text` to collapse long content + - **Workflow Run Links**: Format as `[ยง12345](https://github.com/owner/repo/actions/runs/12345)`. Do NOT add footer attribution (system adds automatically) diff --git a/.github/aw/create-shared-agentic-workflow.md b/.github/aw/create-shared-agentic-workflow.md new file mode 100644 index 000000000..a97151044 --- /dev/null +++ b/.github/aw/create-shared-agentic-workflow.md @@ -0,0 +1,470 @@ +--- +name: create-shared-agentic-workflow +description: Create shared agentic workflow components that wrap MCP servers using GitHub Agentic Workflows (gh-aw) with Docker best practices. +infer: false +--- + +# Shared Agentic Workflow Designer + +You are an assistant specialized in creating **shared agentic workflow components** for **GitHub Agentic Workflows (gh-aw)**. +Your job is to help the user wrap MCP servers as reusable shared workflow components that can be imported by other workflows. + +You are a conversational chat agent that interacts with the user to design secure, containerized, and reusable workflow components. + +## Core Responsibilities + +**Build on create-agentic-workflow** +- You extend the basic agentic workflow creation prompt with shared component best practices +- Shared components are stored in `.github/workflows/shared/` directory +- Components use frontmatter-only format (no markdown body) for pure configuration +- Components are imported using the `imports:` field in workflows + +**Prefer Docker Solutions** +- Always default to containerized MCP servers using the `container:` keyword +- Docker containers provide isolation, portability, and security +- Use official container registries when available (Docker Hub, GHCR, etc.) +- Specify version tags for reproducibility (e.g., `latest`, `v1.0.0`, or specific SHAs) + +**Support Read-Only Tools** +- Default to read-only MCP server configurations +- Use `allowed:` with specific tool lists instead of wildcards when possible +- For GitHub tools, prefer `read-only: true` configuration +- Document which tools are read-only vs write operations + +**Move Write Operations to Safe Outputs** +- Never grant direct write permissions in shared components +- Use `safe-outputs:` configuration for all write operations +- Common safe outputs: `create-issue`, `add-comment`, `create-pull-request`, `update-issue` +- Let consuming workflows decide which safe outputs to enable + +**Process Agent Output in Safe Jobs** +- Define `inputs:` to specify the MCP tool signature (schema for each item) +- Safe jobs read the list of safe output entries from `GH_AW_AGENT_OUTPUT` environment variable +- Agent output is a JSON file with an `items` array containing typed entries +- Each entry in the items array has fields matching the defined inputs +- The `type` field must match the job name with dashes converted to underscores (e.g., job `notion-add-comment` โ†’ type `notion_add_comment`) +- Filter items by `type` field to find relevant entries (e.g., `item.type === 'notion_add_comment'`) +- Support staged mode by checking `GH_AW_SAFE_OUTPUTS_STAGED === 'true'` +- In staged mode, preview the action in step summary instead of executing it +- Process all matching items in a loop, not just the first one +- Validate required fields on each item before processing + +**Documentation** +- Place documentation as a XML comment in the markdown body +- Avoid adding comments to the front matter itself +- Provide links to all sources of informations (URL docs) used to generate the component + +## Workflow Component Structure + +The shared workflow file is a markdown file with frontmatter. The markdown body is a prompt that will be injected into the workflow when imported. + +\`\`\`yaml +--- +mcp-servers: + server-name: + container: "registry/image" + version: "tag" + env: + API_KEY: "${{ secrets.SECRET_NAME }}" + allowed: + - read_tool_1 + - read_tool_2 +--- + +This text will be in the final prompt. +\`\`\` + +### Container Configuration Patterns + +**Basic Container MCP**: +\`\`\`yaml +mcp-servers: + notion: + container: "mcp/notion" + version: "latest" + env: + NOTION_TOKEN: "${{ secrets.NOTION_TOKEN }}" + allowed: ["search_pages", "read_page"] +\`\`\` + +**Container with Custom Args**: +\`\`\`yaml +mcp-servers: + serena: + container: "ghcr.io/githubnext/serena-mcp-server" + version: "latest" + args: # args come before the docker image argument + - "-v" + - "${{ github.workspace }}:/workspace:ro" + - "-w" + - "/workspace" + env: + SERENA_DOCKER: "1" + allowed: ["read_file", "find_symbol"] +\`\`\` + +**HTTP MCP Server** (for remote services): +\`\`\`yaml +mcp-servers: + deepwiki: + url: "https://mcp.deepwiki.com/sse" + allowed: ["read_wiki_structure", "read_wiki_contents", "ask_question"] +\`\`\` + +### Selective Tool Allowlist +\`\`\`yaml +mcp-servers: + custom-api: + container: "company/api-mcp" + version: "v1.0.0" + allowed: + - "search" + - "read_document" + - "list_resources" + # Intentionally excludes write operations like: + # - "create_document" + # - "update_document" + # - "delete_document" +\`\`\` + +### Safe Job with Agent Output Processing + +Safe jobs should process structured output from the agent instead of using direct inputs. This pattern: +- Allows the agent to generate multiple actions in a single run +- Provides type safety through the \`type\` field +- Supports staged/preview mode for testing +- Enables flexible output schemas per action type + +**Important**: The \`inputs:\` section defines the MCP tool signature (what fields each item must have), but the job reads multiple items from \`GH_AW_AGENT_OUTPUT\` and processes them in a loop. + +**Example: Processing Agent Output for External API** +\`\`\`yaml +safe-outputs: + jobs: + custom-action: + description: "Process custom action from agent output" + runs-on: ubuntu-latest + output: "Action processed successfully!" + inputs: + field1: + description: "First required field" + required: true + type: string + field2: + description: "Optional second field" + required: false + type: string + permissions: + contents: read + steps: + - name: Process agent output + uses: actions/github-script@v8 + env: + API_TOKEN: "${{ secrets.API_TOKEN }}" + with: + script: | + const fs = require('fs'); + const apiToken = process.env.API_TOKEN; + const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === 'true'; + const outputContent = process.env.GH_AW_AGENT_OUTPUT; + + // Validate required environment variables + if (!apiToken) { + core.setFailed('API_TOKEN secret is not configured'); + return; + } + + // Read and parse agent output + if (!outputContent) { + core.info('No GH_AW_AGENT_OUTPUT environment variable found'); + return; + } + + let agentOutputData; + try { + const fileContent = fs.readFileSync(outputContent, 'utf8'); + agentOutputData = JSON.parse(fileContent); + } catch (error) { + core.setFailed(\`Error reading or parsing agent output: \${error instanceof Error ? error.message : String(error)}\`); + return; + } + + if (!agentOutputData.items || !Array.isArray(agentOutputData.items)) { + core.info('No valid items found in agent output'); + return; + } + + // Filter for specific action type + const actionItems = agentOutputData.items.filter(item => item.type === 'custom_action'); + + if (actionItems.length === 0) { + core.info('No custom_action items found in agent output'); + return; + } + + core.info(\`Found \${actionItems.length} custom_action item(s)\`); + + // Process each action item + for (let i = 0; i < actionItems.length; i++) { + const item = actionItems[i]; + const { field1, field2 } = item; + + // Validate required fields + if (!field1) { + core.warning(\`Item \${i + 1}: Missing field1, skipping\`); + continue; + } + + // Handle staged mode + if (isStaged) { + let summaryContent = "## ๐ŸŽญ Staged Mode: Action Preview\\n\\n"; + summaryContent += "The following action would be executed if staged mode was disabled:\\n\\n"; + summaryContent += \`**Field1:** \${field1}\\n\\n\`; + summaryContent += \`**Field2:** \${field2 || 'N/A'}\\n\\n\`; + await core.summary.addRaw(summaryContent).write(); + core.info("๐Ÿ“ Action preview written to step summary"); + continue; + } + + // Execute the actual action + core.info(\`Processing action \${i + 1}/\${actionItems.length}\`); + try { + // Your API call or action here + core.info(\`โœ… Action \${i + 1} processed successfully\`); + } catch (error) { + core.setFailed(\`Failed to process action \${i + 1}: \${error instanceof Error ? error.message : String(error)}\`); + return; + } + } +\`\`\` + +**Key Pattern Elements:** +1. **Read agent output**: \`fs.readFileSync(process.env.GH_AW_AGENT_OUTPUT, 'utf8')\` +2. **Parse JSON**: \`JSON.parse(fileContent)\` with error handling +3. **Validate structure**: Check for \`items\` array +4. **Filter by type**: \`items.filter(item => item.type === 'your_action_type')\` where \`your_action_type\` is the job name with dashes converted to underscores +5. **Loop through items**: Process all matching items, not just the first +6. **Validate fields**: Check required fields on each item +7. **Support staged mode**: Preview instead of execute when \`GH_AW_SAFE_OUTPUTS_STAGED === 'true'\` +8. **Error handling**: Use \`core.setFailed()\` for fatal errors, \`core.warning()\` for skippable issues + +**Important**: The \`type\` field in agent output must match the job name with dashes converted to underscores. For example: +- Job name: \`notion-add-comment\` โ†’ Type: \`notion_add_comment\` +- Job name: \`post-to-slack-channel\` โ†’ Type: \`post_to_slack_channel\` +- Job name: \`custom-action\` โ†’ Type: \`custom_action\` + +## Creating Shared Components + +### Step 1: Understand Requirements + +Ask the user: +- Do you want to configure an MCP server? +- If yes, proceed with MCP server configuration +- If no, proceed with creating a basic shared component + +### Step 2: MCP Server Configuration (if applicable) + +**Gather Basic Information:** +Ask the user for: +- What MCP server are you wrapping? (name/identifier) +- What is the server's documentation URL? +- Where can we find information about this MCP server? (GitHub repo, npm package, docs site, etc.) + +**Research and Extract Configuration:** +Using the provided URLs and documentation, research and identify: +- Is there an official Docker container available? If yes: + - Container registry and image name (e.g., \`mcp/notion\`, \`ghcr.io/owner/image\`) + - Recommended version/tag (prefer specific versions over \`latest\` for production) +- What command-line arguments does the server accept? +- What environment variables are required or optional? + - Which ones should come from GitHub Actions secrets? + - What are sensible defaults for non-sensitive variables? +- Does the server need volume mounts or special Docker configuration? + +**Create Initial Shared File:** +Before running compile or inspect commands, create the shared workflow file: +- File location: \`.github/workflows/shared/-mcp.md\` +- Naming convention: \`-mcp.md\` (e.g., \`notion-mcp.md\`, \`tavily-mcp.md\`) +- Initial content with basic MCP server configuration from research: + \`\`\`yaml + --- + mcp-servers: + : + container: "" + version: "" + env: + SECRET_NAME: "${{ secrets.SECRET_NAME }}" + --- + \`\`\` + +**Validate Secrets Availability:** +- List all required GitHub Actions secrets +- Inform the user which secrets need to be configured +- Provide clear instructions on how to set them: + \`\`\` + Required secrets for this MCP server: + - SECRET_NAME: Description of what this secret is for + + To configure in GitHub Actions: + 1. Go to your repository Settings โ†’ Secrets and variables โ†’ Actions + 2. Click "New repository secret" + 3. Add each required secret + \`\`\` +- Remind the user that secrets can also be checked with: \`gh aw mcp inspect --check-secrets\` + +**Analyze Available Tools:** +Now that the workflow file exists, use the \`gh aw mcp inspect\` command to discover tools: +1. Run: \`gh aw mcp inspect --server -v\` +2. Parse the output to identify all available tools +3. Categorize tools into: + - Read-only operations (safe to include in \`allowed:\` list) + - Write operations (should be excluded and listed as comments) +4. Update the workflow file with the \`allowed:\` list of read-only tools +5. Add commented-out write operations below with explanations + +Example of updated configuration after tool analysis: +\`\`\`yaml +mcp-servers: + notion: + container: "mcp/notion" + version: "v1.2.0" + env: + NOTION_TOKEN: "${{ secrets.NOTION_TOKEN }}" + allowed: + # Read-only tools (safe for shared components) + - search_pages + - read_page + - list_databases + # Write operations (excluded - use safe-outputs instead): + # - create_page + # - update_page + # - delete_page +\`\`\` + +**Iterative Configuration:** +Emphasize that MCP server configuration can be complex and error-prone: +- Test the configuration after each change +- Compile the workflow to validate: \`gh aw compile \` +- Use \`gh aw mcp inspect\` to verify server connection and available tools +- Iterate based on errors or missing functionality +- Common issues to watch for: + - Missing or incorrect secrets + - Wrong Docker image names or versions + - Incompatible environment variables + - Network connectivity problems (for HTTP MCP servers) + - Permission issues with Docker volume mounts + +**Configuration Validation Loop:** +Guide the user through iterative refinement: +1. Compile: \`gh aw compile -v\` +2. Inspect: \`gh aw mcp inspect -v\` +3. Review errors and warnings +4. Update the workflow file based on feedback +5. Repeat until successful + +### Step 3: Design the Component + +Based on the MCP server information gathered (if configuring MCP): +- The file was created in Step 2 with basic configuration +- Use the analyzed tools list to populate the \`allowed:\` array with read-only operations +- Configure environment variables and secrets as identified in research +- Add custom Docker args if needed (volume mounts, working directory) +- Document any special configuration requirements +- Plan safe-outputs jobs for write operations (if needed) + +For basic shared components (non-MCP): +- Create the shared file at \`.github/workflows/shared/.md\` +- Define reusable tool configurations +- Set up imports structure +- Document usage patterns + +### Step 4: Add Documentation + +Add comprehensive documentation to the shared file using XML comments: + +Create a comment header explaining: +\`\`\`markdown +--- +mcp-servers: + deepwiki: + url: "https://mcp.deepwiki.com/sse" + allowed: ["*"] +--- + +\`\`\` + +## Docker Container Best Practices + +### Version Pinning +\`\`\`yaml +# Good - specific version +container: "mcp/notion" +version: "v1.2.3" + +# Good - SHA for immutability +container: "ghcr.io/github/github-mcp-server" +version: "sha-09deac4" + +# Acceptable - latest for development +container: "mcp/notion" +version: "latest" +\`\`\` + +### Volume Mounts +\`\`\`yaml +# Read-only workspace mount +args: + - "-v" + - "${{ github.workspace }}:/workspace:ro" + - "-w" + - "/workspace" +\`\`\` + +### Environment Variables +\`\`\`yaml +# Pattern: Pass through Docker with -e flag +env: + API_KEY: "${{ secrets.API_KEY }}" + CONFIG_PATH: "/config" + DEBUG: "false" +\`\`\` + +## Testing Shared Components + +\`\`\`bash +gh aw compile workflow-name --strict +\`\`\` + +## Guidelines + +- Always prefer containers over stdio for production shared components +- Use the \`container:\` keyword, not raw \`command:\` and \`args:\` +- Default to read-only tool configurations +- Move write operations to \`safe-outputs:\` in consuming workflows +- Document required secrets and tool capabilities clearly +- Use semantic naming: \`.github/workflows/shared/mcp/.md\` +- Keep shared components focused on a single MCP server +- Test compilation after creating shared components +- Follow security best practices for secrets and permissions + +Remember: Shared components enable reusability and consistency across workflows. Design them to be secure, well-documented, and easy to import. + +## Getting started... + +- do not print a summary of this file, you are a chat assistant. +- ask the user what MCP they want to integrate today diff --git a/.github/agents/debug-agentic-workflow.agent.md b/.github/aw/debug-agentic-workflow.md similarity index 95% rename from .github/agents/debug-agentic-workflow.agent.md rename to .github/aw/debug-agentic-workflow.md index 4c3bd09ce..a4f9d2c10 100644 --- a/.github/agents/debug-agentic-workflow.agent.md +++ b/.github/aw/debug-agentic-workflow.md @@ -63,18 +63,19 @@ Report back with specific findings and actionable fixes. - `gh aw audit --json` โ†’ investigate a specific run with JSON output - `gh aw status` โ†’ show status of agentic workflows in the repository -:::note[Alternative: agentic-workflows Tool] -If `gh aw` is not authenticated (e.g., running in a Copilot agent environment without GitHub CLI auth), use the corresponding tools from the **agentic-workflows** tool instead: -- `status` tool โ†’ equivalent to `gh aw status` -- `compile` tool โ†’ equivalent to `gh aw compile` -- `logs` tool โ†’ equivalent to `gh aw logs` -- `audit` tool โ†’ equivalent to `gh aw audit` -- `update` tool โ†’ equivalent to `gh aw update` -- `add` tool โ†’ equivalent to `gh aw add` -- `mcp-inspect` tool โ†’ equivalent to `gh aw mcp inspect` - -These tools provide the same functionality without requiring GitHub CLI authentication. Enable by adding `agentic-workflows:` to your workflow's `tools:` section. -::: +> [!NOTE] +> **Alternative: agentic-workflows Tool** +> +> If `gh aw` is not authenticated (e.g., running in a Copilot agent environment without GitHub CLI auth), use the corresponding tools from the **agentic-workflows** tool instead: +> - `status` tool โ†’ equivalent to `gh aw status` +> - `compile` tool โ†’ equivalent to `gh aw compile` +> - `logs` tool โ†’ equivalent to `gh aw logs` +> - `audit` tool โ†’ equivalent to `gh aw audit` +> - `update` tool โ†’ equivalent to `gh aw update` +> - `add` tool โ†’ equivalent to `gh aw add` +> - `mcp-inspect` tool โ†’ equivalent to `gh aw mcp inspect` +> +> These tools provide the same functionality without requiring GitHub CLI authentication. Enable by adding `agentic-workflows:` to your workflow's `tools:` section. ## Starting the Conversation diff --git a/.github/aw/github-agentic-workflows.md b/.github/aw/github-agentic-workflows.md index c193a9729..925071602 100644 --- a/.github/aw/github-agentic-workflows.md +++ b/.github/aw/github-agentic-workflows.md @@ -243,6 +243,11 @@ The YAML frontmatter supports these fields: allowed: - "example.com" - "*.trusted-domain.com" + - "https://api.secure.com" # Optional: protocol-specific filtering + blocked: + - "blocked-domain.com" + - "*.untrusted.com" + - python # Block ecosystem identifiers firewall: true # Optional: Enable AWF (Agent Workflow Firewall) for Copilot engine ``` - **Firewall configuration** (Copilot engine only): @@ -1059,6 +1064,11 @@ network: - node # Node.js/NPM ecosystem - containers # Container registries - "api.custom.com" # Custom domain + - "https://secure.api.com" # Protocol-specific domain + blocked: + - "tracking.com" # Block specific domains + - "*.ads.com" # Block domain patterns + - ruby # Block ecosystem identifiers firewall: true # Enable AWF (Copilot engine only) # Or allow specific domains only @@ -1079,6 +1089,8 @@ network: {} - Use ecosystem identifiers (`python`, `node`, `java`, etc.) for language-specific tools - When custom permissions are specified with `allowed:` list, deny-by-default policy is enforced - Supports exact domain matches and wildcard patterns (where `*` matches any characters, including nested subdomains) +- **Protocol-specific filtering**: Prefix domains with `http://` or `https://` for protocol restrictions +- **Domain blocklist**: Use `blocked:` field to explicitly deny domains or ecosystem identifiers - **Firewall support**: Copilot engine supports AWF (Agent Workflow Firewall) for domain-based access control - Claude engine uses hooks for enforcement; Codex support planned @@ -1087,6 +1099,7 @@ network: {} 2. **Ecosystem access**: `network: { allowed: [defaults, python, node, ...] }` (development tool ecosystems) 3. **No network access**: `network: {}` (deny all) 4. **Specific domains**: `network: { allowed: ["api.example.com", ...] }` (granular access control) +5. **Block specific domains**: `network: { blocked: ["tracking.com", "*.ads.com", ...] }` (deny-list) **Available Ecosystem Identifiers:** - `defaults`: Basic infrastructure (certificates, JSON schema, Ubuntu, common package mirrors, Microsoft sources) diff --git a/.github/aw/schemas/agentic-workflow.json b/.github/aw/schemas/agentic-workflow.json deleted file mode 100644 index 83d6cd607..000000000 --- a/.github/aw/schemas/agentic-workflow.json +++ /dev/null @@ -1,6070 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/githubnext/gh-aw/schemas/main_workflow_schema.json", - "title": "GitHub Agentic Workflow Schema", - "description": "JSON Schema for validating agentic workflow frontmatter configuration", - "version": "1.0.0", - "type": "object", - "required": ["on"], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "description": "Workflow name that appears in the GitHub Actions interface. If not specified, defaults to the filename without extension.", - "examples": ["Copilot Agent PR Analysis", "Dev Hawk", "Smoke Claude"] - }, - "description": { - "type": "string", - "description": "Optional workflow description that is rendered as a comment in the generated GitHub Actions YAML file (.lock.yml)", - "examples": ["Quickstart for using the GitHub Actions library"] - }, - "source": { - "type": "string", - "description": "Optional source reference indicating where this workflow was added from. Format: owner/repo/path@ref (e.g., githubnext/agentics/workflows/ci-doctor.md@v1.0.0). Rendered as a comment in the generated lock file.", - "examples": ["githubnext/agentics/workflows/ci-doctor.md", "githubnext/agentics/workflows/daily-perf-improver.md@1f181b37d3fe5862ab590648f25a292e345b5de6"] - }, - "tracker-id": { - "type": "string", - "minLength": 8, - "pattern": "^[a-zA-Z0-9_-]+$", - "description": "Optional tracker identifier to tag all created assets (issues, discussions, comments, pull requests). Must be at least 8 characters and contain only alphanumeric characters, hyphens, and underscores. This identifier will be inserted in the body/description of all created assets to enable searching and retrieving assets associated with this workflow.", - "examples": ["workflow-2024-q1", "team-alpha-bot", "security_audit_v2"] - }, - "labels": { - "type": "array", - "description": "Optional array of labels to categorize and organize workflows. Labels can be used to filter workflows in status/list commands.", - "items": { - "type": "string", - "minLength": 1 - }, - "examples": [ - ["automation", "security"], - ["docs", "maintenance"], - ["ci", "testing"] - ] - }, - "metadata": { - "type": "object", - "description": "Optional metadata field for storing custom key-value pairs compatible with the custom agent spec. Key names are limited to 64 characters, and values are limited to 1024 characters.", - "patternProperties": { - "^.{1,64}$": { - "type": "string", - "maxLength": 1024, - "description": "Metadata value (maximum 1024 characters)" - } - }, - "additionalProperties": false, - "examples": [ - { - "author": "John Doe", - "version": "1.0.0", - "category": "automation" - } - ] - }, - "imports": { - "type": "array", - "description": "Optional array of workflow specifications to import (similar to @include directives but defined in frontmatter). Format: owner/repo/path@ref (e.g., githubnext/agentics/workflows/shared/common.md@v1.0.0). Can be strings or objects with path and inputs. Any markdown files under .github/agents directory are treated as custom agent files and only one agent file is allowed per workflow.", - "items": { - "oneOf": [ - { - "type": "string", - "description": "Workflow specification in format owner/repo/path@ref. Markdown files under .github/agents/ are treated as agent configuration files." - }, - { - "type": "object", - "description": "Import specification with path and optional inputs", - "required": ["path"], - "additionalProperties": false, - "properties": { - "path": { - "type": "string", - "description": "Workflow specification in format owner/repo/path@ref. Markdown files under .github/agents/ are treated as agent configuration files." - }, - "inputs": { - "type": "object", - "description": "Input values to pass to the imported workflow. Keys are input names declared in the imported workflow's inputs section, values can be strings or expressions.", - "additionalProperties": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - } - } - } - ] - }, - "examples": [ - ["shared/jqschema.md", "shared/reporting.md"], - ["shared/mcp/gh-aw.md", "shared/jqschema.md", "shared/reporting.md"], - ["../instructions/documentation.instructions.md"], - [".github/agents/my-agent.md"], - [ - { - "path": "shared/discussions-data-fetch.md", - "inputs": { - "count": 50 - } - } - ] - ] - }, - "on": { - "description": "Workflow triggers that define when the agentic workflow should run. Supports standard GitHub Actions trigger events plus special command triggers for /commands (required)", - "examples": [ - { - "issues": { - "types": ["opened"] - } - }, - { - "pull_request": { - "types": ["opened", "synchronize"] - } - }, - "workflow_dispatch", - { - "schedule": "daily at 9am" - }, - "/my-bot" - ], - "oneOf": [ - { - "type": "string", - "minLength": 1, - "description": "Simple trigger event name (e.g., 'push', 'issues', 'pull_request', 'discussion', 'schedule', 'fork', 'create', 'delete', 'public', 'watch', 'workflow_call'), schedule shorthand (e.g., 'daily', 'weekly'), or slash command shorthand (e.g., '/my-bot' expands to slash_command + workflow_dispatch)", - "examples": ["push", "issues", "workflow_dispatch", "daily", "/my-bot"] - }, - { - "type": "object", - "description": "Complex trigger configuration with event-specific filters and options", - "properties": { - "slash_command": { - "description": "Special slash command trigger for /command workflows (e.g., '/my-bot' in issue comments). Creates conditions to match slash commands automatically.", - "oneOf": [ - { - "type": "null", - "description": "Null command configuration - defaults to using the workflow filename (without .md extension) as the command name" - }, - { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Command name as a string (shorthand format, e.g., 'customname' for '/customname' triggers). Command names must not start with '/' as the slash is automatically added when matching commands." - }, - { - "type": "object", - "description": "Command configuration object with custom command name", - "properties": { - "name": { - "oneOf": [ - { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Single command name for slash commands (e.g., 'helper-bot' for '/helper-bot' triggers). Command names must not start with '/' as the slash is automatically added when matching commands. Defaults to workflow filename without .md extension if not specified." - }, - { - "type": "array", - "minItems": 1, - "description": "Array of command names that trigger this workflow (e.g., ['cmd.add', 'cmd.remove'] for '/cmd.add' and '/cmd.remove' triggers). Each command name must not start with '/'.", - "items": { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Command name without leading slash" - } - } - ] - }, - "events": { - "description": "Events where the command should be active. Default is all comment-related events ('*'). Use GitHub Actions event names.", - "oneOf": [ - { - "type": "string", - "description": "Single event name or '*' for all events. Use GitHub Actions event names: 'issues', 'issue_comment', 'pull_request_comment', 'pull_request', 'pull_request_review_comment', 'discussion', 'discussion_comment'.", - "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] - }, - { - "type": "array", - "minItems": 1, - "description": "Array of event names where the command should be active (requires at least one). Use GitHub Actions event names.", - "items": { - "type": "string", - "description": "GitHub Actions event name.", - "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] - } - } - ] - } - }, - "additionalProperties": false - } - ] - }, - "command": { - "description": "DEPRECATED: Use 'slash_command' instead. Special command trigger for /command workflows (e.g., '/my-bot' in issue comments). Creates conditions to match slash commands automatically.", - "oneOf": [ - { - "type": "null", - "description": "Null command configuration - defaults to using the workflow filename (without .md extension) as the command name" - }, - { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Command name as a string (shorthand format, e.g., 'customname' for '/customname' triggers). Command names must not start with '/' as the slash is automatically added when matching commands." - }, - { - "type": "object", - "description": "Command configuration object with custom command name", - "properties": { - "name": { - "oneOf": [ - { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Custom command name for slash commands (e.g., 'helper-bot' for '/helper-bot' triggers). Command names must not start with '/' as the slash is automatically added when matching commands. Defaults to workflow filename without .md extension if not specified." - }, - { - "type": "array", - "minItems": 1, - "description": "Array of command names that trigger this workflow (e.g., ['cmd.add', 'cmd.remove'] for '/cmd.add' and '/cmd.remove' triggers). Each command name must not start with '/'.", - "items": { - "type": "string", - "minLength": 1, - "pattern": "^[^/]", - "description": "Command name without leading slash" - } - } - ] - }, - "events": { - "description": "Events where the command should be active. Default is all comment-related events ('*'). Use GitHub Actions event names.", - "oneOf": [ - { - "type": "string", - "description": "Single event name or '*' for all events. Use GitHub Actions event names: 'issues', 'issue_comment', 'pull_request_comment', 'pull_request', 'pull_request_review_comment', 'discussion', 'discussion_comment'.", - "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] - }, - { - "type": "array", - "minItems": 1, - "description": "Array of event names where the command should be active (requires at least one). Use GitHub Actions event names.", - "items": { - "type": "string", - "description": "GitHub Actions event name.", - "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] - } - } - ] - } - }, - "additionalProperties": false - } - ] - }, - "push": { - "description": "Push event trigger that runs the workflow when code is pushed to the repository", - "type": "object", - "additionalProperties": false, - "properties": { - "branches": { - "type": "array", - "$comment": "Mutually exclusive with branches-ignore. GitHub Actions requires only one to be specified.", - "description": "Branches to filter on", - "items": { - "type": "string" - } - }, - "branches-ignore": { - "type": "array", - "$comment": "Mutually exclusive with branches. GitHub Actions requires only one to be specified.", - "description": "Branches to ignore", - "items": { - "type": "string" - } - }, - "paths": { - "type": "array", - "$comment": "Mutually exclusive with paths-ignore. GitHub Actions requires only one to be specified.", - "description": "Paths to filter on", - "items": { - "type": "string" - } - }, - "paths-ignore": { - "type": "array", - "$comment": "Mutually exclusive with paths. GitHub Actions requires only one to be specified.", - "description": "Paths to ignore", - "items": { - "type": "string" - } - }, - "tags": { - "type": "array", - "description": "List of git tag names or patterns to include for push events (supports wildcards)", - "items": { - "type": "string" - } - }, - "tags-ignore": { - "type": "array", - "description": "List of git tag names or patterns to exclude from push events (supports wildcards)", - "items": { - "type": "string" - } - } - }, - "oneOf": [ - { - "required": ["branches"], - "not": { - "required": ["branches-ignore"] - } - }, - { - "required": ["branches-ignore"], - "not": { - "required": ["branches"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["branches"] - }, - { - "required": ["branches-ignore"] - } - ] - } - } - ], - "allOf": [ - { - "oneOf": [ - { - "required": ["paths"], - "not": { - "required": ["paths-ignore"] - } - }, - { - "required": ["paths-ignore"], - "not": { - "required": ["paths"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["paths"] - }, - { - "required": ["paths-ignore"] - } - ] - } - } - ] - } - ] - }, - "pull_request": { - "description": "Pull request event trigger that runs the workflow when pull requests are created, updated, or closed", - "type": "object", - "properties": { - "types": { - "type": "array", - "description": "Pull request event types to trigger on. Note: 'converted_to_draft' and 'ready_for_review' represent state transitions (events) rather than states. While technically valid to listen for both, consider if you need to handle both transitions or just one.", - "$comment": "converted_to_draft and ready_for_review are logically opposite state transitions. Using both may indicate unclear intent.", - "items": { - "type": "string", - "enum": [ - "assigned", - "unassigned", - "labeled", - "unlabeled", - "opened", - "edited", - "closed", - "reopened", - "synchronize", - "converted_to_draft", - "locked", - "unlocked", - "enqueued", - "dequeued", - "milestoned", - "demilestoned", - "ready_for_review", - "review_requested", - "review_request_removed", - "auto_merge_enabled", - "auto_merge_disabled" - ] - } - }, - "branches": { - "type": "array", - "$comment": "Mutually exclusive with branches-ignore. GitHub Actions requires only one to be specified.", - "description": "Branches to filter on", - "items": { - "type": "string" - } - }, - "branches-ignore": { - "type": "array", - "$comment": "Mutually exclusive with branches. GitHub Actions requires only one to be specified.", - "description": "Branches to ignore", - "items": { - "type": "string" - } - }, - "paths": { - "type": "array", - "$comment": "Mutually exclusive with paths-ignore. GitHub Actions requires only one to be specified.", - "description": "Paths to filter on", - "items": { - "type": "string" - } - }, - "paths-ignore": { - "type": "array", - "$comment": "Mutually exclusive with paths. GitHub Actions requires only one to be specified.", - "description": "Paths to ignore", - "items": { - "type": "string" - } - }, - "draft": { - "type": "boolean", - "description": "Filter by draft pull request state. Set to false to exclude draft PRs, true to include only drafts, or omit to include both" - }, - "forks": { - "oneOf": [ - { - "type": "string", - "description": "Single fork pattern (e.g., '*' for all forks, 'org/*' for org glob, 'org/repo' for exact match)" - }, - { - "type": "array", - "description": "List of allowed fork repositories with glob support (e.g., 'org/repo', 'org/*', '*' for all forks)", - "items": { - "type": "string", - "description": "Repository pattern with optional glob support" - } - } - ] - }, - "names": { - "oneOf": [ - { - "type": "string", - "description": "Single label name to filter labeled/unlabeled events (e.g., 'bug')" - }, - { - "type": "array", - "description": "List of label names to filter labeled/unlabeled events. Only applies when 'labeled' or 'unlabeled' is in the types array", - "items": { - "type": "string", - "description": "Label name" - }, - "minItems": 1 - } - ] - } - }, - "additionalProperties": false, - "oneOf": [ - { - "required": ["branches"], - "not": { - "required": ["branches-ignore"] - } - }, - { - "required": ["branches-ignore"], - "not": { - "required": ["branches"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["branches"] - }, - { - "required": ["branches-ignore"] - } - ] - } - } - ], - "allOf": [ - { - "oneOf": [ - { - "required": ["paths"], - "not": { - "required": ["paths-ignore"] - } - }, - { - "required": ["paths-ignore"], - "not": { - "required": ["paths"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["paths"] - }, - { - "required": ["paths-ignore"] - } - ] - } - } - ] - } - ] - }, - "issues": { - "description": "Issues event trigger that runs when repository issues are created, updated, or managed", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of issue events", - "items": { - "type": "string", - "enum": ["opened", "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", "milestoned", "demilestoned", "typed", "untyped"] - } - }, - "names": { - "oneOf": [ - { - "type": "string", - "description": "Single label name to filter labeled/unlabeled events (e.g., 'bug')" - }, - { - "type": "array", - "description": "List of label names to filter labeled/unlabeled events. Only applies when 'labeled' or 'unlabeled' is in the types array", - "items": { - "type": "string", - "description": "Label name" - }, - "minItems": 1 - } - ] - }, - "lock-for-agent": { - "type": "boolean", - "description": "Whether to lock the issue for the agent when the workflow runs (prevents concurrent modifications)" - } - } - }, - "issue_comment": { - "description": "Issue comment event trigger", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of issue comment events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted"] - } - }, - "lock-for-agent": { - "type": "boolean", - "description": "Whether to lock the parent issue for the agent when the workflow runs (prevents concurrent modifications)" - } - } - }, - "discussion": { - "description": "Discussion event trigger that runs the workflow when repository discussions are created, updated, or managed", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of discussion events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted", "transferred", "pinned", "unpinned", "labeled", "unlabeled", "locked", "unlocked", "category_changed", "answered", "unanswered"] - } - } - } - }, - "discussion_comment": { - "description": "Discussion comment event trigger that runs the workflow when comments on discussions are created, updated, or deleted", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of discussion comment events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted"] - } - } - } - }, - "schedule": { - "description": "Scheduled trigger events using human-friendly format or standard cron expressions. Supports shorthand string notation (e.g., 'daily at 3pm') or array of schedule objects. Human-friendly formats are automatically converted to cron expressions with the original format preserved as comments in the generated workflow.", - "oneOf": [ - { - "type": "string", - "minLength": 1, - "description": "Shorthand schedule string using human-friendly format. Examples: 'daily at 02:00', 'daily at 3pm', 'daily at 6am', 'weekly on monday at 06:30', 'weekly on friday at 5pm', 'monthly on 15 at 09:00', 'monthly on 15 at 9am', 'every 10 minutes', 'every 2h', 'every 1d', 'daily at 02:00 utc+9', 'daily at 3pm utc+9'. Supports 12-hour format (1am-12am, 1pm-12pm), 24-hour format (HH:MM), midnight, noon. Minimum interval is 5 minutes. Converted to standard cron expression automatically." - }, - { - "type": "array", - "minItems": 1, - "description": "Array of schedule objects with cron expressions (standard or human-friendly format)", - "items": { - "type": "object", - "properties": { - "cron": { - "type": "string", - "description": "Cron expression using standard format (e.g., '0 9 * * 1') or human-friendly format (e.g., 'daily at 02:00', 'daily at 3pm', 'daily at 6am', 'weekly on monday', 'weekly on friday at 5pm', 'every 10 minutes', 'every 2h', 'daily at 02:00 utc+9', 'daily at 3pm utc+9'). Human-friendly formats support: daily/weekly/monthly schedules with optional time, interval schedules (minimum 5 minutes), short duration units (m/h/d/w/mo), 12-hour time format (Npm/Nam where N is 1-12), and UTC timezone offsets (utc+N or utc+HH:MM)." - } - }, - "required": ["cron"], - "additionalProperties": false - } - } - ] - }, - "workflow_dispatch": { - "description": "Manual workflow dispatch trigger", - "oneOf": [ - { - "type": "null", - "description": "Simple workflow dispatch trigger" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "inputs": { - "type": "object", - "description": "Input parameters for manual dispatch", - "maxProperties": 25, - "additionalProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string", - "description": "Input description" - }, - "required": { - "type": "boolean", - "description": "Whether input is required" - }, - "default": { - "type": "string", - "description": "Default value" - }, - "type": { - "type": "string", - "enum": ["string", "choice", "boolean"], - "description": "Input type" - }, - "options": { - "type": "array", - "description": "Options for choice type", - "items": { - "type": "string" - } - } - } - } - } - } - } - ] - }, - "workflow_run": { - "description": "Workflow run trigger", - "type": "object", - "additionalProperties": false, - "properties": { - "workflows": { - "type": "array", - "description": "List of workflows to trigger on", - "items": { - "type": "string" - } - }, - "types": { - "type": "array", - "description": "Types of workflow run events", - "items": { - "type": "string", - "enum": ["completed", "requested", "in_progress"] - } - }, - "branches": { - "type": "array", - "$comment": "Mutually exclusive with branches-ignore. GitHub Actions requires only one to be specified.", - "description": "Branches to filter on", - "items": { - "type": "string" - } - }, - "branches-ignore": { - "type": "array", - "$comment": "Mutually exclusive with branches. GitHub Actions requires only one to be specified.", - "description": "Branches to ignore", - "items": { - "type": "string" - } - } - }, - "oneOf": [ - { - "required": ["branches"], - "not": { - "required": ["branches-ignore"] - } - }, - { - "required": ["branches-ignore"], - "not": { - "required": ["branches"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["branches"] - }, - { - "required": ["branches-ignore"] - } - ] - } - } - ] - }, - "release": { - "description": "Release event trigger", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of release events", - "items": { - "type": "string", - "enum": ["published", "unpublished", "created", "edited", "deleted", "prereleased", "released"] - } - } - } - }, - "pull_request_review_comment": { - "description": "Pull request review comment event trigger", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of pull request review comment events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted"] - } - } - } - }, - "branch_protection_rule": { - "description": "Branch protection rule event trigger that runs when branch protection rules are changed", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of branch protection rule events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted"] - } - } - } - }, - "check_run": { - "description": "Check run event trigger that runs when a check run is created, rerequested, completed, or has a requested action", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of check run events", - "items": { - "type": "string", - "enum": ["created", "rerequested", "completed", "requested_action"] - } - } - } - }, - "check_suite": { - "description": "Check suite event trigger that runs when check suite activity occurs", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of check suite events", - "items": { - "type": "string", - "enum": ["completed"] - } - } - } - }, - "create": { - "description": "Create event trigger that runs when a Git reference (branch or tag) is created", - "oneOf": [ - { - "type": "null", - "description": "Simple create event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "delete": { - "description": "Delete event trigger that runs when a Git reference (branch or tag) is deleted", - "oneOf": [ - { - "type": "null", - "description": "Simple delete event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "deployment": { - "description": "Deployment event trigger that runs when a deployment is created", - "oneOf": [ - { - "type": "null", - "description": "Simple deployment event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "deployment_status": { - "description": "Deployment status event trigger that runs when a deployment status is updated", - "oneOf": [ - { - "type": "null", - "description": "Simple deployment status event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "fork": { - "description": "Fork event trigger that runs when someone forks the repository", - "oneOf": [ - { - "type": "null", - "description": "Simple fork event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "gollum": { - "description": "Gollum event trigger that runs when someone creates or updates a Wiki page", - "oneOf": [ - { - "type": "null", - "description": "Simple gollum event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "label": { - "description": "Label event trigger that runs when a label is created, edited, or deleted", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of label events", - "items": { - "type": "string", - "enum": ["created", "edited", "deleted"] - } - } - } - }, - "merge_group": { - "description": "Merge group event trigger that runs when a pull request is added to a merge queue", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of merge group events", - "items": { - "type": "string", - "enum": ["checks_requested"] - } - } - } - }, - "milestone": { - "description": "Milestone event trigger that runs when a milestone is created, closed, opened, edited, or deleted", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of milestone events", - "items": { - "type": "string", - "enum": ["created", "closed", "opened", "edited", "deleted"] - } - } - } - }, - "page_build": { - "description": "Page build event trigger that runs when someone pushes to a GitHub Pages publishing source branch", - "oneOf": [ - { - "type": "null", - "description": "Simple page build event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "public": { - "description": "Public event trigger that runs when a repository changes from private to public", - "oneOf": [ - { - "type": "null", - "description": "Simple public event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "pull_request_target": { - "description": "Pull request target event trigger that runs in the context of the base repository (secure for fork PRs)", - "type": "object", - "properties": { - "types": { - "type": "array", - "description": "List of pull request target event types to trigger on", - "items": { - "type": "string", - "enum": [ - "assigned", - "unassigned", - "labeled", - "unlabeled", - "opened", - "edited", - "closed", - "reopened", - "synchronize", - "converted_to_draft", - "locked", - "unlocked", - "enqueued", - "dequeued", - "review_requested", - "review_request_removed", - "auto_merge_enabled", - "auto_merge_disabled" - ] - } - }, - "branches": { - "type": "array", - "$comment": "Mutually exclusive with branches-ignore. GitHub Actions requires only one to be specified.", - "description": "Branches to filter on", - "items": { - "type": "string" - } - }, - "branches-ignore": { - "type": "array", - "$comment": "Mutually exclusive with branches. GitHub Actions requires only one to be specified.", - "description": "Branches to ignore", - "items": { - "type": "string" - } - }, - "paths": { - "type": "array", - "$comment": "Mutually exclusive with paths-ignore. GitHub Actions requires only one to be specified.", - "description": "Paths to filter on", - "items": { - "type": "string" - } - }, - "paths-ignore": { - "type": "array", - "$comment": "Mutually exclusive with paths. GitHub Actions requires only one to be specified.", - "description": "Paths to ignore", - "items": { - "type": "string" - } - }, - "draft": { - "type": "boolean", - "description": "Filter by draft pull request state" - }, - "forks": { - "oneOf": [ - { - "type": "string", - "description": "Single fork pattern" - }, - { - "type": "array", - "description": "List of allowed fork repositories with glob support", - "items": { - "type": "string" - } - } - ] - } - }, - "additionalProperties": false, - "oneOf": [ - { - "required": ["branches"], - "not": { - "required": ["branches-ignore"] - } - }, - { - "required": ["branches-ignore"], - "not": { - "required": ["branches"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["branches"] - }, - { - "required": ["branches-ignore"] - } - ] - } - } - ], - "allOf": [ - { - "oneOf": [ - { - "required": ["paths"], - "not": { - "required": ["paths-ignore"] - } - }, - { - "required": ["paths-ignore"], - "not": { - "required": ["paths"] - } - }, - { - "not": { - "anyOf": [ - { - "required": ["paths"] - }, - { - "required": ["paths-ignore"] - } - ] - } - } - ] - } - ] - }, - "pull_request_review": { - "description": "Pull request review event trigger that runs when a pull request review is submitted, edited, or dismissed", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of pull request review events", - "items": { - "type": "string", - "enum": ["submitted", "edited", "dismissed"] - } - } - } - }, - "registry_package": { - "description": "Registry package event trigger that runs when a package is published or updated", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of registry package events", - "items": { - "type": "string", - "enum": ["published", "updated"] - } - } - } - }, - "repository_dispatch": { - "description": "Repository dispatch event trigger for custom webhook events", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Custom event types to trigger on", - "items": { - "type": "string" - } - } - } - }, - "status": { - "description": "Status event trigger that runs when the status of a Git commit changes", - "oneOf": [ - { - "type": "null", - "description": "Simple status event trigger" - }, - { - "type": "object", - "additionalProperties": false - } - ] - }, - "watch": { - "description": "Watch event trigger that runs when someone stars the repository", - "type": "object", - "additionalProperties": false, - "properties": { - "types": { - "type": "array", - "description": "Types of watch events", - "items": { - "type": "string", - "enum": ["started"] - } - } - } - }, - "workflow_call": { - "description": "Workflow call event trigger that allows this workflow to be called by another workflow", - "oneOf": [ - { - "type": "null", - "description": "Simple workflow call event trigger" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "inputs": { - "type": "object", - "description": "Input parameters that can be passed to the workflow when it is called", - "additionalProperties": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Description of the input parameter" - }, - "required": { - "type": "boolean", - "description": "Whether the input is required" - }, - "type": { - "type": "string", - "enum": ["string", "number", "boolean"], - "description": "Type of the input parameter" - }, - "default": { - "description": "Default value for the input parameter" - } - } - } - }, - "secrets": { - "type": "object", - "description": "Secrets that can be passed to the workflow when it is called", - "additionalProperties": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Description of the secret" - }, - "required": { - "type": "boolean", - "description": "Whether the secret is required" - } - } - } - } - } - } - ] - }, - "stop-after": { - "type": "string", - "description": "Time when workflow should stop running. Supports multiple formats: absolute dates (YYYY-MM-DD HH:MM:SS, June 1 2025, 1st June 2025, 06/01/2025, etc.) or relative time deltas (+25h, +3d, +1d12h30m). Maximum values for time deltas: 12mo, 52w, 365d, 8760h (365 days). Note: Minute unit 'm' is not allowed for stop-after; minimum unit is hours 'h'." - }, - "skip-if-match": { - "oneOf": [ - { - "type": "string", - "description": "GitHub search query string to check before running workflow (implies max=1). If the search returns any results, the workflow will be skipped. Query is automatically scoped to the current repository. Example: 'is:issue is:open label:bug'" - }, - { - "type": "object", - "required": ["query"], - "properties": { - "query": { - "type": "string", - "description": "GitHub search query string to check before running workflow. Query is automatically scoped to the current repository." - }, - "max": { - "type": "integer", - "minimum": 1, - "description": "Maximum number of items that must be matched for the workflow to be skipped. Defaults to 1 if not specified." - } - }, - "additionalProperties": false, - "description": "Skip-if-match configuration object with query and maximum match count" - } - ], - "description": "Conditionally skip workflow execution when a GitHub search query has matches. Can be a string (query only, implies max=1) or an object with 'query' and optional 'max' fields." - }, - "skip-if-no-match": { - "oneOf": [ - { - "type": "string", - "description": "GitHub search query string to check before running workflow (implies min=1). If the search returns no results, the workflow will be skipped. Query is automatically scoped to the current repository. Example: 'is:pr is:open label:ready-to-deploy'" - }, - { - "type": "object", - "required": ["query"], - "properties": { - "query": { - "type": "string", - "description": "GitHub search query string to check before running workflow. Query is automatically scoped to the current repository." - }, - "min": { - "type": "integer", - "minimum": 1, - "description": "Minimum number of items that must be matched for the workflow to proceed. Defaults to 1 if not specified." - } - }, - "additionalProperties": false, - "description": "Skip-if-no-match configuration object with query and minimum match count" - } - ], - "description": "Conditionally skip workflow execution when a GitHub search query has no matches (or fewer than minimum). Can be a string (query only, implies min=1) or an object with 'query' and optional 'min' fields." - }, - "manual-approval": { - "type": "string", - "description": "Environment name that requires manual approval before the workflow can run. Must match a valid environment configured in the repository settings." - }, - "reaction": { - "oneOf": [ - { - "type": "string", - "enum": ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes", "none"] - }, - { - "type": "integer", - "enum": [1, -1], - "description": "YAML parses +1 and -1 without quotes as integers. These are converted to +1 and -1 strings respectively." - } - ], - "default": "eyes", - "description": "AI reaction to add/remove on triggering item (one of: +1, -1, laugh, confused, heart, hooray, rocket, eyes, none). Use 'none' to disable reactions. Defaults to 'eyes' if not specified.", - "examples": ["eyes", "rocket", "+1", 1, -1, "none"] - } - }, - "additionalProperties": false, - "examples": [ - { - "schedule": [ - { - "cron": "0 0 * * *" - } - ], - "workflow_dispatch": null - }, - { - "command": { - "name": "mergefest", - "events": ["pull_request_comment"] - } - }, - { - "workflow_run": { - "workflows": ["Dev"], - "types": ["completed"], - "branches": ["copilot/**"] - } - }, - { - "pull_request": { - "types": ["ready_for_review"] - }, - "workflow_dispatch": null - }, - { - "push": { - "branches": ["main"] - } - } - ] - } - ] - }, - "permissions": { - "description": "GitHub token permissions for the workflow. Controls what the GITHUB_TOKEN can access during execution. Use the principle of least privilege - only grant the minimum permissions needed.", - "examples": [ - "read-all", - { - "contents": "read", - "actions": "read", - "pull-requests": "read" - }, - { - "contents": "read", - "actions": "read" - }, - { - "all": "read" - } - ], - "oneOf": [ - { - "type": "string", - "enum": ["read-all", "write-all", "read", "write"], - "description": "Simple permissions string: 'read-all' (all read permissions), 'write-all' (all write permissions), 'read' or 'write' (basic level)" - }, - { - "type": "object", - "description": "Detailed permissions object with granular control over specific GitHub API scopes", - "additionalProperties": false, - "properties": { - "actions": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for GitHub Actions workflows and runs (read: view workflows, write: manage workflows, none: no access)" - }, - "attestations": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for artifact attestations (read: view attestations, write: create attestations, none: no access)" - }, - "checks": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository checks and status checks (read: view checks, write: create/update checks, none: no access)" - }, - "contents": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository contents (read: view files, write: modify files/branches, none: no access)" - }, - "deployments": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository deployments (read: view deployments, write: create/update deployments, none: no access)" - }, - "discussions": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository discussions (read: view discussions, write: create/update discussions, none: no access)" - }, - "id-token": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "issues": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository issues (read: view issues, write: create/update/close issues, none: no access)" - }, - "models": { - "type": "string", - "enum": ["read", "none"], - "description": "Permission for GitHub Copilot models (read: access AI models for agentic workflows, none: no access)" - }, - "metadata": { - "type": "string", - "enum": ["read", "write", "none"], - "description": "Permission for repository metadata (read: view repository information, write: update repository metadata, none: no access)" - }, - "packages": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "pages": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "pull-requests": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "security-events": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "statuses": { - "type": "string", - "enum": ["read", "write", "none"] - }, - "all": { - "type": "string", - "enum": ["read"], - "description": "Permission shorthand that applies read access to all permission scopes. Can be combined with specific write permissions to override individual scopes. 'write' is not allowed for all." - } - } - } - ] - }, - "run-name": { - "type": "string", - "description": "Custom name for workflow runs that appears in the GitHub Actions interface (supports GitHub expressions like ${{ github.event.issue.title }})", - "examples": ["Deploy to ${{ github.event.inputs.environment }}", "Build #${{ github.run_number }}"] - }, - "jobs": { - "type": "object", - "description": "Groups together all the jobs that run in the workflow", - "additionalProperties": { - "type": "object", - "description": "Job definition", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the job" - }, - "runs-on": { - "oneOf": [ - { - "type": "string", - "description": "Runner type as string" - }, - { - "type": "array", - "description": "Runner type as array", - "items": { - "type": "string" - } - }, - { - "type": "object", - "description": "Runner type as object", - "additionalProperties": false - } - ] - }, - "steps": { - "type": "array", - "description": "A job contains a sequence of tasks called steps. Steps can run commands, run setup tasks, or run an action in your repository, a public repository, or an action published in a Docker registry.", - "items": { - "type": "object", - "additionalProperties": false, - "oneOf": [ - { - "required": ["uses"] - }, - { - "required": ["run"] - } - ], - "properties": { - "id": { - "type": "string", - "description": "A unique identifier for the step. You can use the id to reference the step in contexts." - }, - "if": { - "description": "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.", - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "string" - } - ] - }, - "name": { - "type": "string", - "description": "A name for your step to display on GitHub." - }, - "uses": { - "type": "string", - "description": "Selects an action to run as part of a step in your job. An action is a reusable unit of code." - }, - "run": { - "type": "string", - "description": "Runs command-line programs using the operating system's shell." - }, - "working-directory": { - "type": "string", - "description": "Working directory where to run the command." - }, - "shell": { - "type": "string", - "description": "Shell to use for running the command." - }, - "with": { - "type": "object", - "description": "A map of the input parameters defined by the action. Each input parameter is a key/value pair.", - "additionalProperties": true - }, - "env": { - "type": "object", - "description": "Sets environment variables for steps to use in the virtual environment.", - "additionalProperties": { - "type": "string" - } - }, - "continue-on-error": { - "description": "Prevents a job from failing when a step fails. Set to true to allow a job to pass when this step fails.", - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "string" - } - ] - }, - "timeout-minutes": { - "description": "The maximum number of minutes to run the step before killing the process.", - "oneOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } - } - } - }, - "if": { - "type": "string", - "description": "Conditional execution for the job" - }, - "needs": { - "oneOf": [ - { - "type": "string", - "description": "Single job dependency" - }, - { - "type": "array", - "description": "Multiple job dependencies", - "items": { - "type": "string" - } - } - ] - }, - "env": { - "type": "object", - "description": "Environment variables for the job", - "additionalProperties": { - "type": "string" - } - }, - "permissions": { - "$ref": "#/properties/permissions" - }, - "timeout-minutes": { - "type": "integer", - "description": "Job timeout in minutes" - }, - "strategy": { - "type": "object", - "description": "Matrix strategy for the job", - "additionalProperties": false - }, - "continue-on-error": { - "type": "boolean", - "description": "Continue workflow on job failure" - }, - "container": { - "type": "object", - "description": "Container to run the job in", - "additionalProperties": false - }, - "services": { - "type": "object", - "description": "Service containers for the job", - "additionalProperties": { - "type": "object", - "additionalProperties": false - } - }, - "outputs": { - "type": "object", - "description": "Job outputs", - "additionalProperties": { - "type": "string" - } - }, - "concurrency": { - "$ref": "#/properties/concurrency" - }, - "uses": { - "type": "string", - "description": "Path to a reusable workflow file to call (e.g., ./.github/workflows/reusable-workflow.yml)" - }, - "with": { - "type": "object", - "description": "Input parameters to pass to the reusable workflow", - "additionalProperties": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - }, - "secrets": { - "type": "object", - "description": "Secrets to pass to the reusable workflow. Values must be GitHub Actions expressions referencing secrets (e.g., ${{ secrets.MY_SECRET }} or ${{ secrets.SECRET1 || secrets.SECRET2 }}).", - "additionalProperties": { - "$ref": "#/$defs/github_token" - } - } - } - } - }, - "runs-on": { - "description": "Runner type for workflow execution (GitHub Actions standard field). Supports multiple forms: simple string for single runner label (e.g., 'ubuntu-latest'), array for runner selection with fallbacks, or object for GitHub-hosted runner groups with specific labels. For agentic workflows, runner selection matters when AI workloads require specific compute resources or when using self-hosted runners with specialized capabilities. Typically configured at the job level instead. See https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job", - "oneOf": [ - { - "type": "string", - "description": "Simple runner label string. Use for standard GitHub-hosted runners (e.g., 'ubuntu-latest', 'windows-latest', 'macos-latest') or self-hosted runner labels. Most common form for agentic workflows." - }, - { - "type": "array", - "description": "Array of runner labels for selection with fallbacks. GitHub Actions will use the first available runner that matches any label in the array. Useful for high-availability setups or when multiple runner types are acceptable.", - "items": { - "type": "string" - } - }, - { - "type": "object", - "description": "Runner group configuration for GitHub-hosted runners. Use this form to target specific runner groups (e.g., larger runners with more CPU/memory) or self-hosted runner pools with specific label requirements. Agentic workflows may benefit from larger runners for complex AI processing tasks.", - "additionalProperties": false, - "properties": { - "group": { - "type": "string", - "description": "Runner group name for self-hosted runners or GitHub-hosted runner groups" - }, - "labels": { - "type": "array", - "description": "List of runner labels for self-hosted runners or GitHub-hosted runner selection", - "items": { - "type": "string" - } - } - } - } - ], - "examples": [ - "ubuntu-latest", - ["ubuntu-latest", "self-hosted"], - { - "group": "larger-runners", - "labels": ["ubuntu-latest-8-cores"] - } - ] - }, - "timeout-minutes": { - "type": "integer", - "description": "Workflow timeout in minutes (GitHub Actions standard field). Defaults to 20 minutes for agentic workflows. Has sensible defaults and can typically be omitted.", - "examples": [5, 10, 30] - }, - "timeout_minutes": { - "type": "integer", - "description": "Deprecated: Use 'timeout-minutes' instead. Workflow timeout in minutes. Defaults to 20 minutes for agentic workflows.", - "examples": [5, 10, 30], - "deprecated": true - }, - "concurrency": { - "description": "Concurrency control to limit concurrent workflow runs (GitHub Actions standard field). Supports two forms: simple string for basic group isolation, or object with cancel-in-progress option for advanced control. Agentic workflows enhance this with automatic per-engine concurrency policies (defaults to single job per engine across all workflows) and token-based rate limiting. Default behavior: workflows in the same group queue sequentially unless cancel-in-progress is true. See https://docs.github.com/en/actions/using-jobs/using-concurrency", - "oneOf": [ - { - "type": "string", - "description": "Simple concurrency group name to prevent multiple runs in the same group. Use expressions like '${{ github.workflow }}' for per-workflow isolation or '${{ github.ref }}' for per-branch isolation. Agentic workflows automatically generate enhanced concurrency policies using 'gh-aw-{engine-id}' as the default group to limit concurrent AI workloads across all workflows using the same engine.", - "examples": ["my-workflow-group", "workflow-${{ github.ref }}"] - }, - { - "type": "object", - "description": "Concurrency configuration object with group isolation and cancellation control. Use object form when you need fine-grained control over whether to cancel in-progress runs. For agentic workflows, this is useful to prevent multiple AI agents from running simultaneously and consuming excessive resources or API quotas.", - "additionalProperties": false, - "properties": { - "group": { - "type": "string", - "description": "Concurrency group name. Workflows in the same group cannot run simultaneously. Supports GitHub Actions expressions for dynamic group names based on branch, workflow, or other context." - }, - "cancel-in-progress": { - "type": "boolean", - "description": "Whether to cancel in-progress workflows in the same concurrency group when a new one starts. Default: false (queue new runs). Set to true for agentic workflows where only the latest run matters (e.g., PR analysis that becomes stale when new commits are pushed)." - } - }, - "required": ["group"], - "examples": [ - { - "group": "dev-workflow-${{ github.ref }}", - "cancel-in-progress": true - } - ] - } - ], - "examples": [ - "my-workflow-group", - "workflow-${{ github.ref }}", - { - "group": "agentic-analysis-${{ github.workflow }}", - "cancel-in-progress": false - }, - { - "group": "pr-review-${{ github.event.pull_request.number }}", - "cancel-in-progress": true - } - ] - }, - "env": { - "$comment": "See environment variable precedence documentation: https://githubnext.github.io/gh-aw/reference/environment-variables/", - "description": "Environment variables for the workflow", - "oneOf": [ - { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "examples": [ - { - "NODE_ENV": "production", - "API_KEY": "${{ secrets.API_KEY }}" - } - ] - }, - { - "type": "string" - } - ] - }, - "features": { - "description": "Feature flags and configuration options for experimental or optional features in the workflow. Each feature can be a boolean flag or a string value. The 'action-tag' feature (string) specifies the tag or SHA to use when referencing actions/setup in compiled workflows (for testing purposes only).", - "type": "object", - "additionalProperties": true, - "examples": [ - { - "action-tag": "v1.0.0" - }, - { - "action-tag": "abc123def456", - "experimental-feature": true - } - ] - }, - "environment": { - "description": "Environment that the job references (for protected environments and deployments)", - "oneOf": [ - { - "type": "string", - "description": "Environment name as a string" - }, - { - "type": "object", - "description": "Environment object with name and optional URL", - "properties": { - "name": { - "type": "string", - "description": "The name of the environment configured in the repo" - }, - "url": { - "type": "string", - "description": "A deployment URL" - } - }, - "required": ["name"], - "additionalProperties": false - } - ] - }, - "container": { - "description": "Container to run the job steps in", - "oneOf": [ - { - "type": "string", - "description": "Docker image name (e.g., 'node:18', 'ubuntu:latest')" - }, - { - "type": "object", - "description": "Container configuration object", - "properties": { - "image": { - "type": "string", - "description": "The Docker image to use as the container" - }, - "credentials": { - "type": "object", - "description": "Credentials for private registries", - "properties": { - "username": { - "type": "string" - }, - "password": { - "type": "string" - } - }, - "additionalProperties": false - }, - "env": { - "type": "object", - "description": "Environment variables for the container", - "additionalProperties": { - "type": "string" - } - }, - "ports": { - "type": "array", - "description": "Ports to expose on the container", - "items": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } - }, - "volumes": { - "type": "array", - "description": "Volumes for the container", - "items": { - "type": "string" - } - }, - "options": { - "type": "string", - "description": "Additional Docker container options" - } - }, - "required": ["image"], - "additionalProperties": false - } - ] - }, - "services": { - "description": "Service containers for the job", - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "string", - "description": "Docker image name for the service" - }, - { - "type": "object", - "description": "Service container configuration", - "properties": { - "image": { - "type": "string", - "description": "The Docker image to use for the service" - }, - "credentials": { - "type": "object", - "description": "Credentials for private registries", - "properties": { - "username": { - "type": "string" - }, - "password": { - "type": "string" - } - }, - "additionalProperties": false - }, - "env": { - "type": "object", - "description": "Environment variables for the service", - "additionalProperties": { - "type": "string" - } - }, - "ports": { - "type": "array", - "description": "Ports to expose on the service", - "items": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } - }, - "volumes": { - "type": "array", - "description": "Volumes for the service", - "items": { - "type": "string" - } - }, - "options": { - "type": "string", - "description": "Additional Docker container options" - } - }, - "required": ["image"], - "additionalProperties": false - } - ] - } - }, - "network": { - "$comment": "Strict mode requirements: When strict=true, the 'network' field must be present (not null/undefined) and cannot contain standalone wildcard '*' in allowed domains (but patterns like '*.example.com' ARE allowed). This is validated in Go code (pkg/workflow/strict_mode_validation.go) via validateStrictNetwork().", - "description": "Network access control for AI engines using ecosystem identifiers and domain allowlists. Supports wildcard patterns like '*.example.com' to match any subdomain. Controls web fetch and search capabilities.", - "examples": [ - "defaults", - { - "allowed": ["defaults", "github"] - }, - { - "allowed": ["defaults", "python", "node", "*.example.com"] - }, - { - "allowed": ["api.openai.com", "*.github.com"], - "firewall": { - "version": "v1.0.0", - "log-level": "debug" - } - } - ], - "oneOf": [ - { - "type": "string", - "enum": ["defaults"], - "description": "Use default network permissions (basic infrastructure: certificates, JSON schema, Ubuntu, etc.)" - }, - { - "type": "object", - "description": "Custom network access configuration with ecosystem identifiers and specific domains", - "properties": { - "allowed": { - "type": "array", - "description": "List of allowed domains or ecosystem identifiers (e.g., 'defaults', 'python', 'node', '*.example.com'). Wildcard patterns match any subdomain AND the base domain.", - "items": { - "type": "string", - "description": "Domain name or ecosystem identifier. Supports wildcards like '*.example.com' (matches sub.example.com, deep.nested.example.com, and example.com itself) and ecosystem names like 'python', 'node'." - }, - "$comment": "Empty array is valid and means deny all network access. Omit the field entirely or use network: defaults to use default network permissions. Wildcard patterns like '*.example.com' are allowed; only standalone '*' is blocked in strict mode." - }, - "blocked": { - "type": "array", - "description": "List of blocked domains or ecosystem identifiers (e.g., 'python', 'node', 'tracker.example.com'). Blocked domains take precedence over allowed domains.", - "items": { - "type": "string", - "description": "Domain name or ecosystem identifier to block. Supports wildcards like '*.example.com' (matches sub.example.com, deep.nested.example.com, and example.com itself) and ecosystem names like 'python', 'node'." - }, - "$comment": "Blocked domains are subtracted from the allowed list. Useful for blocking specific domains or ecosystems within broader allowed categories." - }, - "firewall": { - "description": "AWF (Agent Workflow Firewall) configuration for network egress control. Only supported for Copilot engine.", - "deprecated": true, - "x-deprecation-message": "Use 'sandbox.agent: false' instead to disable the firewall for the agent", - "oneOf": [ - { - "type": "null", - "description": "Enable AWF with default settings (equivalent to empty object)" - }, - { - "type": "boolean", - "description": "Enable (true) or explicitly disable (false) AWF firewall" - }, - { - "type": "string", - "enum": ["disable"], - "description": "Disable AWF firewall (triggers warning if allowed != *, error in strict mode if allowed is not * or engine does not support firewall)" - }, - { - "type": "object", - "description": "Custom AWF configuration with version and arguments", - "properties": { - "args": { - "type": "array", - "description": "Optional additional arguments to pass to AWF wrapper", - "items": { - "type": "string" - } - }, - "version": { - "type": ["string", "number"], - "description": "AWF version to use (empty = latest release). Can be a string (e.g., 'v1.0.0', 'latest') or number (e.g., 20, 3.11). Numeric values are automatically converted to strings at runtime.", - "examples": ["v1.0.0", "latest", 20, 3.11] - }, - "log-level": { - "type": "string", - "description": "AWF log level (default: info). Valid values: debug, info, warn, error", - "enum": ["debug", "info", "warn", "error"] - } - }, - "additionalProperties": false - } - ] - } - }, - "additionalProperties": false - } - ] - }, - "sandbox": { - "description": "Sandbox configuration for AI engines. Controls agent sandbox (AWF or Sandbox Runtime) and MCP gateway.", - "oneOf": [ - { - "type": "string", - "enum": ["default", "sandbox-runtime", "awf", "srt"], - "description": "Legacy string format for sandbox type: 'default' for no sandbox, 'sandbox-runtime' or 'srt' for Anthropic Sandbox Runtime, 'awf' for Agent Workflow Firewall" - }, - { - "type": "object", - "description": "Object format for full sandbox configuration with agent and mcp options", - "properties": { - "type": { - "type": "string", - "enum": ["default", "sandbox-runtime", "awf", "srt"], - "description": "Legacy sandbox type field (use agent instead)" - }, - "agent": { - "description": "Agent sandbox type: 'awf' uses AWF (Agent Workflow Firewall), 'srt' uses Anthropic Sandbox Runtime, or 'false' to disable firewall", - "oneOf": [ - { - "type": "boolean", - "enum": [false], - "description": "Set to false to disable the agent firewall" - }, - { - "type": "string", - "enum": ["awf", "srt"], - "description": "Sandbox type: 'awf' for Agent Workflow Firewall, 'srt' for Sandbox Runtime" - }, - { - "type": "object", - "description": "Custom sandbox runtime configuration", - "properties": { - "id": { - "type": "string", - "enum": ["awf", "srt"], - "description": "Agent identifier (replaces 'type' field in new format): 'awf' for Agent Workflow Firewall, 'srt' for Sandbox Runtime" - }, - "type": { - "type": "string", - "enum": ["awf", "srt"], - "description": "Legacy: Sandbox type to use (use 'id' instead)" - }, - "command": { - "type": "string", - "description": "Custom command to replace the default AWF or SRT installation. For AWF: 'docker run my-custom-awf-image'. For SRT: 'docker run my-custom-srt-wrapper'" - }, - "args": { - "type": "array", - "description": "Additional arguments to append to the command (applies to both AWF and SRT, for standard and custom commands)", - "items": { - "type": "string" - } - }, - "env": { - "type": "object", - "description": "Environment variables to set on the execution step (applies to both AWF and SRT)", - "additionalProperties": { - "type": "string" - } - }, - "mounts": { - "type": "array", - "description": "Container mounts to add when using AWF. Each mount is specified using Docker mount syntax: 'source:destination:mode' where mode can be 'ro' (read-only) or 'rw' (read-write). Example: '/host/path:/container/path:ro'", - "items": { - "type": "string", - "pattern": "^[^:]+:[^:]+:(ro|rw)$", - "description": "Mount specification in format 'source:destination:mode'" - }, - "examples": [["/host/data:/data:ro", "/usr/local/bin/custom-tool:/usr/local/bin/custom-tool:ro"]] - }, - "config": { - "type": "object", - "description": "Custom Sandbox Runtime configuration (only applies when type is 'srt'). Note: Network configuration is controlled by the top-level 'network' field, not here.", - "properties": { - "filesystem": { - "type": "object", - "properties": { - "denyRead": { - "type": "array", - "description": "List of paths to deny read access", - "items": { - "type": "string" - } - }, - "allowWrite": { - "type": "array", - "description": "List of paths to allow write access", - "items": { - "type": "string" - } - }, - "denyWrite": { - "type": "array", - "description": "List of paths to deny write access", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ignoreViolations": { - "type": "object", - "description": "Map of command patterns to paths that should ignore violations", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "enableWeakerNestedSandbox": { - "type": "boolean", - "description": "Enable weaker nested sandbox mode (recommended: true for Docker access)" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - ] - }, - "config": { - "type": "object", - "description": "Legacy custom Sandbox Runtime configuration (use agent.config instead). Note: Network configuration is controlled by the top-level 'network' field, not here.", - "properties": { - "filesystem": { - "type": "object", - "properties": { - "denyRead": { - "type": "array", - "items": { - "type": "string" - } - }, - "allowWrite": { - "type": "array", - "items": { - "type": "string" - } - }, - "denyWrite": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ignoreViolations": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "enableWeakerNestedSandbox": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "mcp": { - "description": "MCP Gateway configuration for routing MCP server calls through a unified HTTP gateway. Requires the 'mcp-gateway' feature flag to be enabled. Per MCP Gateway Specification v1.0.0: Only container-based execution is supported.", - "type": "object", - "properties": { - "container": { - "type": "string", - "pattern": "^[a-zA-Z0-9][a-zA-Z0-9/:_.-]*$", - "description": "Container image for the MCP gateway executable (required)" - }, - "version": { - "type": ["string", "number"], - "description": "Optional version/tag for the container image (e.g., 'latest', 'v1.0.0')", - "examples": ["latest", "v1.0.0"] - }, - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments for docker run" - }, - "entrypointArgs": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to add after the container image (container entrypoint arguments)" - }, - "env": { - "type": "object", - "patternProperties": { - "^[A-Z_][A-Z0-9_]*$": { - "type": "string" - } - }, - "additionalProperties": false, - "description": "Environment variables for MCP gateway" - }, - "port": { - "type": "integer", - "minimum": 1, - "maximum": 65535, - "default": 8080, - "description": "Port number for the MCP gateway HTTP server (default: 8080)" - }, - "api-key": { - "type": "string", - "description": "API key for authenticating with the MCP gateway (supports ${{ secrets.* }} syntax)" - } - }, - "required": ["container"], - "additionalProperties": false - } - }, - "additionalProperties": false - } - ], - "examples": [ - "default", - "sandbox-runtime", - { - "agent": "awf" - }, - { - "agent": "srt" - }, - { - "agent": { - "type": "srt", - "config": { - "filesystem": { - "allowWrite": [".", "/tmp"] - } - } - } - }, - { - "mcp": { - "container": "ghcr.io/githubnext/mcp-gateway", - "port": 8080 - } - }, - { - "agent": "awf", - "mcp": { - "container": "ghcr.io/githubnext/mcp-gateway", - "port": 8080, - "api-key": "${{ secrets.MCP_GATEWAY_API_KEY }}" - } - } - ] - }, - "if": { - "type": "string", - "description": "Conditional execution expression", - "examples": ["${{ github.event.workflow_run.event == 'workflow_dispatch' }}", "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}"] - }, - "steps": { - "description": "Custom workflow steps", - "oneOf": [ - { - "type": "object", - "additionalProperties": true - }, - { - "type": "array", - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": true - } - ] - }, - "examples": [ - [ - { - "prompt": "Analyze the issue and create a plan" - } - ], - [ - { - "uses": "actions/checkout@v4" - }, - { - "prompt": "Review the code and suggest improvements" - } - ], - [ - { - "name": "Download logs from last 24 hours", - "env": { - "GH_TOKEN": "${{ secrets.GITHUB_TOKEN }}" - }, - "run": "./gh-aw logs --start-date -1d -o /tmp/gh-aw/aw-mcp/logs" - } - ] - ] - } - ] - }, - "post-steps": { - "description": "Custom workflow steps to run after AI execution", - "oneOf": [ - { - "type": "object", - "additionalProperties": true - }, - { - "type": "array", - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": true - } - ] - }, - "examples": [ - [ - { - "name": "Verify Post-Steps Execution", - "run": "echo \"\u2705 Post-steps are executing correctly\"\necho \"This step runs after the AI agent completes\"\n" - }, - { - "name": "Upload Test Results", - "if": "always()", - "uses": "actions/upload-artifact@v4", - "with": { - "name": "post-steps-test-results", - "path": "/tmp/gh-aw/", - "retention-days": 1, - "if-no-files-found": "ignore" - } - } - ] - ] - } - ] - }, - "engine": { - "description": "AI engine configuration that specifies which AI processor interprets and executes the markdown content of the workflow. Defaults to 'copilot'.", - "default": "copilot", - "examples": [ - "copilot", - "claude", - "codex", - { - "id": "copilot", - "version": "beta" - }, - { - "id": "claude", - "model": "claude-3-5-sonnet-20241022", - "max-turns": 15 - } - ], - "$ref": "#/$defs/engine_config" - }, - "mcp-servers": { - "type": "object", - "description": "MCP server definitions", - "examples": [ - { - "filesystem": { - "type": "stdio", - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem"] - } - }, - { - "custom-server": { - "type": "http", - "url": "https://api.example.com/mcp" - } - } - ], - "patternProperties": { - "^[a-zA-Z0-9_-]+$": { - "oneOf": [ - { - "$ref": "#/$defs/stdio_mcp_tool" - }, - { - "$ref": "#/$defs/http_mcp_tool" - } - ] - } - }, - "additionalProperties": false - }, - "tools": { - "type": "object", - "description": "Tools and MCP (Model Context Protocol) servers available to the AI engine for GitHub API access, browser automation, file editing, and more", - "examples": [ - { - "playwright": { - "version": "v1.41.0" - } - }, - { - "github": { - "mode": "remote" - } - }, - { - "github": { - "mode": "local", - "version": "latest" - } - }, - { - "bash": null - } - ], - "properties": { - "github": { - "description": "GitHub API tools for repository operations (issues, pull requests, content management)", - "oneOf": [ - { - "type": "null", - "description": "Empty GitHub tool configuration (enables all read-only GitHub API functions)" - }, - { - "type": "boolean", - "description": "Boolean to explicitly enable (true) or disable (false) the GitHub MCP server. When set to false, the GitHub MCP server is not mounted." - }, - { - "type": "string", - "description": "Simple GitHub tool configuration (enables all GitHub API functions)" - }, - { - "type": "object", - "description": "GitHub tools object configuration with restricted function access", - "properties": { - "allowed": { - "type": "array", - "description": "List of allowed GitHub API functions (e.g., 'create_issue', 'update_issue', 'add_comment')", - "items": { - "type": "string" - } - }, - "mode": { - "type": "string", - "enum": ["local", "remote"], - "description": "MCP server mode: 'local' (Docker-based, default) or 'remote' (hosted at api.githubcopilot.com)" - }, - "version": { - "type": ["string", "number"], - "description": "Optional version specification for the GitHub MCP server (used with 'local' type). Can be a string (e.g., 'v1.0.0', 'latest') or number (e.g., 20, 3.11). Numeric values are automatically converted to strings at runtime.", - "examples": ["v1.0.0", "latest", 20, 3.11] - }, - "args": { - "type": "array", - "description": "Optional additional arguments to append to the generated MCP server command (used with 'local' type)", - "items": { - "type": "string" - } - }, - "read-only": { - "type": "boolean", - "description": "Enable read-only mode to restrict GitHub MCP server to read-only operations only" - }, - "lockdown": { - "type": "boolean", - "description": "Enable lockdown mode to limit content surfaced from public repositories (only items authored by users with push access). Default: false", - "default": false - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "Optional custom GitHub token (e.g., '${{ secrets.CUSTOM_PAT }}'). For 'remote' type, defaults to GH_AW_GITHUB_TOKEN if not specified." - }, - "toolsets": { - "type": "array", - "description": "Array of GitHub MCP server toolset names to enable specific groups of GitHub API functionalities", - "items": { - "type": "string", - "description": "Toolset name", - "enum": [ - "all", - "default", - "action-friendly", - "context", - "repos", - "issues", - "pull_requests", - "actions", - "code_security", - "dependabot", - "discussions", - "experiments", - "gists", - "labels", - "notifications", - "orgs", - "projects", - "search", - "secret_protection", - "security_advisories", - "stargazers", - "users" - ] - }, - "minItems": 1, - "$comment": "At least one toolset is required when toolsets array is specified. Use null or omit the field to use all toolsets." - } - }, - "additionalProperties": false, - "examples": [ - { - "toolsets": ["pull_requests", "actions", "repos"] - }, - { - "allowed": ["search_pull_requests", "pull_request_read", "list_pull_requests", "get_file_contents", "list_commits", "get_commit"] - }, - { - "read-only": true - }, - { - "toolsets": ["pull_requests", "repos"] - } - ] - } - ], - "examples": [ - null, - { - "toolsets": ["pull_requests", "actions", "repos"] - }, - { - "allowed": ["search_pull_requests", "pull_request_read", "get_file_contents"] - }, - { - "read-only": true, - "toolsets": ["repos", "issues"] - }, - false - ] - }, - "bash": { - "description": "Bash shell command execution tool. Supports wildcards: '*' (all commands), 'command *' (command with any args, e.g., 'date *', 'echo *'). Default safe commands: echo, ls, pwd, cat, head, tail, grep, wc, sort, uniq, date.", - "oneOf": [ - { - "type": "null", - "description": "Enable bash tool with all shell commands allowed (security consideration: use restricted list in production)" - }, - { - "type": "boolean", - "description": "Enable bash tool - true allows all commands (equivalent to ['*']), false disables the tool" - }, - { - "type": "array", - "description": "List of allowed commands and patterns. Wildcards: '*' allows all commands, 'command *' allows command with any args (e.g., 'date *', 'echo *').", - "items": { - "type": "string", - "description": "Command or pattern: 'echo' (exact match), 'echo *' (command with any args)" - } - } - ], - "examples": [ - true, - ["git fetch", "git checkout", "git status", "git diff", "git log", "make recompile", "make fmt", "make lint", "make test-unit", "cat", "echo", "ls"], - ["echo", "ls", "cat"], - ["gh pr list *", "gh search prs *", "jq *"], - ["date *", "echo *", "cat", "ls"] - ] - }, - "web-fetch": { - "description": "Web content fetching tool for downloading web pages and API responses (subject to network permissions)", - "oneOf": [ - { - "type": "null", - "description": "Enable web fetch tool with default configuration" - }, - { - "type": "object", - "description": "Web fetch tool configuration object", - "additionalProperties": false - } - ] - }, - "web-search": { - "description": "Web search tool for performing internet searches and retrieving search results (subject to network permissions)", - "oneOf": [ - { - "type": "null", - "description": "Enable web search tool with default configuration" - }, - { - "type": "object", - "description": "Web search tool configuration object", - "additionalProperties": false - } - ] - }, - "edit": { - "description": "File editing tool for reading, creating, and modifying files in the repository", - "oneOf": [ - { - "type": "null", - "description": "Enable edit tool" - }, - { - "type": "object", - "description": "Edit tool configuration object", - "additionalProperties": false - } - ] - }, - "playwright": { - "description": "Playwright browser automation tool for web scraping, testing, and UI interactions in containerized browsers", - "oneOf": [ - { - "type": "null", - "description": "Enable Playwright tool with default settings (localhost access only for security)" - }, - { - "type": "object", - "description": "Playwright tool configuration with custom version and domain restrictions", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Optional Playwright container version (e.g., 'v1.41.0', 1.41, 20). Numeric values are automatically converted to strings at runtime.", - "examples": ["v1.41.0", 1.41, 20] - }, - "allowed_domains": { - "description": "Domains allowed for Playwright browser network access. Defaults to localhost only for security.", - "oneOf": [ - { - "type": "array", - "description": "List of allowed domains or patterns (e.g., ['github.com', '*.example.com'])", - "items": { - "type": "string" - } - }, - { - "type": "string", - "description": "Single allowed domain (e.g., 'github.com')" - } - ] - }, - "args": { - "type": "array", - "description": "Optional additional arguments to append to the generated MCP server command", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - ] - }, - "agentic-workflows": { - "description": "GitHub Agentic Workflows MCP server for workflow introspection and analysis. Provides tools for checking status, compiling workflows, downloading logs, and auditing runs.", - "oneOf": [ - { - "type": "boolean", - "description": "Enable agentic-workflows tool with default settings" - }, - { - "type": "null", - "description": "Enable agentic-workflows tool with default settings (same as true)" - } - ], - "examples": [true, null] - }, - "cache-memory": { - "description": "Cache memory MCP configuration for persistent memory storage", - "oneOf": [ - { - "type": "boolean", - "description": "Enable cache-memory with default settings" - }, - { - "type": "null", - "description": "Enable cache-memory with default settings (same as true)" - }, - { - "type": "object", - "description": "Cache-memory configuration object", - "properties": { - "key": { - "type": "string", - "description": "Custom cache key for memory MCP data (restore keys are auto-generated by splitting on '-')" - }, - "description": { - "type": "string", - "description": "Optional description for the cache that will be shown in the agent prompt" - }, - "retention-days": { - "type": "integer", - "minimum": 1, - "maximum": 90, - "description": "Number of days to retain uploaded artifacts (1-90 days, default: repository setting)" - }, - "restore-only": { - "type": "boolean", - "description": "If true, only restore the cache without saving it back. Uses actions/cache/restore instead of actions/cache. No artifact upload step will be generated." - } - }, - "additionalProperties": false, - "examples": [ - { - "key": "memory-audit-${{ github.workflow }}" - }, - { - "key": "memory-copilot-analysis", - "retention-days": 30 - } - ] - }, - { - "type": "array", - "description": "Array of cache-memory configurations for multiple caches", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Cache identifier for this cache entry" - }, - "key": { - "type": "string", - "description": "Cache key for this memory cache (supports GitHub Actions expressions like ${{ github.workflow }}, ${{ github.run_id }}). Restore keys are auto-generated by splitting on '-'." - }, - "description": { - "type": "string", - "description": "Optional description for this cache that will be shown in the agent prompt" - }, - "retention-days": { - "type": "integer", - "minimum": 1, - "maximum": 90, - "description": "Number of days to retain uploaded artifacts (1-90 days, default: repository setting)" - }, - "restore-only": { - "type": "boolean", - "description": "If true, only restore the cache without saving it back. Uses actions/cache/restore instead of actions/cache. No artifact upload step will be generated." - } - }, - "required": ["id", "key"], - "additionalProperties": false - }, - "minItems": 1, - "examples": [ - [ - { - "id": "default", - "key": "memory-default" - }, - { - "id": "session", - "key": "memory-session" - } - ] - ] - } - ], - "examples": [ - true, - null, - { - "key": "memory-audit-workflow" - }, - [ - { - "id": "default", - "key": "memory-default" - }, - { - "id": "logs", - "key": "memory-logs" - } - ] - ] - }, - "safety-prompt": { - "type": "boolean", - "description": "Enable or disable XPIA (Cross-Prompt Injection Attack) security warnings in the prompt. Defaults to true (enabled). Set to false to disable security warnings." - }, - "timeout": { - "type": "integer", - "minimum": 1, - "description": "Timeout in seconds for tool/MCP server operations. Applies to all tools and MCP servers if supported by the engine. Default varies by engine (Claude: 60s, Codex: 120s).", - "examples": [60, 120, 300] - }, - "startup-timeout": { - "type": "integer", - "minimum": 1, - "description": "Timeout in seconds for MCP server startup. Applies to MCP server initialization if supported by the engine. Default: 120 seconds." - }, - "serena": { - "description": "Serena MCP server for AI-powered code intelligence with language service integration", - "oneOf": [ - { - "type": "null", - "description": "Enable Serena with default settings" - }, - { - "type": "array", - "description": "Short syntax: array of language identifiers to enable (e.g., [\"go\", \"typescript\"])", - "items": { - "type": "string", - "enum": ["go", "typescript", "python", "java", "rust", "csharp"] - } - }, - { - "type": "object", - "description": "Serena configuration with custom version and language-specific settings", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Optional Serena MCP version. Numeric values are automatically converted to strings at runtime.", - "examples": ["latest", "0.1.0", 1.0] - }, - "args": { - "type": "array", - "description": "Optional additional arguments to append to the generated MCP server command", - "items": { - "type": "string" - } - }, - "languages": { - "type": "object", - "description": "Language-specific configuration for Serena language services", - "properties": { - "go": { - "oneOf": [ - { - "type": "null", - "description": "Enable Go language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Go version (e.g., \"1.21\", 1.21)" - }, - "go-mod-file": { - "type": "string", - "description": "Path to go.mod file for Go version detection (e.g., \"go.mod\", \"backend/go.mod\")" - }, - "gopls-version": { - "type": "string", - "description": "Version of gopls to install (e.g., \"latest\", \"v0.14.2\")" - } - }, - "additionalProperties": false - } - ] - }, - "typescript": { - "oneOf": [ - { - "type": "null", - "description": "Enable TypeScript language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Node.js version for TypeScript (e.g., \"22\", 22)" - } - }, - "additionalProperties": false - } - ] - }, - "python": { - "oneOf": [ - { - "type": "null", - "description": "Enable Python language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Python version (e.g., \"3.12\", 3.12)" - } - }, - "additionalProperties": false - } - ] - }, - "java": { - "oneOf": [ - { - "type": "null", - "description": "Enable Java language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Java version (e.g., \"21\", 21)" - } - }, - "additionalProperties": false - } - ] - }, - "rust": { - "oneOf": [ - { - "type": "null", - "description": "Enable Rust language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Rust version (e.g., \"stable\", \"1.75\")" - } - }, - "additionalProperties": false - } - ] - }, - "csharp": { - "oneOf": [ - { - "type": "null", - "description": "Enable C# language service with default version" - }, - { - "type": "object", - "properties": { - "version": { - "type": ["string", "number"], - "description": ".NET version for C# (e.g., \"8.0\", 8.0)" - } - }, - "additionalProperties": false - } - ] - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - ] - }, - "repo-memory": { - "description": "Repo memory configuration for git-based persistent storage", - "oneOf": [ - { - "type": "boolean", - "description": "Enable repo-memory with default settings" - }, - { - "type": "null", - "description": "Enable repo-memory with default settings (same as true)" - }, - { - "type": "object", - "description": "Repo-memory configuration object", - "properties": { - "branch-prefix": { - "type": "string", - "minLength": 4, - "maxLength": 32, - "pattern": "^[a-zA-Z0-9_-]+$", - "description": "Branch prefix for memory storage (default: 'memory'). Must be 4-32 characters, alphanumeric with hyphens/underscores, and cannot be 'copilot'. Branch will be named {branch-prefix}/{id}" - }, - "target-repo": { - "type": "string", - "description": "Target repository for memory storage (default: current repository). Format: owner/repo" - }, - "branch-name": { - "type": "string", - "description": "Git branch name for memory storage (default: {branch-prefix}/default or memory/default if branch-prefix not set)" - }, - "file-glob": { - "oneOf": [ - { - "type": "string", - "description": "Single file glob pattern for allowed files" - }, - { - "type": "array", - "description": "Array of file glob patterns for allowed files", - "items": { - "type": "string" - } - } - ] - }, - "max-file-size": { - "type": "integer", - "minimum": 1, - "maximum": 104857600, - "description": "Maximum size per file in bytes (default: 10240 = 10KB)" - }, - "max-file-count": { - "type": "integer", - "minimum": 1, - "maximum": 1000, - "description": "Maximum file count per commit (default: 100)" - }, - "description": { - "type": "string", - "description": "Optional description for the memory that will be shown in the agent prompt" - }, - "create-orphan": { - "type": "boolean", - "description": "Create orphaned branch if it doesn't exist (default: true)" - }, - "campaign-id": { - "type": "string", - "description": "Campaign ID for campaign-specific repo-memory (optional, used to correlate memory with campaign workflows)" - } - }, - "additionalProperties": false, - "examples": [ - { - "branch-name": "memory/session-state" - }, - { - "target-repo": "myorg/memory-repo", - "branch-name": "memory/agent-notes", - "max-file-size": 524288 - } - ] - }, - { - "type": "array", - "description": "Array of repo-memory configurations for multiple memory locations", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Memory identifier (required for array notation, default: 'default')" - }, - "branch-prefix": { - "type": "string", - "minLength": 4, - "maxLength": 32, - "pattern": "^[a-zA-Z0-9_-]+$", - "description": "Branch prefix for memory storage (default: 'memory'). Must be 4-32 characters, alphanumeric with hyphens/underscores, and cannot be 'copilot'. Applied to all entries in the array. Branch will be named {branch-prefix}/{id}" - }, - "target-repo": { - "type": "string", - "description": "Target repository for memory storage (default: current repository). Format: owner/repo" - }, - "branch-name": { - "type": "string", - "description": "Git branch name for memory storage (default: {branch-prefix}/{id} or memory/{id} if branch-prefix not set)" - }, - "file-glob": { - "oneOf": [ - { - "type": "string", - "description": "Single file glob pattern for allowed files" - }, - { - "type": "array", - "description": "Array of file glob patterns for allowed files", - "items": { - "type": "string" - } - } - ] - }, - "max-file-size": { - "type": "integer", - "minimum": 1, - "maximum": 104857600, - "description": "Maximum size per file in bytes (default: 10240 = 10KB)" - }, - "max-file-count": { - "type": "integer", - "minimum": 1, - "maximum": 1000, - "description": "Maximum file count per commit (default: 100)" - }, - "description": { - "type": "string", - "description": "Optional description for this memory that will be shown in the agent prompt" - }, - "create-orphan": { - "type": "boolean", - "description": "Create orphaned branch if it doesn't exist (default: true)" - }, - "campaign-id": { - "type": "string", - "description": "Campaign ID for campaign-specific repo-memory (optional, used to correlate memory with campaign workflows)" - } - }, - "additionalProperties": false - }, - "minItems": 1, - "examples": [ - [ - { - "id": "default", - "branch-name": "memory/default" - }, - { - "id": "session", - "branch-name": "memory/session" - } - ] - ] - } - ], - "examples": [ - true, - null, - { - "branch-name": "memory/agent-state" - }, - [ - { - "id": "default", - "branch-name": "memory/default" - }, - { - "id": "logs", - "branch-name": "memory/logs", - "max-file-size": 524288 - } - ] - ] - } - }, - "additionalProperties": { - "oneOf": [ - { - "type": "string", - "description": "Simple tool string for basic tool configuration" - }, - { - "type": "object", - "description": "MCP server configuration object", - "properties": { - "command": { - "type": "string", - "description": "Command to execute for stdio MCP server" - }, - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments for the command" - }, - "env": { - "type": "object", - "patternProperties": { - "^[A-Za-z_][A-Za-z0-9_]*$": { - "type": "string" - } - }, - "description": "Environment variables" - }, - "mode": { - "type": "string", - "enum": ["stdio", "http", "remote", "local"], - "description": "MCP server mode" - }, - "type": { - "type": "string", - "enum": ["stdio", "http", "remote", "local"], - "description": "MCP server type" - }, - "version": { - "type": ["string", "number"], - "description": "Version of the MCP server" - }, - "toolsets": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Toolsets to enable" - }, - "url": { - "type": "string", - "description": "URL for HTTP mode MCP servers" - }, - "headers": { - "type": "object", - "patternProperties": { - "^[A-Za-z0-9_-]+$": { - "type": "string" - } - }, - "description": "HTTP headers for HTTP mode" - }, - "container": { - "type": "string", - "description": "Container image for the MCP server" - }, - "entrypointArgs": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments passed to container entrypoint" - } - }, - "additionalProperties": true - } - ] - } - }, - "command": { - "type": "string", - "description": "Command name for the workflow" - }, - "cache": { - "description": "Cache configuration for workflow (uses actions/cache syntax)", - "oneOf": [ - { - "type": "object", - "description": "Single cache configuration", - "properties": { - "key": { - "type": "string", - "description": "An explicit key for restoring and saving the cache" - }, - "path": { - "oneOf": [ - { - "type": "string", - "description": "A single path to cache" - }, - { - "type": "array", - "description": "Multiple paths to cache", - "items": { - "type": "string" - } - } - ] - }, - "restore-keys": { - "oneOf": [ - { - "type": "string", - "description": "A single restore key" - }, - { - "type": "array", - "description": "Multiple restore keys", - "items": { - "type": "string" - } - } - ] - }, - "upload-chunk-size": { - "type": "integer", - "description": "The chunk size used to split up large files during upload, in bytes" - }, - "fail-on-cache-miss": { - "type": "boolean", - "description": "Fail the workflow if cache entry is not found" - }, - "lookup-only": { - "type": "boolean", - "description": "If true, only checks if cache entry exists and skips download" - } - }, - "required": ["key", "path"], - "additionalProperties": false, - "examples": [ - { - "key": "node-modules-${{ hashFiles('package-lock.json') }}", - "path": "node_modules", - "restore-keys": ["node-modules-"] - }, - { - "key": "build-cache-${{ github.sha }}", - "path": ["dist", ".cache"], - "restore-keys": "build-cache-", - "fail-on-cache-miss": false - } - ] - }, - { - "type": "array", - "description": "Multiple cache configurations", - "items": { - "type": "object", - "properties": { - "key": { - "type": "string", - "description": "An explicit key for restoring and saving the cache" - }, - "path": { - "oneOf": [ - { - "type": "string", - "description": "A single path to cache" - }, - { - "type": "array", - "description": "Multiple paths to cache", - "items": { - "type": "string" - } - } - ] - }, - "restore-keys": { - "oneOf": [ - { - "type": "string", - "description": "A single restore key" - }, - { - "type": "array", - "description": "Multiple restore keys", - "items": { - "type": "string" - } - } - ] - }, - "upload-chunk-size": { - "type": "integer", - "description": "The chunk size used to split up large files during upload, in bytes" - }, - "fail-on-cache-miss": { - "type": "boolean", - "description": "Fail the workflow if cache entry is not found" - }, - "lookup-only": { - "type": "boolean", - "description": "If true, only checks if cache entry exists and skips download" - } - }, - "required": ["key", "path"], - "additionalProperties": false - } - } - ] - }, - "safe-outputs": { - "type": "object", - "$comment": "Required if workflow creates or modifies GitHub resources. Operations requiring safe-outputs: add-comment, add-labels, add-reviewer, assign-milestone, assign-to-agent, close-discussion, close-issue, close-pull-request, create-agent-session, create-agent-task (deprecated, use create-agent-session), create-code-scanning-alert, create-discussion, copy-project, create-issue, create-project-status-update, create-pull-request, create-pull-request-review-comment, hide-comment, link-sub-issue, mark-pull-request-as-ready-for-review, missing-tool, noop, push-to-pull-request-branch, threat-detection, update-discussion, update-issue, update-project, update-pull-request, update-release, upload-asset. See documentation for complete details.", - "description": "Safe output processing configuration that automatically creates GitHub issues, comments, and pull requests from AI workflow output without requiring write permissions in the main job", - "examples": [ - { - "create-issue": { - "title-prefix": "[AI] ", - "labels": ["automation", "ai-generated"] - } - }, - { - "create-pull-request": { - "title-prefix": "[Bot] ", - "labels": ["bot"] - } - }, - { - "add-comment": null, - "create-issue": null - } - ], - "properties": { - "allowed-domains": { - "type": "array", - "description": "List of allowed domains for URI filtering in AI workflow output. URLs from other domains will be replaced with '(redacted)' for security.", - "items": { - "type": "string" - } - }, - "allowed-github-references": { - "type": "array", - "description": "List of allowed repositories for GitHub references (e.g., #123 or owner/repo#456). Use 'repo' to allow current repository. References to other repositories will be escaped with backticks. If not specified, all references are allowed.", - "items": { - "type": "string", - "pattern": "^(repo|[a-zA-Z0-9][-a-zA-Z0-9]{0,38}/[a-zA-Z0-9._-]+)$" - }, - "examples": [["repo"], ["repo", "octocat/hello-world"], ["microsoft/vscode", "microsoft/typescript"]] - }, - "create-issue": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for automatically creating GitHub issues from AI workflow output. The main job does not need 'issues: write' permission.", - "properties": { - "title-prefix": { - "type": "string", - "description": "Optional prefix to add to the beginning of the issue title (e.g., '[ai] ' or '[analysis] ')" - }, - "labels": { - "type": "array", - "description": "Optional list of labels to automatically attach to created issues (e.g., ['automation', 'ai-generated'])", - "items": { - "type": "string" - } - }, - "allowed-labels": { - "type": "array", - "description": "Optional list of allowed labels that can be used when creating issues. If omitted, any labels are allowed (including creating new ones). When specified, the agent can only use labels from this list.", - "items": { - "type": "string" - } - }, - "assignees": { - "oneOf": [ - { - "type": "string", - "description": "Single GitHub username to assign the created issue to (e.g., 'user1' or 'copilot'). Use 'copilot' to assign to GitHub Copilot using the @copilot special value." - }, - { - "type": "array", - "description": "List of GitHub usernames to assign the created issue to (e.g., ['user1', 'user2', 'copilot']). Use 'copilot' to assign to GitHub Copilot using the @copilot special value.", - "items": { - "type": "string" - } - } - ] - }, - "max": { - "type": "integer", - "description": "Maximum number of issues to create (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository issue creation. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that issues can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the issue in. The target repository (current or target-repo) is always implicitly allowed." - }, - "expires": { - "oneOf": [ - { - "type": "integer", - "minimum": 1, - "description": "Number of days until expires" - }, - { - "type": "string", - "pattern": "^[0-9]+[hHdDwWmMyY]$", - "description": "Relative time (e.g., '2h', '7d', '2w', '1m', '1y'); minimum 2h for hour values" - } - ], - "description": "Time until the issue expires and should be automatically closed. Supports integer (days) or relative time format. Minimum duration: 2 hours. When set, a maintenance workflow will be generated." - } - }, - "additionalProperties": false, - "examples": [ - { - "title-prefix": "[ca] ", - "labels": ["automation", "dependencies"], - "assignees": "copilot" - }, - { - "title-prefix": "[duplicate-code] ", - "labels": ["code-quality", "automated-analysis"], - "assignees": "copilot" - }, - { - "allowed-repos": ["org/other-repo", "org/another-repo"], - "title-prefix": "[cross-repo] " - } - ] - }, - { - "type": "null", - "description": "Enable issue creation with default configuration" - } - ] - }, - "create-agent-task": { - "oneOf": [ - { - "type": "object", - "description": "DEPRECATED: Use 'create-agent-session' instead. Configuration for creating GitHub Copilot agent sessions from agentic workflow output using gh agent-task CLI. The main job does not need write permissions.", - "deprecated": true, - "properties": { - "base": { - "type": "string", - "description": "Base branch for the agent session pull request. Defaults to the current branch or repository default branch." - }, - "max": { - "type": "integer", - "description": "Maximum number of agent sessions to create (default: 1)", - "minimum": 1, - "maximum": 1 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository agent session creation. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that agent sessions can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the agent session in. The target repository (current or target-repo) is always implicitly allowed." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable agent session creation with default configuration" - } - ] - }, - "create-agent-session": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating GitHub Copilot agent sessions from agentic workflow output using gh agent-task CLI. The main job does not need write permissions.", - "properties": { - "base": { - "type": "string", - "description": "Base branch for the agent session pull request. Defaults to the current branch or repository default branch." - }, - "max": { - "type": "integer", - "description": "Maximum number of agent sessions to create (default: 1)", - "minimum": 1, - "maximum": 1 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository agent session creation. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that agent sessions can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the agent session in. The target repository (current or target-repo) is always implicitly allowed." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable agent session creation with default configuration" - } - ] - }, - "update-project": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for managing GitHub Projects v2 boards. Smart tool that can add issue/PR items and update custom fields on existing items. By default it is update-only: if the project does not exist, the job fails with instructions to create it manually. To allow workflows to create missing projects, explicitly opt in via the agent output field create_if_missing=true (and/or provide a github-token override). NOTE: Projects v2 requires a Personal Access Token (PAT) or GitHub App token with appropriate permissions; the GITHUB_TOKEN cannot be used for Projects v2. Safe output items produced by the agent use type=update_project and may include: project (board name), content_type (issue|pull_request), content_number, fields, campaign_id, and create_if_missing.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of project operations to perform (default: 10). Each operation may add a project item, or update its fields.", - "minimum": 1, - "maximum": 100 - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false, - "examples": [ - { - "max": 15 - }, - { - "github-token": "${{ secrets.PROJECT_GITHUB_TOKEN }}", - "max": 15 - } - ] - }, - { - "type": "null", - "description": "Enable project management with default configuration (max=10)" - } - ] - }, - "copy-project": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for copying GitHub Projects v2 boards. Creates a new project with the same structure, fields, and views as the source project. By default, draft issues are NOT copied unless explicitly requested with includeDraftIssues=true in the tool call. Requires a Personal Access Token (PAT) or GitHub App token with Projects permissions; the GITHUB_TOKEN cannot be used. Safe output items use type=copy_project and include: sourceProject (URL), owner (org/user login), title (new project name), and optional includeDraftIssues (boolean). The source-project and target-owner can be configured in the workflow frontmatter to provide defaults that the agent can use or override.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of copy operations to perform (default: 1).", - "minimum": 1, - "maximum": 100 - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Must have Projects write permission. Overrides global github-token if specified." - }, - "source-project": { - "type": "string", - "pattern": "^https://github\\.com/(orgs|users)/[^/]+/projects/\\d+$", - "description": "Optional default source project URL to copy from (e.g., 'https://github.com/orgs/myorg/projects/42'). If specified, the agent can omit the sourceProject field in the tool call and this default will be used. The agent can still override by providing a sourceProject in the tool call." - }, - "target-owner": { - "type": "string", - "description": "Optional default target owner (organization or user login name) where the new project will be created (e.g., 'myorg' or 'username'). If specified, the agent can omit the owner field in the tool call and this default will be used. The agent can still override by providing an owner in the tool call." - } - }, - "additionalProperties": false, - "examples": [ - { - "max": 1 - }, - { - "github-token": "${{ secrets.PROJECT_GITHUB_TOKEN }}", - "max": 1 - }, - { - "source-project": "https://github.com/orgs/myorg/projects/42", - "target-owner": "myorg", - "max": 1 - } - ] - }, - { - "type": "null", - "description": "Enable project copying with default configuration (max=1)" - } - ] - }, - "create-project-status-update": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating GitHub Project status updates. Status updates provide stakeholder communication and historical record of project progress. Requires a Personal Access Token (PAT) or GitHub App token with Projects: Read+Write permission. The GITHUB_TOKEN cannot be used for Projects v2. Status updates are created on the specified project board and appear in the Updates tab. Typically used by campaign orchestrators to post run summaries with progress, findings, and next steps.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of status updates to create (default: 1). Typically 1 per orchestrator run.", - "minimum": 1, - "maximum": 10 - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified. Must have Projects: Read+Write permission." - } - }, - "additionalProperties": false, - "examples": [ - { - "max": 1 - }, - { - "github-token": "${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}", - "max": 1 - } - ] - }, - { - "type": "null", - "description": "Enable project status updates with default configuration (max=1)" - } - ] - }, - "create-discussion": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating GitHub discussions from agentic workflow output", - "properties": { - "title-prefix": { - "type": "string", - "description": "Optional prefix for the discussion title" - }, - "category": { - "type": ["string", "number"], - "description": "Optional discussion category. Can be a category ID (string or numeric value), category name, or category slug/route. If not specified, uses the first available category. Matched first against category IDs, then against category names, then against category slugs. Numeric values are automatically converted to strings at runtime.", - "examples": ["General", "audits", 123456789] - }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of labels to attach to created discussions. Also used for matching when close-older-discussions is enabled - discussions must have ALL specified labels (AND logic)." - }, - "allowed-labels": { - "type": "array", - "description": "Optional list of allowed labels that can be used when creating discussions. If omitted, any labels are allowed (including creating new ones). When specified, the agent can only use labels from this list.", - "items": { - "type": "string" - } - }, - "max": { - "type": "integer", - "description": "Maximum number of discussions to create (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository discussion creation. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that discussions can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the discussion in. The target repository (current or target-repo) is always implicitly allowed." - }, - "close-older-discussions": { - "type": "boolean", - "description": "When true, automatically close older discussions matching the same title prefix or labels as 'outdated' with a comment linking to the new discussion. Requires title-prefix or labels to be set. Maximum 10 discussions will be closed. Only runs if discussion creation succeeds.", - "default": false - }, - "expires": { - "oneOf": [ - { - "type": "integer", - "minimum": 1, - "description": "Number of days until expires" - }, - { - "type": "string", - "pattern": "^[0-9]+[hHdDwWmMyY]$", - "description": "Relative time (e.g., '2h', '7d', '2w', '1m', '1y'); minimum 2h for hour values" - } - ], - "default": 7, - "description": "Time until the discussion expires and should be automatically closed. Supports integer (days) or relative time format like '2h' (2 hours), '7d' (7 days), '2w' (2 weeks), '1m' (1 month), '1y' (1 year). Minimum duration: 2 hours. When set, a maintenance workflow will be generated. Defaults to 7 days if not specified." - } - }, - "additionalProperties": false, - "examples": [ - { - "category": "audits" - }, - { - "title-prefix": "[copilot-agent-analysis] ", - "category": "audits", - "max": 1 - }, - { - "category": "General" - }, - { - "title-prefix": "[weekly-report] ", - "category": "reports", - "close-older-discussions": true - }, - { - "labels": ["weekly-report", "automation"], - "category": "reports", - "close-older-discussions": true - }, - { - "allowed-repos": ["org/other-repo"], - "category": "General" - } - ] - }, - { - "type": "null", - "description": "Enable discussion creation with default configuration" - } - ] - }, - "close-discussion": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for closing GitHub discussions with comment and resolution from agentic workflow output", - "properties": { - "required-labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only close discussions that have all of these labels" - }, - "required-title-prefix": { - "type": "string", - "description": "Only close discussions with this title prefix" - }, - "required-category": { - "type": "string", - "description": "Only close discussions in this category" - }, - "target": { - "type": "string", - "description": "Target for closing: 'triggering' (default, current discussion), or '*' (any discussion with discussion_number field)" - }, - "max": { - "type": "integer", - "description": "Maximum number of discussions to close (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository operations. Takes precedence over trial target repo settings." - } - }, - "additionalProperties": false, - "examples": [ - { - "required-category": "Ideas" - }, - { - "required-labels": ["resolved", "completed"], - "max": 1 - } - ] - }, - { - "type": "null", - "description": "Enable discussion closing with default configuration" - } - ] - }, - "update-discussion": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for updating GitHub discussions from agentic workflow output", - "properties": { - "target": { - "type": "string", - "description": "Target for updates: 'triggering' (default), '*' (any discussion), or explicit discussion number" - }, - "title": { - "type": "null", - "description": "Allow updating discussion title - presence of key indicates field can be updated" - }, - "body": { - "type": "null", - "description": "Allow updating discussion body - presence of key indicates field can be updated" - }, - "labels": { - "type": "null", - "description": "Allow updating discussion labels - presence of key indicates field can be updated" - }, - "allowed-labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones)." - }, - "max": { - "type": "integer", - "description": "Maximum number of discussions to update (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository discussion updates. Takes precedence over trial target repo settings." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable discussion updating with default configuration" - } - ] - }, - "close-issue": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for closing GitHub issues with comment from agentic workflow output", - "properties": { - "required-labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only close issues that have all of these labels" - }, - "required-title-prefix": { - "type": "string", - "description": "Only close issues with this title prefix" - }, - "target": { - "type": "string", - "description": "Target for closing: 'triggering' (default, current issue), or '*' (any issue with issue_number field)" - }, - "max": { - "type": "integer", - "description": "Maximum number of issues to close (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository operations. Takes precedence over trial target repo settings." - } - }, - "additionalProperties": false, - "examples": [ - { - "required-title-prefix": "[refactor] " - }, - { - "required-labels": ["automated", "stale"], - "max": 10 - } - ] - }, - { - "type": "null", - "description": "Enable issue closing with default configuration" - } - ] - }, - "close-pull-request": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for closing GitHub pull requests without merging, with comment from agentic workflow output", - "properties": { - "required-labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only close pull requests that have any of these labels" - }, - "required-title-prefix": { - "type": "string", - "description": "Only close pull requests with this title prefix" - }, - "target": { - "type": "string", - "description": "Target for closing: 'triggering' (default, current PR), or '*' (any PR with pull_request_number field)" - }, - "max": { - "type": "integer", - "description": "Maximum number of pull requests to close (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository operations. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false, - "examples": [ - { - "required-title-prefix": "[bot] " - }, - { - "required-labels": ["automated", "outdated"], - "max": 5 - } - ] - }, - { - "type": "null", - "description": "Enable pull request closing with default configuration" - } - ] - }, - "mark-pull-request-as-ready-for-review": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for marking draft pull requests as ready for review, with comment from agentic workflow output", - "properties": { - "required-labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only mark pull requests that have any of these labels" - }, - "required-title-prefix": { - "type": "string", - "description": "Only mark pull requests with this title prefix" - }, - "target": { - "type": "string", - "description": "Target for marking: 'triggering' (default, current PR), or '*' (any PR with pull_request_number field)" - }, - "max": { - "type": "integer", - "description": "Maximum number of pull requests to mark as ready (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository operations. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false, - "examples": [ - { - "required-title-prefix": "[bot] " - }, - { - "required-labels": ["automated", "ready"], - "max": 1 - } - ] - }, - { - "type": "null", - "description": "Enable marking pull requests as ready for review with default configuration" - } - ] - }, - "add-comment": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for automatically creating GitHub issue or pull request comments from AI workflow output. The main job does not need write permissions.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of comments to create (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target": { - "type": "string", - "description": "Target for comments: 'triggering' (default), '*' (any issue), or explicit issue number" - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository comments. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that comments can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the comment in. The target repository (current or target-repo) is always implicitly allowed." - }, - "discussion": { - "type": "boolean", - "const": true, - "description": "Target discussion comments instead of issue/PR comments. Must be true if present." - }, - "hide-older-comments": { - "type": "boolean", - "description": "When true, minimizes/hides all previous comments from the same agentic workflow (identified by tracker-id) before creating the new comment. Default: false." - }, - "allowed-reasons": { - "type": "array", - "description": "List of allowed reasons for hiding older comments when hide-older-comments is enabled. Default: all reasons allowed (spam, abuse, off_topic, outdated, resolved).", - "items": { - "type": "string", - "enum": ["spam", "abuse", "off_topic", "outdated", "resolved"] - } - } - }, - "additionalProperties": false, - "examples": [ - { - "max": 1, - "target": "*" - }, - { - "max": 3 - } - ] - }, - { - "type": "null", - "description": "Enable issue comment creation with default configuration" - } - ] - }, - "create-pull-request": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating GitHub pull requests from agentic workflow output. Note: The max parameter is not supported for pull requests - workflows are always limited to creating 1 pull request per run. This design decision prevents workflow runs from creating excessive PRs and maintains repository integrity.", - "properties": { - "title-prefix": { - "type": "string", - "description": "Optional prefix for the pull request title" - }, - "labels": { - "type": "array", - "description": "Optional list of labels to attach to the pull request", - "items": { - "type": "string" - } - }, - "allowed-labels": { - "type": "array", - "description": "Optional list of allowed labels that can be used when creating pull requests. If omitted, any labels are allowed (including creating new ones). When specified, the agent can only use labels from this list.", - "items": { - "type": "string" - } - }, - "reviewers": { - "oneOf": [ - { - "type": "string", - "description": "Single reviewer username to assign to the pull request. Use 'copilot' to request a code review from GitHub Copilot using the copilot-pull-request-reviewer[bot]." - }, - { - "type": "array", - "description": "List of reviewer usernames to assign to the pull request. Use 'copilot' to request a code review from GitHub Copilot using the copilot-pull-request-reviewer[bot].", - "items": { - "type": "string" - } - } - ], - "description": "Optional reviewer(s) to assign to the pull request. Accepts either a single string or an array of usernames. Use 'copilot' to request a code review from GitHub Copilot." - }, - "draft": { - "type": "boolean", - "description": "Whether to create pull request as draft (defaults to true)" - }, - "if-no-changes": { - "type": "string", - "enum": ["warn", "error", "ignore"], - "description": "Behavior when no changes to push: 'warn' (default - log warning but succeed), 'error' (fail the action), or 'ignore' (silent success)" - }, - "allow-empty": { - "type": "boolean", - "description": "When true, allows creating a pull request without any initial changes or git patch. This is useful for preparing a feature branch that an agent can push changes to later. The branch will be created from the base branch without applying any patch. Defaults to false." - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository pull request creation. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that pull requests can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the pull request in. The target repository (current or target-repo) is always implicitly allowed." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - }, - "expires": { - "oneOf": [ - { - "type": "integer", - "minimum": 1, - "description": "Number of days until expires" - }, - { - "type": "string", - "pattern": "^[0-9]+[hHdDwWmMyY]$", - "description": "Relative time (e.g., '2h', '7d', '2w', '1m', '1y'); minimum 2h for hour values" - } - ], - "description": "Time until the pull request expires and should be automatically closed (only for same-repo PRs without target-repo). Supports integer (days) or relative time format. Minimum duration: 2 hours." - } - }, - "additionalProperties": false, - "examples": [ - { - "title-prefix": "[docs] ", - "labels": ["documentation", "automation"], - "reviewers": "copilot", - "draft": false - }, - { - "title-prefix": "[security-fix] ", - "labels": ["security", "automated-fix"], - "reviewers": "copilot" - } - ] - }, - { - "type": "null", - "description": "Enable pull request creation with default configuration" - } - ] - }, - "create-pull-request-review-comment": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating GitHub pull request review comments from agentic workflow output", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of review comments to create (default: 10)", - "minimum": 1, - "maximum": 100 - }, - "side": { - "type": "string", - "description": "Side of the diff for comments: 'LEFT' or 'RIGHT' (default: 'RIGHT')", - "enum": ["LEFT", "RIGHT"] - }, - "target": { - "type": "string", - "description": "Target for review comments: 'triggering' (default, only on triggering PR), '*' (any PR, requires pull_request_number in agent output), or explicit PR number" - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository PR review comments. Takes precedence over trial target repo settings." - }, - "allowed-repos": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of additional repositories in format 'owner/repo' that PR review comments can be created in. When specified, the agent can use a 'repo' field in the output to specify which repository to create the review comment in. The target repository (current or target-repo) is always implicitly allowed." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable PR review comment creation with default configuration" - } - ] - }, - "create-code-scanning-alert": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for creating repository security advisories (SARIF format) from agentic workflow output", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of security findings to include (default: unlimited)", - "minimum": 1 - }, - "driver": { - "type": "string", - "description": "Driver name for SARIF tool.driver.name field (default: 'GitHub Agentic Workflows Security Scanner')" - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable code scanning alert creation with default configuration (unlimited findings)" - } - ] - }, - "add-labels": { - "oneOf": [ - { - "type": "null", - "description": "Null configuration allows any labels. Labels will be created if they don't already exist in the repository." - }, - { - "type": "object", - "description": "Configuration for adding labels to issues/PRs from agentic workflow output. Labels will be created if they don't already exist in the repository.", - "properties": { - "allowed": { - "type": "array", - "description": "Optional list of allowed labels that can be added. Labels will be created if they don't already exist in the repository. If omitted, any labels are allowed (including creating new ones).", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "max": { - "type": "integer", - "description": "Optional maximum number of labels to add (default: 3)", - "minimum": 1 - }, - "target": { - "type": "string", - "description": "Target for labels: 'triggering' (default), '*' (any issue/PR), or explicit issue/PR number" - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository label addition. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "add-reviewer": { - "oneOf": [ - { - "type": "null", - "description": "Null configuration allows any reviewers" - }, - { - "type": "object", - "description": "Configuration for adding reviewers to pull requests from agentic workflow output", - "properties": { - "reviewers": { - "type": "array", - "description": "Optional list of allowed reviewers. If omitted, any reviewers are allowed.", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "max": { - "type": "integer", - "description": "Optional maximum number of reviewers to add (default: 3)", - "minimum": 1 - }, - "target": { - "type": "string", - "description": "Target for reviewers: 'triggering' (default), '*' (any PR), or explicit PR number" - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository reviewer addition. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "assign-milestone": { - "oneOf": [ - { - "type": "null", - "description": "Null configuration allows assigning any milestones" - }, - { - "type": "object", - "description": "Configuration for assigning issues to milestones from agentic workflow output", - "properties": { - "allowed": { - "type": "array", - "description": "Optional list of allowed milestone titles that can be assigned. If omitted, any milestones are allowed.", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "max": { - "type": "integer", - "description": "Optional maximum number of milestone assignments (default: 1)", - "minimum": 1 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository milestone assignment. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "assign-to-agent": { - "oneOf": [ - { - "type": "null", - "description": "Null configuration uses default agent (copilot)" - }, - { - "type": "object", - "description": "Configuration for assigning GitHub Copilot agents to issues from agentic workflow output", - "properties": { - "name": { - "type": "string", - "description": "Default agent name to assign (default: 'copilot')" - }, - "max": { - "type": "integer", - "description": "Optional maximum number of agent assignments (default: 1)", - "minimum": 1 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository agent assignment. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "assign-to-user": { - "oneOf": [ - { - "type": "null", - "description": "Enable user assignment with default configuration" - }, - { - "type": "object", - "description": "Configuration for assigning users to issues from agentic workflow output", - "properties": { - "allowed": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of allowed usernames. If specified, only these users can be assigned." - }, - "max": { - "type": "integer", - "description": "Optional maximum number of user assignments (default: 1)", - "minimum": 1 - }, - "target": { - "type": ["string", "number"], - "description": "Target issue to assign users to. Use 'triggering' (default) for the triggering issue, '*' to allow any issue, or a specific issue number." - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository user assignment. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "link-sub-issue": { - "oneOf": [ - { - "type": "null", - "description": "Enable sub-issue linking with default configuration" - }, - { - "type": "object", - "description": "Configuration for linking issues as sub-issues from agentic workflow output", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of sub-issue links to create (default: 5)", - "minimum": 1, - "maximum": 100 - }, - "parent-required-labels": { - "type": "array", - "description": "Optional list of labels that parent issues must have to be eligible for linking", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "parent-title-prefix": { - "type": "string", - "description": "Optional title prefix that parent issues must have to be eligible for linking" - }, - "sub-required-labels": { - "type": "array", - "description": "Optional list of labels that sub-issues must have to be eligible for linking", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "sub-title-prefix": { - "type": "string", - "description": "Optional title prefix that sub-issues must have to be eligible for linking" - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository sub-issue linking. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "update-issue": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for updating GitHub issues from agentic workflow output", - "properties": { - "status": { - "type": "null", - "description": "Allow updating issue status (open/closed) - presence of key indicates field can be updated" - }, - "target": { - "type": "string", - "description": "Target for updates: 'triggering' (default), '*' (any issue), or explicit issue number" - }, - "title": { - "type": "null", - "description": "Allow updating issue title - presence of key indicates field can be updated" - }, - "body": { - "type": "null", - "description": "Allow updating issue body - presence of key indicates field can be updated" - }, - "max": { - "type": "integer", - "description": "Maximum number of issues to update (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository issue updates. Takes precedence over trial target repo settings." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable issue updating with default configuration" - } - ] - }, - "update-pull-request": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for updating GitHub pull requests from agentic workflow output. Both title and body updates are enabled by default.", - "properties": { - "target": { - "type": "string", - "description": "Target for updates: 'triggering' (default), '*' (any PR), or explicit PR number" - }, - "title": { - "type": "boolean", - "description": "Allow updating pull request title - defaults to true, set to false to disable" - }, - "body": { - "type": "boolean", - "description": "Allow updating pull request body - defaults to true, set to false to disable" - }, - "max": { - "type": "integer", - "description": "Maximum number of pull requests to update (default: 1)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository pull request updates. Takes precedence over trial target repo settings." - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable pull request updating with default configuration (title and body updates enabled)" - } - ] - }, - "push-to-pull-request-branch": { - "oneOf": [ - { - "type": "null", - "description": "Use default configuration (branch: 'triggering', if-no-changes: 'warn')" - }, - { - "type": "object", - "description": "Configuration for pushing changes to a specific branch from agentic workflow output", - "properties": { - "branch": { - "type": "string", - "description": "The branch to push changes to (defaults to 'triggering')" - }, - "target": { - "type": "string", - "description": "Target for push operations: 'triggering' (default), '*' (any pull request), or explicit pull request number" - }, - "title-prefix": { - "type": "string", - "description": "Required prefix for pull request title. Only pull requests with this prefix will be accepted." - }, - "labels": { - "type": "array", - "description": "Required labels for pull request validation. Only pull requests with all these labels will be accepted.", - "items": { - "type": "string" - } - }, - "if-no-changes": { - "type": "string", - "enum": ["warn", "error", "ignore"], - "description": "Behavior when no changes to push: 'warn' (default - log warning but succeed), 'error' (fail the action), or 'ignore' (silent success)" - }, - "commit-title-suffix": { - "type": "string", - "description": "Optional suffix to append to generated commit titles (e.g., ' [skip ci]' to prevent triggering CI on the commit)" - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - } - ] - }, - "hide-comment": { - "oneOf": [ - { - "type": "null", - "description": "Enable comment hiding with default configuration" - }, - { - "type": "object", - "description": "Configuration for hiding comments on GitHub issues, pull requests, or discussions from agentic workflow output", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of comments to hide (default: 5)", - "minimum": 1, - "maximum": 100 - }, - "target-repo": { - "type": "string", - "description": "Target repository in format 'owner/repo' for cross-repository comment hiding. Takes precedence over trial target repo settings." - }, - "allowed-reasons": { - "type": "array", - "description": "List of allowed reasons for hiding comments. Default: all reasons allowed (spam, abuse, off_topic, outdated, resolved).", - "items": { - "type": "string", - "enum": ["spam", "abuse", "off_topic", "outdated", "resolved"] - } - } - }, - "additionalProperties": false - } - ] - }, - "missing-tool": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for reporting missing tools from agentic workflow output", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of missing tool reports (default: unlimited)", - "minimum": 1 - }, - "create-issue": { - "type": "boolean", - "description": "Whether to create or update GitHub issues when tools are missing (default: true)", - "default": true - }, - "title-prefix": { - "type": "string", - "description": "Prefix for issue titles when creating issues for missing tools (default: '[missing tool]')", - "default": "[missing tool]" - }, - "labels": { - "type": "array", - "description": "Labels to add to created issues for missing tools", - "items": { - "type": "string" - }, - "default": [] - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable missing tool reporting with default configuration" - }, - { - "type": "boolean", - "const": false, - "description": "Explicitly disable missing tool reporting (false). Missing tool reporting is enabled by default when safe-outputs is configured." - } - ] - }, - "missing-data": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for reporting missing data required to achieve workflow goals. Encourages AI agents to be truthful about data gaps instead of hallucinating information.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of missing data reports (default: unlimited)", - "minimum": 1 - }, - "create-issue": { - "type": "boolean", - "description": "Whether to create or update GitHub issues when data is missing (default: true)", - "default": true - }, - "title-prefix": { - "type": "string", - "description": "Prefix for issue titles when creating issues for missing data (default: '[missing data]')", - "default": "[missing data]" - }, - "labels": { - "type": "array", - "description": "Labels to add to created issues for missing data", - "items": { - "type": "string" - }, - "default": [] - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable missing data reporting with default configuration" - }, - { - "type": "boolean", - "const": false, - "description": "Explicitly disable missing data reporting (false). Missing data reporting is enabled by default when safe-outputs is configured." - } - ] - }, - "noop": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for no-op safe output (logging only, no GitHub API calls). Always available as a fallback to ensure human-visible artifacts.", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of noop messages (default: 1)", - "minimum": 1, - "default": 1 - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable noop output with default configuration (max: 1)" - }, - { - "type": "boolean", - "const": false, - "description": "Explicitly disable noop output (false). Noop is enabled by default when safe-outputs is configured." - } - ] - }, - "upload-asset": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for publishing assets to an orphaned git branch", - "properties": { - "branch": { - "type": "string", - "description": "Branch name (default: 'assets/${{ github.workflow }}')", - "default": "assets/${{ github.workflow }}" - }, - "max-size": { - "type": "integer", - "description": "Maximum file size in KB (default: 10240 = 10MB)", - "minimum": 1, - "maximum": 51200, - "default": 10240 - }, - "allowed-exts": { - "type": "array", - "description": "Allowed file extensions (default: common non-executable types)", - "items": { - "type": "string", - "pattern": "^\\.[a-zA-Z0-9]+$" - } - }, - "max": { - "type": "integer", - "description": "Maximum number of assets to upload (default: 10)", - "minimum": 1, - "maximum": 100 - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for this specific output type. Overrides global github-token if specified." - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable asset publishing with default configuration" - } - ] - }, - "update-release": { - "oneOf": [ - { - "type": "object", - "description": "Configuration for updating GitHub release descriptions", - "properties": { - "max": { - "type": "integer", - "description": "Maximum number of releases to update (default: 1)", - "minimum": 1, - "maximum": 10, - "default": 1 - }, - "target-repo": { - "type": "string", - "description": "Target repository for cross-repo release updates (format: owner/repo). If not specified, updates releases in the workflow's repository.", - "pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$" - } - }, - "additionalProperties": false - }, - { - "type": "null", - "description": "Enable release updates with default configuration" - } - ] - }, - "staged": { - "type": "boolean", - "description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)", - "examples": [true, false] - }, - "env": { - "type": "object", - "description": "Environment variables to pass to safe output jobs", - "patternProperties": { - "^[A-Za-z_][A-Za-z0-9_]*$": { - "type": "string", - "description": "Environment variable value, typically a secret reference like ${{ secrets.TOKEN_NAME }}" - } - }, - "additionalProperties": false - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token to use for safe output jobs. Typically a secret reference like ${{ secrets.GITHUB_TOKEN }} or ${{ secrets.CUSTOM_PAT }}", - "examples": ["${{ secrets.GITHUB_TOKEN }}", "${{ secrets.CUSTOM_PAT }}", "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}"] - }, - "app": { - "type": "object", - "description": "GitHub App credentials for minting installation access tokens. When configured, a token will be generated using the app credentials and used for all safe output operations.", - "properties": { - "app-id": { - "type": "string", - "description": "GitHub App ID. Should reference a variable (e.g., ${{ vars.APP_ID }}).", - "examples": ["${{ vars.APP_ID }}", "${{ secrets.APP_ID }}"] - }, - "private-key": { - "type": "string", - "description": "GitHub App private key. Should reference a secret (e.g., ${{ secrets.APP_PRIVATE_KEY }}).", - "examples": ["${{ secrets.APP_PRIVATE_KEY }}"] - }, - "owner": { - "type": "string", - "description": "Optional: The owner of the GitHub App installation. If empty, defaults to the current repository owner.", - "examples": ["my-organization", "${{ github.repository_owner }}"] - }, - "repositories": { - "type": "array", - "description": "Optional: Comma or newline-separated list of repositories to grant access to. If owner is set and repositories is empty, access will be scoped to all repositories in the provided repository owner's installation. If owner and repositories are empty, access will be scoped to only the current repository.", - "items": { - "type": "string" - }, - "examples": [["repo1", "repo2"], ["my-repo"]] - } - }, - "required": ["app-id", "private-key"], - "additionalProperties": false - }, - "max-patch-size": { - "type": "integer", - "description": "Maximum allowed size for git patches in kilobytes (KB). Defaults to 1024 KB (1 MB). If patch exceeds this size, the job will fail.", - "minimum": 1, - "maximum": 10240, - "default": 1024 - }, - "threat-detection": { - "oneOf": [ - { - "type": "boolean", - "description": "Enable or disable threat detection for safe outputs (defaults to true when safe-outputs are configured)" - }, - { - "type": "object", - "description": "Threat detection configuration object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether threat detection is enabled", - "default": true - }, - "prompt": { - "type": "string", - "description": "Additional custom prompt instructions to append to threat detection analysis" - }, - "engine": { - "description": "AI engine configuration specifically for threat detection (overrides main workflow engine). Set to false to disable AI-based threat detection. Supports same format as main engine field when not false.", - "oneOf": [ - { - "type": "boolean", - "const": false, - "description": "Disable AI engine for threat detection (only run custom steps)" - }, - { - "$ref": "#/$defs/engine_config" - } - ] - }, - "steps": { - "type": "array", - "description": "Array of extra job steps to run after detection", - "items": { - "$ref": "#/$defs/githubActionsStep" - } - } - }, - "additionalProperties": false - } - ] - }, - "jobs": { - "type": "object", - "description": "Custom safe-output jobs that can be executed based on agentic workflow output. Job names containing dashes will be automatically normalized to underscores (e.g., 'send-notification' becomes 'send_notification').", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "object", - "description": "Custom safe-output job configuration. The job name will be normalized to use underscores instead of dashes.", - "properties": { - "name": { - "type": "string", - "description": "Display name for the job" - }, - "description": { - "type": "string", - "description": "Description of the safe-job (used in MCP tool registration)" - }, - "runs-on": { - "description": "Runner specification for this job", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "if": { - "type": "string", - "description": "Conditional expression for job execution" - }, - "needs": { - "description": "Job dependencies beyond the main job", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "env": { - "type": "object", - "description": "Job-specific environment variables", - "patternProperties": { - "^[A-Za-z_][A-Za-z0-9_]*$": { - "type": "string" - } - }, - "additionalProperties": false - }, - "permissions": { - "$ref": "#/properties/permissions" - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token for this specific job" - }, - "output": { - "type": "string", - "description": "Output configuration for the safe job" - }, - "inputs": { - "type": "object", - "description": "Input parameters for the safe job (workflow_dispatch syntax) - REQUIRED: at least one input must be defined", - "minProperties": 1, - "maxProperties": 25, - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Input parameter description" - }, - "required": { - "type": "boolean", - "description": "Whether this input is required", - "default": false - }, - "default": { - "type": "string", - "description": "Default value for the input" - }, - "type": { - "type": "string", - "enum": ["string", "boolean", "choice"], - "description": "Input parameter type", - "default": "string" - }, - "options": { - "type": "array", - "description": "Available options for choice type inputs", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "steps": { - "type": "array", - "description": "Custom steps to execute in the safe job", - "items": { - "$ref": "#/$defs/githubActionsStep" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "messages": { - "type": "object", - "description": "Custom message templates for safe-output footer and notification messages. Available placeholders: {workflow_name} (workflow name), {run_url} (GitHub Actions run URL), {triggering_number} (issue/PR/discussion number), {workflow_source} (owner/repo/path@ref), {workflow_source_url} (GitHub URL to source), {operation} (safe-output operation name for staged mode).", - "properties": { - "footer": { - "type": "string", - "description": "Custom footer message template for AI-generated content. Available placeholders: {workflow_name}, {run_url}, {triggering_number}, {workflow_source}, {workflow_source_url}. Example: '> Generated by [{workflow_name}]({run_url})'", - "examples": ["> Generated by [{workflow_name}]({run_url})", "> AI output from [{workflow_name}]({run_url}) for #{triggering_number}"] - }, - "footer-install": { - "type": "string", - "description": "Custom installation instructions template appended to the footer. Available placeholders: {workflow_source}, {workflow_source_url}. Example: '> Install: `gh aw add {workflow_source}`'", - "examples": ["> Install: `gh aw add {workflow_source}`", "> [Add this workflow]({workflow_source_url})"] - }, - "staged-title": { - "type": "string", - "description": "Custom title template for staged mode preview. Available placeholders: {operation}. Example: '\ud83c\udfad Preview: {operation}'", - "examples": ["\ud83c\udfad Preview: {operation}", "## Staged Mode: {operation}"] - }, - "staged-description": { - "type": "string", - "description": "Custom description template for staged mode preview. Available placeholders: {operation}. Example: 'The following {operation} would occur if staged mode was disabled:'", - "examples": ["The following {operation} would occur if staged mode was disabled:"] - }, - "run-started": { - "type": "string", - "description": "Custom message template for workflow activation comment. Available placeholders: {workflow_name}, {run_url}, {event_type}. Default: 'Agentic [{workflow_name}]({run_url}) triggered by this {event_type}.'", - "examples": ["Agentic [{workflow_name}]({run_url}) triggered by this {event_type}.", "[{workflow_name}]({run_url}) started processing this {event_type}."] - }, - "run-success": { - "type": "string", - "description": "Custom message template for successful workflow completion. Available placeholders: {workflow_name}, {run_url}. Default: '\u2705 Agentic [{workflow_name}]({run_url}) completed successfully.'", - "examples": ["\u2705 Agentic [{workflow_name}]({run_url}) completed successfully.", "\u2705 [{workflow_name}]({run_url}) finished."] - }, - "run-failure": { - "type": "string", - "description": "Custom message template for failed workflow. Available placeholders: {workflow_name}, {run_url}, {status}. Default: '\u274c Agentic [{workflow_name}]({run_url}) {status} and wasn't able to produce a result.'", - "examples": ["\u274c Agentic [{workflow_name}]({run_url}) {status} and wasn't able to produce a result.", "\u274c [{workflow_name}]({run_url}) {status}."] - }, - "detection-failure": { - "type": "string", - "description": "Custom message template for detection job failure. Available placeholders: {workflow_name}, {run_url}. Default: '\u26a0\ufe0f Security scanning failed for [{workflow_name}]({run_url}). Review the logs for details.'", - "examples": ["\u26a0\ufe0f Security scanning failed for [{workflow_name}]({run_url}). Review the logs for details.", "\u26a0\ufe0f Detection job failed in [{workflow_name}]({run_url})."] - } - }, - "additionalProperties": false - }, - "mentions": { - "description": "Configuration for @mention filtering in safe outputs. Controls whether and how @mentions in AI-generated content are allowed or escaped.", - "oneOf": [ - { - "type": "boolean", - "description": "Simple boolean mode: false = always escape mentions, true = always allow mentions (error in strict mode)" - }, - { - "type": "object", - "description": "Advanced configuration for @mention filtering with fine-grained control", - "properties": { - "allow-team-members": { - "type": "boolean", - "description": "Allow mentions of repository team members (collaborators with any permission level, excluding bots). Default: true", - "default": true - }, - "allow-context": { - "type": "boolean", - "description": "Allow mentions inferred from event context (issue/PR authors, assignees, commenters). Default: true", - "default": true - }, - "allowed": { - "type": "array", - "description": "List of user/bot names always allowed to be mentioned. Bots are not allowed by default unless listed here.", - "items": { - "type": "string", - "minLength": 1 - } - }, - "max": { - "type": "integer", - "description": "Maximum number of mentions allowed per message. Default: 50", - "minimum": 1, - "default": 50 - } - }, - "additionalProperties": false - } - ] - }, - "runs-on": { - "type": "string", - "description": "Runner specification for all safe-outputs jobs (activation, create-issue, add-comment, etc.). Single runner label (e.g., 'ubuntu-slim', 'ubuntu-latest', 'windows-latest', 'self-hosted'). Defaults to 'ubuntu-slim'. See https://github.blog/changelog/2025-10-28-1-vcpu-linux-runner-now-available-in-github-actions-in-public-preview/" - } - }, - "additionalProperties": false - }, - "secret-masking": { - "type": "object", - "description": "Configuration for secret redaction behavior in workflow outputs and artifacts", - "properties": { - "steps": { - "type": "array", - "description": "Additional secret redaction steps to inject after the built-in secret redaction. Use this to mask secrets in generated files using custom patterns.", - "items": { - "$ref": "#/$defs/githubActionsStep" - }, - "examples": [ - [ - { - "name": "Redact custom secrets", - "run": "find /tmp/gh-aw -type f -exec sed -i 's/password123/REDACTED/g' {} +" - } - ] - ] - } - }, - "additionalProperties": false - }, - "roles": { - "description": "Repository access roles required to trigger agentic workflows. Defaults to ['admin', 'maintainer', 'write'] for security. Use 'all' to allow any authenticated user (\u26a0\ufe0f security consideration).", - "oneOf": [ - { - "type": "string", - "enum": ["all"], - "description": "Allow any authenticated user to trigger the workflow (\u26a0\ufe0f disables permission checking entirely - use with caution)" - }, - { - "type": "array", - "description": "List of repository permission levels that can trigger the workflow. Permission checks are automatically applied to potentially unsafe triggers.", - "items": { - "type": "string", - "enum": ["admin", "maintainer", "maintain", "write", "triage"], - "description": "Repository permission level: 'admin' (full access), 'maintainer'/'maintain' (repository management), 'write' (push access), 'triage' (issue management)" - }, - "minItems": 1 - } - ] - }, - "bots": { - "type": "array", - "description": "Allow list of bot identifiers that can trigger the workflow even if they don't meet the required role permissions. When the actor is in this list, the bot must be active (installed) on the repository to trigger the workflow.", - "items": { - "type": "string", - "minLength": 1, - "description": "Bot identifier/name (e.g., 'dependabot[bot]', 'renovate[bot]', 'github-actions[bot]')" - } - }, - "strict": { - "type": "boolean", - "default": true, - "$comment": "Strict mode enforces several security constraints that are validated in Go code (pkg/workflow/strict_mode_validation.go) rather than JSON Schema: (1) Write Permissions + Safe Outputs: When strict=true AND permissions contains write values (contents:write, issues:write, pull-requests:write), safe-outputs must be configured. This relationship is too complex for JSON Schema as it requires checking if ANY permission property has a 'write' value. (2) Network Requirements: When strict=true, the 'network' field must be present and cannot contain standalone wildcard '*' (but patterns like '*.example.com' ARE allowed). (3) MCP Container Network: Custom MCP servers with containers require explicit network configuration. (4) Action Pinning: Actions must be pinned to commit SHAs. These are enforced during compilation via validateStrictMode().", - "description": "Enable strict mode validation for enhanced security and compliance. Strict mode enforces: (1) Write Permissions - refuses contents:write, issues:write, pull-requests:write; requires safe-outputs instead, (2) Network Configuration - requires explicit network configuration with no standalone wildcard '*' in allowed domains (patterns like '*.example.com' are allowed), (3) Action Pinning - enforces actions pinned to commit SHAs instead of tags/branches, (4) MCP Network - requires network configuration for custom MCP servers with containers, (5) Deprecated Fields - refuses deprecated frontmatter fields. Can be enabled per-workflow via 'strict: true' in frontmatter, or disabled via 'strict: false'. CLI flag takes precedence over frontmatter (gh aw compile --strict enforces strict mode). Defaults to true. See: https://githubnext.github.io/gh-aw/reference/frontmatter/#strict-mode-strict", - "examples": [true, false] - }, - "safe-inputs": { - "type": "object", - "description": "Safe inputs configuration for defining custom lightweight MCP tools as JavaScript, shell scripts, or Python scripts. Tools are mounted in an MCP server and have access to secrets specified by the user. Only one of 'script' (JavaScript), 'run' (shell), or 'py' (Python) must be specified per tool.", - "patternProperties": { - "^([a-ln-z][a-z0-9_-]*|m[a-np-z][a-z0-9_-]*|mo[a-ce-z][a-z0-9_-]*|mod[a-df-z][a-z0-9_-]*|mode[a-z0-9_-]+)$": { - "type": "object", - "description": "Custom tool definition. The key is the tool name (lowercase alphanumeric with dashes/underscores).", - "required": ["description"], - "properties": { - "description": { - "type": "string", - "description": "Tool description that explains what the tool does. This is required and will be shown to the AI agent." - }, - "inputs": { - "type": "object", - "description": "Optional input parameters for the tool using workflow syntax. Each property defines an input with its type and description.", - "additionalProperties": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["string", "number", "boolean", "array", "object"], - "default": "string", - "description": "The JSON schema type of the input parameter." - }, - "description": { - "type": "string", - "description": "Description of the input parameter." - }, - "required": { - "type": "boolean", - "default": false, - "description": "Whether this input is required." - }, - "default": { - "description": "Default value for the input parameter." - } - }, - "additionalProperties": false - } - }, - "script": { - "type": "string", - "description": "JavaScript implementation (CommonJS format). The script receives input parameters as a JSON object and should return a result. Cannot be used together with 'run', 'py', or 'go'." - }, - "run": { - "type": "string", - "description": "Shell script implementation. The script receives input parameters as environment variables (JSON-encoded for complex types). Cannot be used together with 'script', 'py', or 'go'." - }, - "py": { - "type": "string", - "description": "Python script implementation. The script receives input parameters as environment variables (INPUT_* prefix, uppercased). Cannot be used together with 'script', 'run', or 'go'." - }, - "go": { - "type": "string", - "description": "Go script implementation. The script is executed using 'go run' and receives input parameters as JSON via stdin. Cannot be used together with 'script', 'run', or 'py'." - }, - "env": { - "type": "object", - "description": "Environment variables to pass to the tool, typically for secrets. Use ${{ secrets.NAME }} syntax.", - "additionalProperties": { - "type": "string" - }, - "examples": [ - { - "GH_TOKEN": "${{ secrets.GITHUB_TOKEN }}", - "API_KEY": "${{ secrets.MY_API_KEY }}" - } - ] - }, - "timeout": { - "type": "integer", - "description": "Timeout in seconds for tool execution. Default is 60 seconds. Applies to shell (run) and Python (py) tools.", - "default": 60, - "minimum": 1, - "examples": [30, 60, 120, 300] - } - }, - "additionalProperties": false, - "oneOf": [ - { - "required": ["script"], - "not": { - "anyOf": [ - { - "required": ["run"] - }, - { - "required": ["py"] - }, - { - "required": ["go"] - } - ] - } - }, - { - "required": ["run"], - "not": { - "anyOf": [ - { - "required": ["script"] - }, - { - "required": ["py"] - }, - { - "required": ["go"] - } - ] - } - }, - { - "required": ["py"], - "not": { - "anyOf": [ - { - "required": ["script"] - }, - { - "required": ["run"] - }, - { - "required": ["go"] - } - ] - } - }, - { - "required": ["go"], - "not": { - "anyOf": [ - { - "required": ["script"] - }, - { - "required": ["run"] - }, - { - "required": ["py"] - } - ] - } - } - ] - } - }, - "examples": [ - { - "search-issues": { - "description": "Search GitHub issues using the GitHub API", - "inputs": { - "query": { - "type": "string", - "description": "Search query for issues", - "required": true - }, - "limit": { - "type": "number", - "description": "Maximum number of results", - "default": 10 - } - }, - "script": "const { Octokit } = require('@octokit/rest');\nconst octokit = new Octokit({ auth: process.env.GH_TOKEN });\nconst result = await octokit.search.issuesAndPullRequests({ q: inputs.query, per_page: inputs.limit });\nreturn result.data.items;", - "env": { - "GH_TOKEN": "${{ secrets.GITHUB_TOKEN }}" - } - } - }, - { - "run-linter": { - "description": "Run a custom linter on the codebase", - "inputs": { - "path": { - "type": "string", - "description": "Path to lint", - "default": "." - } - }, - "run": "eslint $INPUT_PATH --format json", - "env": { - "INPUT_PATH": "${{ inputs.path }}" - } - } - } - ], - "additionalProperties": false - }, - "runtimes": { - "type": "object", - "description": "Runtime environment version overrides. Allows customizing runtime versions (e.g., Node.js, Python) or defining new runtimes. Runtimes from imported shared workflows are also merged.", - "patternProperties": { - "^[a-z][a-z0-9-]*$": { - "type": "object", - "description": "Runtime configuration object identified by runtime ID (e.g., 'node', 'python', 'go')", - "properties": { - "version": { - "type": ["string", "number"], - "description": "Runtime version as a string (e.g., '22', '3.12', 'latest') or number (e.g., 22, 3.12). Numeric values are automatically converted to strings at runtime.", - "examples": ["22", "3.12", "latest", 22, 3.12] - }, - "action-repo": { - "type": "string", - "description": "GitHub Actions repository for setting up the runtime (e.g., 'actions/setup-node', 'custom/setup-runtime'). Overrides the default setup action." - }, - "action-version": { - "type": "string", - "description": "Version of the setup action to use (e.g., 'v4', 'v5'). Overrides the default action version." - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "github-token": { - "$ref": "#/$defs/github_token", - "description": "GitHub token expression to use for all steps that require GitHub authentication. Typically a secret reference like ${{ secrets.GITHUB_TOKEN }} or ${{ secrets.CUSTOM_PAT }}. If not specified, defaults to ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}. This value can be overridden by safe-outputs github-token or individual safe-output github-token fields." - } - }, - "additionalProperties": false, - "allOf": [ - { - "if": { - "properties": { - "on": { - "type": "object", - "anyOf": [ - { - "properties": { - "slash_command": { - "not": { - "type": "null" - } - } - }, - "required": ["slash_command"] - }, - { - "properties": { - "command": { - "not": { - "type": "null" - } - } - }, - "required": ["command"] - } - ] - } - } - }, - "then": { - "properties": { - "on": { - "not": { - "anyOf": [ - { - "properties": { - "issue_comment": { - "not": { - "type": "null" - } - } - }, - "required": ["issue_comment"] - }, - { - "properties": { - "pull_request_review_comment": { - "not": { - "type": "null" - } - } - }, - "required": ["pull_request_review_comment"] - }, - { - "properties": { - "label": { - "not": { - "type": "null" - } - } - }, - "required": ["label"] - } - ] - } - } - } - } - } - ], - "$defs": { - "engine_config": { - "examples": [ - "claude", - "copilot", - { - "id": "claude", - "model": "claude-3-5-sonnet-20241022", - "max-turns": 15 - }, - { - "id": "copilot", - "version": "beta" - }, - { - "id": "claude", - "concurrency": { - "group": "gh-aw-claude", - "cancel-in-progress": false - } - } - ], - "oneOf": [ - { - "type": "string", - "enum": ["claude", "codex", "copilot", "custom"], - "description": "Simple engine name: 'claude' (default, Claude Code), 'copilot' (GitHub Copilot CLI), 'codex' (OpenAI Codex CLI), or 'custom' (user-defined steps)" - }, - { - "type": "object", - "description": "Extended engine configuration object with advanced options for model selection, turn limiting, environment variables, and custom steps", - "properties": { - "id": { - "type": "string", - "enum": ["claude", "codex", "custom", "copilot"], - "description": "AI engine identifier: 'claude' (Claude Code), 'codex' (OpenAI Codex CLI), 'copilot' (GitHub Copilot CLI), or 'custom' (user-defined GitHub Actions steps)" - }, - "version": { - "type": ["string", "number"], - "description": "Optional version of the AI engine action (e.g., 'beta', 'stable', 20). Has sensible defaults and can typically be omitted. Numeric values are automatically converted to strings at runtime.", - "examples": ["beta", "stable", 20, 3.11] - }, - "model": { - "type": "string", - "description": "Optional specific LLM model to use (e.g., 'claude-3-5-sonnet-20241022', 'gpt-4'). Has sensible defaults and can typically be omitted." - }, - "max-turns": { - "oneOf": [ - { - "type": "integer", - "description": "Maximum number of chat iterations per run as an integer value" - }, - { - "type": "string", - "description": "Maximum number of chat iterations per run as a string value" - } - ], - "description": "Maximum number of chat iterations per run. Helps prevent runaway loops and control costs. Has sensible defaults and can typically be omitted. Note: Only supported by the claude engine." - }, - "concurrency": { - "oneOf": [ - { - "type": "string", - "description": "Simple concurrency group name. Gets converted to GitHub Actions concurrency format with the specified group." - }, - { - "type": "object", - "description": "GitHub Actions concurrency configuration for the agent job. Controls how many agentic workflow runs can run concurrently.", - "properties": { - "group": { - "type": "string", - "description": "Concurrency group identifier. Use GitHub Actions expressions like ${{ github.workflow }} or ${{ github.ref }}. Defaults to 'gh-aw-{engine-id}' if not specified." - }, - "cancel-in-progress": { - "type": "boolean", - "description": "Whether to cancel in-progress runs of the same concurrency group. Defaults to false for agentic workflow runs." - } - }, - "required": ["group"], - "additionalProperties": false - } - ], - "description": "Agent job concurrency configuration. Defaults to single job per engine across all workflows (group: 'gh-aw-{engine-id}'). Supports full GitHub Actions concurrency syntax." - }, - "user-agent": { - "type": "string", - "description": "Custom user agent string for GitHub MCP server configuration (codex engine only)" - }, - "env": { - "type": "object", - "description": "Custom environment variables to pass to the AI engine, including secret overrides (e.g., OPENAI_API_KEY: ${{ secrets.CUSTOM_KEY }})", - "additionalProperties": { - "type": "string" - } - }, - "steps": { - "type": "array", - "description": "Custom GitHub Actions steps for 'custom' engine. Define your own deterministic workflow steps instead of using AI processing.", - "items": { - "type": "object", - "additionalProperties": true - } - }, - "error_patterns": { - "type": "array", - "description": "Custom error patterns for validating agent logs", - "items": { - "type": "object", - "description": "Error pattern definition", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this error pattern" - }, - "pattern": { - "type": "string", - "description": "Ecma script regular expression pattern to match log lines" - }, - "level_group": { - "type": "integer", - "minimum": 0, - "description": "Capture group index (1-based) that contains the error level. Use 0 to infer from pattern content." - }, - "message_group": { - "type": "integer", - "minimum": 0, - "description": "Capture group index (1-based) that contains the error message. Use 0 to use the entire match." - }, - "description": { - "type": "string", - "description": "Human-readable description of what this pattern matches" - } - }, - "required": ["pattern"], - "additionalProperties": false - } - }, - "config": { - "type": "string", - "description": "Additional TOML configuration text that will be appended to the generated config.toml in the action (codex engine only)" - }, - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional array of command-line arguments to pass to the AI engine CLI. These arguments are injected after all other args but before the prompt." - } - }, - "required": ["id"], - "additionalProperties": false - } - ] - }, - "stdio_mcp_tool": { - "type": "object", - "description": "Stdio MCP tool configuration", - "properties": { - "type": { - "type": "string", - "enum": ["stdio", "local"], - "description": "MCP connection type for stdio (local is an alias for stdio)" - }, - "registry": { - "type": "string", - "description": "URI to the installation location when MCP is installed from a registry" - }, - "command": { - "type": "string", - "minLength": 1, - "$comment": "Mutually exclusive with 'container' - only one execution mode can be specified. Validated by 'not.allOf' constraint below.", - "description": "Command for stdio MCP connections" - }, - "container": { - "type": "string", - "pattern": "^[a-zA-Z0-9][a-zA-Z0-9/:_.-]*$", - "$comment": "Mutually exclusive with 'command' - only one execution mode can be specified. Validated by 'not.allOf' constraint below.", - "description": "Container image for stdio MCP connections" - }, - "version": { - "type": ["string", "number"], - "description": "Optional version/tag for the container image (e.g., 'latest', 'v1.0.0', 20, 3.11). Numeric values are automatically converted to strings at runtime.", - "examples": ["latest", "v1.0.0", 20, 3.11] - }, - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments for command or container execution" - }, - "entrypointArgs": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to add after the container image (container entrypoint arguments)" - }, - "env": { - "type": "object", - "patternProperties": { - "^[A-Z_][A-Z0-9_]*$": { - "type": "string" - } - }, - "additionalProperties": false, - "description": "Environment variables for MCP server" - }, - "network": { - "type": "object", - "$comment": "Requires 'container' to be specified - network configuration only applies to container-based MCP servers. Validated by 'if/then' constraint in 'allOf' below.", - "properties": { - "allowed": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*$", - "description": "Allowed domain name" - }, - "minItems": 1, - "uniqueItems": true, - "description": "List of allowed domain names for network access" - }, - "proxy-args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Custom proxy arguments for container-based MCP servers" - } - }, - "additionalProperties": false, - "description": "Network configuration for container-based MCP servers" - }, - "allowed": { - "type": "array", - "description": "List of allowed tool functions", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false, - "$comment": "Validation constraints: (1) Mutual exclusion: 'command' and 'container' cannot both be specified. (2) Requirement: Either 'command' or 'container' must be provided (via 'anyOf'). (3) Dependency: 'network' requires 'container' (validated in 'allOf'). (4) Type constraint: When 'type' is 'stdio' or 'local', either 'command' or 'container' is required.", - "anyOf": [ - { - "required": ["type"] - }, - { - "required": ["command"] - }, - { - "required": ["container"] - } - ], - "not": { - "allOf": [ - { - "required": ["command"] - }, - { - "required": ["container"] - } - ] - }, - "allOf": [ - { - "if": { - "required": ["network"] - }, - "then": { - "required": ["container"] - } - }, - { - "if": { - "properties": { - "type": { - "enum": ["stdio", "local"] - } - } - }, - "then": { - "anyOf": [ - { - "required": ["command"] - }, - { - "required": ["container"] - } - ] - } - } - ] - }, - "http_mcp_tool": { - "type": "object", - "description": "HTTP MCP tool configuration", - "properties": { - "type": { - "type": "string", - "enum": ["http"], - "description": "MCP connection type for HTTP" - }, - "registry": { - "type": "string", - "description": "URI to the installation location when MCP is installed from a registry" - }, - "url": { - "type": "string", - "minLength": 1, - "description": "URL for HTTP MCP connections" - }, - "headers": { - "type": "object", - "patternProperties": { - "^[A-Za-z0-9_-]+$": { - "type": "string" - } - }, - "additionalProperties": false, - "description": "HTTP headers for HTTP MCP connections" - }, - "allowed": { - "type": "array", - "description": "List of allowed tool functions", - "items": { - "type": "string" - } - } - }, - "required": ["url"], - "additionalProperties": false - }, - "github_token": { - "type": "string", - "pattern": "^\\$\\{\\{\\s*secrets\\.[A-Za-z_][A-Za-z0-9_]*(\\s*\\|\\|\\s*secrets\\.[A-Za-z_][A-Za-z0-9_]*)*\\s*\\}\\}$", - "description": "GitHub token expression using secrets. Pattern details: `[A-Za-z_][A-Za-z0-9_]*` matches a valid secret name (starts with a letter or underscore, followed by letters, digits, or underscores). The full pattern matches expressions like `${{ secrets.NAME }}` or `${{ secrets.NAME1 || secrets.NAME2 }}`.", - "examples": ["${{ secrets.GITHUB_TOKEN }}", "${{ secrets.CUSTOM_PAT }}", "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}"] - }, - "githubActionsStep": { - "type": "object", - "description": "GitHub Actions workflow step", - "properties": { - "name": { - "type": "string", - "description": "A name for your step to display on GitHub" - }, - "id": { - "type": "string", - "description": "A unique identifier for the step" - }, - "if": { - "type": "string", - "description": "Conditional expression to determine if step should run" - }, - "uses": { - "type": "string", - "description": "Selects an action to run as part of a step in your job" - }, - "run": { - "type": "string", - "description": "Runs command-line programs using the operating system's shell" - }, - "with": { - "type": "object", - "description": "Input parameters defined by the action", - "additionalProperties": true - }, - "env": { - "type": "object", - "description": "Environment variables for the step", - "patternProperties": { - "^[A-Za-z_][A-Za-z0-9_]*$": { - "type": "string" - } - }, - "additionalProperties": false - }, - "continue-on-error": { - "type": "boolean", - "description": "Prevents a job from failing when a step fails" - }, - "timeout-minutes": { - "type": "number", - "description": "The maximum number of minutes to run the step before killing the process" - }, - "working-directory": { - "type": "string", - "description": "Working directory for the step" - }, - "shell": { - "type": "string", - "description": "Shell to use for the run command" - } - }, - "additionalProperties": false, - "anyOf": [ - { - "required": ["uses"] - }, - { - "required": ["run"] - } - ] - } - } -} diff --git a/.github/aw/update-agentic-workflow.md b/.github/aw/update-agentic-workflow.md new file mode 100644 index 000000000..beeef734a --- /dev/null +++ b/.github/aw/update-agentic-workflow.md @@ -0,0 +1,353 @@ +--- +description: Update existing agentic workflows using GitHub Agentic Workflows (gh-aw) extension with intelligent guidance on modifications, improvements, and refactoring. +infer: false +--- + +This file will configure the agent into a mode to update existing agentic workflows. Read the ENTIRE content of this file carefully before proceeding. Follow the instructions precisely. + +# GitHub Agentic Workflow Updater + +You are an assistant specialized in **updating existing GitHub Agentic Workflows (gh-aw)**. +Your job is to help the user modify, improve, and refactor **existing agentic workflows** in this repository, using the already-installed gh-aw CLI extension. + +## Scope + +This agent is for **updating EXISTING workflows only**. For creating new workflows from scratch, use the `create` prompt instead. + +## Writing Style + +You format your questions and responses similarly to the GitHub Copilot CLI chat style. You love to use emojis to make the conversation more engaging. + +## Capabilities & Responsibilities + +**Read the gh-aw instructions** + +- Always consult the **instructions file** for schema and features: + - Local copy: @.github/aw/github-agentic-workflows.md + - Canonical upstream: https://raw.githubusercontent.com/githubnext/gh-aw/main/.github/aw/github-agentic-workflows.md +- Key commands: + - `gh aw compile` โ†’ compile all workflows + - `gh aw compile ` โ†’ compile one workflow + - `gh aw compile --strict` โ†’ compile with strict mode validation (recommended for production) + - `gh aw compile --purge` โ†’ remove stale lock files + +## Starting the Conversation + +1. **Identify the Workflow** + Start by asking the user which workflow they want to update: + - Which workflow would you like to update? (provide the workflow name or path) + +2. **Understand the Goal** + Once you know which workflow to update, ask: + - What changes would you like to make to this workflow? + +Wait for the user to respond before proceeding. + +## Update Scenarios + +### Common Update Types + +1. **Adding New Features** + - Adding new tools or MCP servers + - Adding new safe output types + - Adding new triggers or events + - Adding custom steps or post-steps + +2. **Modifying Configuration** + - Changing permissions + - Updating network access policies + - Modifying timeout settings + - Adjusting tool configurations + +3. **Improving Prompts** + - Refining agent instructions + - Adding clarifications or guidelines + - Improving prompt engineering + - Adding security notices + +4. **Fixing Issues** + - Resolving compilation errors + - Fixing deprecated fields + - Addressing security warnings + - Correcting misconfigurations + +5. **Performance Optimization** + - Adding caching strategies + - Optimizing tool usage + - Reducing redundant operations + - Improving trigger conditions + +## Update Best Practices + +### ๐ŸŽฏ Make Small, Incremental Changes + +**CRITICAL**: When updating existing workflows, make **small, incremental changes** only. Do NOT rewrite the entire frontmatter unless absolutely necessary. + +- โœ… **DO**: Only add/modify the specific fields needed to address the user's request +- โœ… **DO**: Preserve existing configuration patterns and style +- โœ… **DO**: Keep changes minimal and focused on the goal +- โŒ **DON'T**: Rewrite entire frontmatter sections that don't need changes +- โŒ **DON'T**: Add unnecessary fields with default values +- โŒ **DON'T**: Change existing patterns unless specifically requested + +**Example - Adding a Tool**: +```yaml +# โŒ BAD - Rewrites entire frontmatter +--- +description: Updated workflow +on: + issues: + types: [opened] +engine: copilot +timeout-minutes: 10 +permissions: + contents: read + issues: read +tools: + github: + toolsets: [default] + web-fetch: # <-- The only actual change needed +--- + +# โœ… GOOD - Only adds what's needed +# Original frontmatter stays intact, just append: +tools: + web-fetch: +``` + +### Keep Frontmatter Minimal + +Only include fields that differ from sensible defaults: +- โš™๏ธ **DO NOT include `engine: copilot`** - Copilot is the default engine +- โฑ๏ธ **DO NOT include `timeout-minutes:`** unless user needs a specific timeout +- ๐Ÿ“‹ **DO NOT include other fields with good defaults** unless the user specifically requests them + +### Tools & MCP Servers + +When adding or modifying tools: + +**GitHub tool with toolsets**: +```yaml +tools: + github: + toolsets: [default] +``` + +โš ๏ธ **IMPORTANT**: +- **Always use `toolsets:` for GitHub tools** - Use `toolsets: [default]` instead of manually listing individual tools +- **Never recommend GitHub mutation tools** like `create_issue`, `add_issue_comment`, `update_issue`, etc. +- **Always use `safe-outputs` instead** for any GitHub write operations +- **Do NOT recommend `mode: remote`** for GitHub tools - it requires additional configuration + +**General tools (Serena language server)**: +```yaml +tools: + serena: ["go"] # Update with the repository's programming language +``` + +โš ๏ธ **IMPORTANT - Default Tools**: +- **`edit` and `bash` are enabled by default** when sandboxing is active (no need to add explicitly) +- `bash` defaults to `*` (all commands) when sandboxing is active +- Only specify `bash:` with specific patterns if you need to restrict commands beyond the secure defaults + +**MCP servers (top-level block)**: +```yaml +mcp-servers: + my-custom-server: + command: "node" + args: ["path/to/mcp-server.js"] + allowed: + - custom_function_1 + - custom_function_2 +``` + +### Custom Safe Output Jobs + +โš ๏ธ **IMPORTANT**: When adding a **new safe output** (e.g., sending email via custom service, posting to Slack/Discord, calling custom APIs), guide the user to create a **custom safe output job** under `safe-outputs.jobs:` instead of using `post-steps:`. + +**When to use custom safe output jobs:** +- Sending notifications to external services (email, Slack, Discord, Teams, PagerDuty) +- Creating/updating records in third-party systems (Notion, Jira, databases) +- Triggering deployments or webhooks +- Any write operation to external services based on AI agent output + +**DO NOT use `post-steps:` for these scenarios.** `post-steps:` are for cleanup/logging tasks only, NOT for custom write operations triggered by the agent. + +### Security Best Practices + +When updating workflows, maintain security: +- Default to `permissions: read-all` and expand only if necessary +- Prefer `safe-outputs` over granting write permissions +- Constrain `network:` to the minimum required ecosystems/domains +- Use sanitized expressions (`${{ needs.activation.outputs.text }}`) + +## Update Workflow Process + +### Step 1: Read the Current Workflow + +Use the `view` tool to read the current workflow file: +```bash +# View the workflow markdown file +view /path/to/.github/workflows/.md + +# View the agentics prompt file if it exists +view /path/to/.github/agentics/.md +``` + +Understand the current configuration before making changes. + +### Step 2: Make Targeted Changes + +Based on the user's request, make **minimal, targeted changes**: + +**For frontmatter changes**: +- Use `edit` tool to modify only the specific YAML fields that need updating +- Preserve existing indentation and formatting +- Don't rewrite sections that don't need changes + +**For prompt changes**: +- If an agentics prompt file exists (`.github/agentics/.md`), edit that file directly +- If no agentics file exists, edit the markdown body in the workflow file +- Make surgical changes to the prompt text + +**Example - Adding a Safe Output**: +```yaml +# Find the safe-outputs section and add: +safe-outputs: + create-issue: # existing + labels: [automated] + add-comment: # NEW - just add this line and its config + max: 1 +``` + +### Step 3: Compile and Validate + +**CRITICAL**: After making changes, always compile the workflow: + +```bash +gh aw compile +``` + +If compilation fails: +1. **Fix ALL syntax errors** - Never leave a workflow in a broken state +2. Review error messages carefully +3. Re-run `gh aw compile ` until it succeeds +4. If errors persist, consult `.github/aw/github-agentic-workflows.md` + +### Step 4: Verify Changes + +After successful compilation: +1. Review the `.lock.yml` file to ensure changes are reflected +2. Confirm the changes match the user's request +3. Explain what was changed and why + +## Common Update Patterns + +### Adding a New Tool + +```yaml +# Locate the tools: section and add the new tool +tools: + github: + toolsets: [default] # existing + web-fetch: # NEW - add just this +``` + +### Adding Network Access + +```yaml +# Add or update the network: section +network: + allowed: + - defaults + - python # NEW ecosystem +``` + +### Adding a Safe Output + +```yaml +# Locate safe-outputs: and add the new type +safe-outputs: + add-comment: # existing + create-issue: # NEW + labels: [ai-generated] +``` + +### Updating Permissions + +```yaml +# Locate permissions: and add specific permission +permissions: + contents: read # existing + discussions: read # NEW +``` + +### Modifying Triggers + +```yaml +# Update the on: section +on: + issues: + types: [opened] # existing + pull_request: # NEW + types: [opened, edited] +``` + +### Improving the Prompt + +If an agentics prompt file exists: +```bash +# Edit the agentics prompt file directly +edit .github/agentics/.md + +# Add clarifications, guidelines, or instructions +# WITHOUT recompiling the workflow! +``` + +If no agentics file exists, edit the markdown body of the workflow file. + +## Guidelines + +- This agent is for **updating EXISTING workflows** only +- **Make small, incremental changes** - preserve existing configuration +- **Always compile workflows** after modifying them with `gh aw compile ` +- **Always fix ALL syntax errors** - never leave workflows in a broken state +- **Use strict mode by default**: Use `gh aw compile --strict` to validate syntax +- **Be conservative about relaxing strict mode**: Prefer fixing workflows to meet security requirements + - If the user asks to relax strict mode, **ask for explicit confirmation** + - **Propose secure alternatives** before agreeing to disable strict mode + - Only proceed with relaxed security if the user explicitly confirms after understanding the risks +- Always follow security best practices (least privilege, safe outputs, constrained network) +- Skip verbose summaries at the end, keep it concise + +## Prompt Editing Without Recompilation + +**Key Feature**: If the workflow uses runtime imports (e.g., `@./agentics/.md`), you can edit the imported prompt file WITHOUT recompiling the workflow. + +**When to use this**: +- Improving agent instructions +- Adding clarifications or guidelines +- Refining prompt engineering +- Adding security notices + +**How to do it**: +1. Check if the workflow has a runtime import: `@./agentics/.md` +2. If yes, edit that file directly - no compilation needed! +3. Changes take effect on the next workflow run + +**Example**: +```bash +# Edit the prompt without recompiling +edit .github/agentics/issue-classifier.md + +# Add your improvements to the agent instructions +# The changes will be active on the next run - no compile needed! +``` + +## Final Words + +After completing updates: +- Inform the user which files were changed +- Explain what was modified and why +- Remind them to commit and push the changes +- If prompt-only changes were made to an agentics file, note that recompilation wasn't needed diff --git a/.github/aw/upgrade-agentic-workflows.md b/.github/aw/upgrade-agentic-workflows.md new file mode 100644 index 000000000..83cee26eb --- /dev/null +++ b/.github/aw/upgrade-agentic-workflows.md @@ -0,0 +1,285 @@ +--- +description: Upgrade agentic workflows to the latest version of gh-aw with automated compilation and error fixing +infer: false +--- + +You are specialized in **upgrading GitHub Agentic Workflows (gh-aw)** to the latest version. +Your job is to upgrade workflows in a repository to work with the latest gh-aw version, handling breaking changes and compilation errors. + +Read the ENTIRE content of this file carefully before proceeding. Follow the instructions precisely. + +## Capabilities & Responsibilities + +**Prerequisites** + +- The `gh aw` CLI may be available in this environment. +- Always consult the **instructions file** for schema and features: + - Local copy: @.github/aw/github-agentic-workflows.md + - Canonical upstream: https://raw.githubusercontent.com/githubnext/gh-aw/main/.github/aw/github-agentic-workflows.md + +**Key Commands Available** + +- `fix` โ†’ apply automatic codemods to fix deprecated fields +- `compile` โ†’ compile all workflows +- `compile ` โ†’ compile a specific workflow + +:::note[Command Execution] +When running in GitHub Copilot Cloud, you don't have direct access to `gh aw` CLI commands. Instead, use the **agentic-workflows** MCP tool: +- `fix` tool โ†’ apply automatic codemods to fix deprecated fields +- `compile` tool โ†’ compile workflows + +When running in other environments with `gh aw` CLI access, prefix commands with `gh aw` (e.g., `gh aw compile`). + +These tools provide the same functionality through the MCP server without requiring GitHub CLI authentication. +::: + +## Instructions + +### 1. Fetch Latest gh-aw Changes + +Before upgrading, always review what's new: + +1. **Fetch Latest Release Information** + - Use GitHub tools to fetch the CHANGELOG.md from the `githubnext/gh-aw` repository + - Review and understand: + - Breaking changes + - New features + - Deprecations + - Migration guides or upgrade instructions + - Summarize key changes with clear indicators: + - ๐Ÿšจ Breaking changes (requires action) + - โœจ New features (optional enhancements) + - โš ๏ธ Deprecations (plan to update) + - ๐Ÿ“– Migration guides (follow instructions) + +### 2. Apply Automatic Fixes with Codemods + +Before attempting to compile, apply automatic codemods: + +1. **Run Automatic Fixes** + + Use the `fix` tool with the `--write` flag to apply automatic fixes. + + This will automatically update workflow files with changes like: + - Replacing 'timeout_minutes' with 'timeout-minutes' + - Replacing 'network.firewall' with 'sandbox.agent: false' + - Removing deprecated 'safe-inputs.mode' field + +2. **Review the Changes** + - Note which workflows were updated by the codemods + - These automatic fixes handle common deprecations + +### 3. Attempt Recompilation + +Try to compile all workflows: + +1. **Run Compilation** + + Use the `compile` tool to compile all workflows. + +2. **Analyze Results** + - Note any compilation errors or warnings + - Group errors by type (schema validation, breaking changes, missing features) + - Identify patterns in the errors + +### 4. Fix Compilation Errors + +If compilation fails, work through errors systematically: + +1. **Analyze Each Error** + - Read the error message carefully + - Reference the changelog for breaking changes + - Check the gh-aw instructions for correct syntax + +2. **Common Error Patterns** + + **Schema Changes:** + - Old field names that have been renamed + - New required fields + - Changed field types or formats + + **Breaking Changes:** + - Deprecated features that have been removed + - Changed default behaviors + - Updated tool configurations + + **Example Fixes:** + + ```yaml + # Old format (deprecated) + mcp-servers: + github: + mode: remote + + # New format + tools: + github: + mode: remote + toolsets: [default] + ``` + +3. **Apply Fixes Incrementally** + - Fix one workflow or one error type at a time + - After each fix, use the `compile` tool with `` to verify + - Verify the fix works before moving to the next error + +4. **Document Changes** + - Keep track of all changes made + - Note which breaking changes affected which workflows + - Document any manual migration steps taken + +### 5. Verify All Workflows + +After fixing all errors: + +1. **Final Compilation Check** + + Use the `compile` tool to ensure all workflows compile successfully. + +2. **Review Generated Lock Files** + - Ensure all workflows have corresponding `.lock.yml` files + - Check that lock files are valid GitHub Actions YAML + +3. **Refresh Agent and Instruction Files** + + After successfully upgrading workflows, refresh the agent files and instructions to ensure you have the latest versions: + - Run `gh aw init` to update all agent files (`.github/agents/*.md`) and instruction files (`.github/aw/github-agentic-workflows.md`) + - This ensures that agents and instructions are aligned with the new gh-aw version + - The command will preserve your existing configuration while updating to the latest templates + +## Creating Outputs + +After completing the upgrade: + +### If All Workflows Compile Successfully + +Create a **pull request** with: + +**Title:** `Upgrade workflows to latest gh-aw version` + +**Description:** +```markdown +## Summary + +Upgraded all agentic workflows to gh-aw version [VERSION]. + +## Changes + +### gh-aw Version Update +- Previous version: [OLD_VERSION] +- New version: [NEW_VERSION] + +### Key Changes from Changelog +- [List relevant changes from the changelog] +- [Highlight any breaking changes that affected this repository] + +### Workflows Updated +- [List all workflow files that were modified] + +### Automatic Fixes Applied (via codemods) +- [List changes made by the `fix` tool with `--write` flag] +- [Reference which deprecated fields were updated] + +### Manual Fixes Applied +- [Describe any manual changes made to fix compilation errors] +- [Reference specific breaking changes that required fixes] + +### Testing +- โœ… All workflows compile successfully +- โœ… All `.lock.yml` files generated +- โœ… No compilation errors or warnings + +### Post-Upgrade Steps +- โœ… Refreshed agent files and instructions with `gh aw init` + +## Files Changed +- Updated `.md` workflow files: [LIST] +- Generated `.lock.yml` files: [LIST] +- Updated agent files: [LIST] (if `gh aw init` was run) +``` + +### If Compilation Errors Cannot Be Fixed + +Create an **issue** with: + +**Title:** `Failed to upgrade workflows to latest gh-aw version` + +**Description:** +```markdown +## Summary + +Attempted to upgrade workflows to gh-aw version [VERSION] but encountered compilation errors that could not be automatically resolved. + +## Version Information +- Current gh-aw version: [VERSION] +- Target version: [NEW_VERSION] + +## Compilation Errors + +### Error 1: [Error Type] +``` +[Full error message] +``` + +**Affected Workflows:** +- [List workflows with this error] + +**Attempted Fixes:** +- [Describe what was tried] +- [Explain why it didn't work] + +**Relevant Changelog Reference:** +- [Link to changelog section] +- [Excerpt of relevant documentation] + +### Error 2: [Error Type] +[Repeat for each distinct error] + +## Investigation Steps Taken +1. [Step 1] +2. [Step 2] +3. [Step 3] + +## Recommendations +- [Suggest next steps] +- [Identify if this is a bug in gh-aw or requires repository changes] +- [Link to relevant documentation or issues] + +## Additional Context +- Changelog review: [Link to CHANGELOG.md] +- Migration guide: [Link if available] +``` + +## Best Practices + +1. **Always Review Changelog First** + - Understanding breaking changes upfront saves time + - Look for migration guides or specific upgrade instructions + - Pay attention to deprecation warnings + +2. **Fix Errors Incrementally** + - Don't try to fix everything at once + - Validate each fix before moving to the next + - Group similar errors and fix them together + +3. **Test Thoroughly** + - Compile workflows to verify fixes + - Check that all lock files are generated + - Review the generated YAML for correctness + +4. **Document Everything** + - Keep track of all changes made + - Explain why changes were necessary + - Reference specific changelog entries + +5. **Clear Communication** + - Use emojis to make output engaging + - Summarize complex changes clearly + - Provide actionable next steps + +## Important Notes + +- When running in GitHub Copilot Cloud, use the **agentic-workflows** MCP tool for all commands +- When running in environments with `gh aw` CLI access, prefix commands with `gh aw` +- Breaking changes are inevitable - expect to make manual fixes +- If stuck, create an issue with detailed information for the maintainers diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml deleted file mode 100644 index 3cd59ac0f..000000000 --- a/.github/workflows/agentics-maintenance.yml +++ /dev/null @@ -1,135 +0,0 @@ -# -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by pkg/workflow/maintenance_workflow.go (v0.36.0). DO NOT EDIT. -# -# To regenerate this workflow, run: -# gh aw compile -# For more information: https://github.com/githubnext/gh-aw/blob/main/.github/aw/github-agentic-workflows.md -# -# Alternative regeneration methods: -# make recompile -# -# Or use the gh-aw CLI directly: -# ./gh-aw compile --validate --verbose -# -# The workflow is generated when any workflow uses the 'expires' field -# in create-discussions or create-issues safe-outputs configuration. -# Schedule frequency is automatically determined by the shortest expiration time. -# -name: Agentics Maintenance - -on: - schedule: - - cron: "37 0 * * *" # Daily (based on minimum expires: 7 days) - workflow_dispatch: - -permissions: {} - -jobs: - close-expired-discussions: - runs-on: ubuntu-latest - permissions: - discussions: write - steps: - - name: Setup Scripts - uses: githubnext/gh-aw/actions/setup@v0.37.0 - with: - destination: /opt/gh-aw/actions - - - name: Close expired discussions - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/close_expired_discussions.cjs'); - await main(); - - close-expired-issues: - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Setup Scripts - uses: githubnext/gh-aw/actions/setup@v0.37.0 - with: - destination: /opt/gh-aw/actions - - - name: Close expired issues - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/close_expired_issues.cjs'); - await main(); - - compile-workflows: - runs-on: ubuntu-latest - permissions: - contents: read - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.2.2 - with: - sparse-checkout: | - .github - persist-credentials: false - - - - name: Install gh-aw - run: | - curl -fsSL https://raw.githubusercontent.com/githubnext/gh-aw/329844a/install-gh-aw.sh | bash - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Compile workflows - run: | - gh-aw compile --validate --verbose - echo "โœ“ All workflows compiled successfully" - - - name: Setup Scripts - uses: githubnext/gh-aw/actions/setup@v0.37.0 - with: - destination: /tmp/gh-aw/actions - - - name: Check for out-of-sync workflows and create issue if needed - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const { setupGlobals } = require('/tmp/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/tmp/gh-aw/actions/check_workflow_recompile_needed.cjs'); - await main(); - - zizmor-scan: - runs-on: ubuntu-latest - needs: compile-workflows - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.2.2 - - - name: Install gh-aw - run: | - curl -fsSL https://raw.githubusercontent.com/githubnext/gh-aw/329844a/install-gh-aw.sh | bash - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Run zizmor security scanner - run: | - gh-aw compile --zizmor --verbose - echo "โœ“ Zizmor security scan completed" diff --git a/.github/workflows/api-coherence-checker.lock.yml b/.github/workflows/api-coherence-checker.lock.yml index 55dd0ff6a..a0775546d 100644 --- a/.github/workflows/api-coherence-checker.lock.yml +++ b/.github/workflows/api-coherence-checker.lock.yml @@ -13,7 +13,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.36.0). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.37.0). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -28,7 +28,7 @@ name: "API Coherence Checker" # Friendly format: daily (scattered) workflow_dispatch: -permissions: read-all +permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}" @@ -66,6 +66,10 @@ jobs: 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: /tmp/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json @@ -75,6 +79,7 @@ jobs: model: ${{ steps.generate_aw_info.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts uses: githubnext/gh-aw/actions/setup@v0.37.0 @@ -83,37 +88,13 @@ jobs: - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Checkout repository - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - - name: Setup .NET - uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 - with: - dotnet-version: '8.0' - - name: Setup Java - uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4.8.0 - with: - java-version: '21' - distribution: temurin - - name: Setup Node.js - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - with: - node-version: '24' - package-manager-cache: false - - name: Setup Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 - with: - python-version: '3.12' - - name: Setup uv - uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - - name: Install Python language service - run: pip install --quiet python-lsp-server - - name: Install TypeScript language service - run: npm install -g --silent typescript-language-server typescript # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory run: bash /opt/gh-aw/actions/create_cache_memory_dir.sh - - name: Restore cache memory file share data - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + - name: Restore cache-memory file share data + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: memory-${{ github.workflow }}-${{ github.run_id }} path: /tmp/gh-aw/cache-memory @@ -145,7 +126,8 @@ jobs: const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -154,7 +136,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -162,23 +145,19 @@ jobs: # Verify installation copilot --version - name: Install awf binary - run: | - echo "Installing awf via installer script (requested version: v0.8.2)" - curl -sSL https://raw.githubusercontent.com/githubnext/gh-aw-firewall/main/install.sh | sudo AWF_VERSION=v0.8.2 bash - which awf - awf --version + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.10.0 - name: Determine automatic lockdown mode for GitHub MCP server id: determine-automatic-lockdown env: TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} if: env.TOKEN_CHECK != '' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - - name: Downloading container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.27.0 + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.29.0 ghcr.io/githubnext/gh-aw-mcpg:v0.0.71 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs @@ -216,7 +195,7 @@ jobs: "name": "create_discussion" }, { - "description": "Report that a tool or capability needed to complete the task is not available. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "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": { @@ -225,16 +204,15 @@ jobs: "type": "string" }, "reason": { - "description": "Explanation of why this tool is needed to complete the task (max 256 characters).", + "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": "Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", "type": "string" } }, "required": [ - "tool", "reason" ], "type": "object" @@ -257,6 +235,33 @@ jobs: "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" } ] EOF @@ -323,44 +328,48 @@ jobs: } } EOF - - name: Setup MCPs + - name: Start MCP gateway + id: start-mcp-gateway env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | + set -eo pipefail mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY="" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + export MCP_GATEWAY_API_KEY + + # Register API key as secret to mask it from logs + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + 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 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 -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/githubnext/gh-aw-mcpg:v0.0.71' + mkdir -p /home/runner/.copilot - cat > /home/runner/.copilot/mcp-config.json << EOF + cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh { "mcpServers": { "github": { - "type": "local", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-e", - "GITHUB_PERSONAL_ACCESS_TOKEN", - "-e", - "GITHUB_READ_ONLY=1", - "-e", - "GITHUB_LOCKDOWN_MODE=$GITHUB_MCP_LOCKDOWN", - "-e", - "GITHUB_TOOLSETS=context,repos,issues,pull_requests", - "ghcr.io/github/github-mcp-server:v0.27.0" - ], - "tools": ["*"], + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.29.0", "env": { - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}" + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" } }, "safeoutputs": { - "type": "local", - "command": "node", - "args": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], - "tools": ["*"], + "type": "stdio", + "container": "node:lts-alpine", + "entrypoint": "node", + "entrypointArgs": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], + "mounts": ["/opt/gh-aw:/opt/gh-aw:ro", "/tmp/gh-aw:/tmp/gh-aw:rw"], "env": { "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}", "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", @@ -377,21 +386,21 @@ jobs: } }, "serena": { - "type": "local", - "command": "uvx", - "args": ["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "tools": ["*"] + "type": "stdio", + "container": "ghcr.io/githubnext/serena-mcp-server:latest", + "args": ["--network", "host"], + "entrypoint": "serena", + "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], + "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}" } } - EOF - echo "-------START MCP CONFIG-----------" - cat /home/runner/.copilot/mcp-config.json - echo "-------END MCP CONFIG-----------" - echo "-------/home/runner/.copilot-----------" - find /home/runner/.copilot - echo "HOME: $HOME" - echo "GITHUB_COPILOT_CLI_MODE: $GITHUB_COPILOT_CLI_MODE" + MCPCONFIG_EOF - name: Generate agentic run info id: generate_aw_info uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -404,8 +413,8 @@ jobs: engine_name: "GitHub Copilot CLI", model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", version: "", - agent_version: "0.0.375", - cli_version: "v0.36.0", + agent_version: "0.0.387", + cli_version: "v0.37.0", workflow_name: "API Coherence Checker", experimental: false, supports_tools_allowlist: true, @@ -422,7 +431,8 @@ jobs: network_mode: "defaults", allowed_domains: [], firewall_enabled: true, - awf_version: "v0.8.2", + awf_version: "v0.10.0", + awmg_version: "v0.0.71", steps: { firewall: "squid" }, @@ -443,15 +453,93 @@ jobs: script: | const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); await generateWorkflowOverview(core); - - name: Create prompt + - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" + + PROMPT_EOF + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + --- + + ## Cache Folder Available + + You have access to a persistent cache folder at `/tmp/gh-aw/cache-memory/` where you can read and write files to create memories and store information. + + - **Read/Write Access**: You can freely read from and write to any files in this folder + - **Persistence**: Files in this folder persist across workflow runs via GitHub Actions cache + - **Last Write Wins**: If multiple processes write to the same file, the last write will be preserved + - **File Share**: Use this as a simple file share - organize files as you see fit + + Examples of what you can store: + - `/tmp/gh-aw/cache-memory/notes.txt` - general notes and observations + - `/tmp/gh-aw/cache-memory/preferences.json` - user preferences and settings + - `/tmp/gh-aw/cache-memory/history.log` - activity history and logs + - `/tmp/gh-aw/cache-memory/state/` - organized state files in subdirectories + + Feel free to create, read, update, and organize files in this folder as needed for your tasks. + + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + **Available tools**: create_discussion, missing_tool, noop + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + + + 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}} + + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" # API Coherence Checker ## Job Description @@ -633,127 +721,14 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} - with: - script: | - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, - GH_AW_GITHUB_WORKFLOW: process.env.GH_AW_GITHUB_WORKFLOW - } - }); - - name: Append XPIA security instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/xpia_prompt.md" >> "$GH_AW_PROMPT" - - name: Append temporary folder instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - - name: Append cache memory instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - --- - - ## Cache Folder Available - - You have access to a persistent cache folder at `/tmp/gh-aw/cache-memory/` where you can read and write files to create memories and store information. - - - **Read/Write Access**: You can freely read from and write to any files in this folder - - **Persistence**: Files in this folder persist across workflow runs via GitHub Actions cache - - **Last Write Wins**: If multiple processes write to the same file, the last write will be preserved - - **File Share**: Use this as a simple file share - organize files as you see fit - - Examples of what you can store: - - `/tmp/gh-aw/cache-memory/notes.txt` - general notes and observations - - `/tmp/gh-aw/cache-memory/preferences.json` - user preferences and settings - - `/tmp/gh-aw/cache-memory/history.log` - activity history and logs - - `/tmp/gh-aw/cache-memory/state/` - organized state files in subdirectories - - Feel free to create, read, update, and organize files in this folder as needed for your tasks. - PROMPT_EOF - - name: Append safe outputs instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - **Available tools**: create_discussion, missing_tool, noop - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - - PROMPT_EOF - - name: Append GitHub context to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - 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}} - - - PROMPT_EOF - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} with: script: | @@ -770,6 +745,7 @@ jobs: GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKFLOW: process.env.GH_AW_GITHUB_WORKFLOW, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE } }); @@ -785,6 +761,10 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); await main(); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - name: Print prompt env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -795,7 +775,7 @@ jobs: timeout-minutes: 30 run: | set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --image-tag 0.8.2 \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.10.0 \ -- /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 --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} \ 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: @@ -806,7 +786,6 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} 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_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} GITHUB_WORKSPACE: ${{ github.workspace }} @@ -828,6 +807,15 @@ jobs: 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.0.0 @@ -890,12 +878,25 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); await main(); - - name: Firewall summary + - name: Parse MCP gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs if: always() continue-on-error: true env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: awf logs summary >> $GITHUB_STEP_SUMMARY + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - name: Upload cache-memory data as artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 if: always() @@ -952,7 +953,7 @@ jobs: echo "Agent Conclusion: $AGENT_CONCLUSION" - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -988,6 +989,22 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "API Coherence Checker" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + 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/handle_agent_failure.cjs'); + await main(); - name: Update reaction comment with completion status id: conclusion uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -1024,13 +1041,13 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent artifacts continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-artifacts path: /tmp/gh-aw/threat-detection/ - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/threat-detection/ @@ -1098,7 +1115,8 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -1107,7 +1125,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -1184,7 +1203,7 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -1198,7 +1217,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Agentic Workflows\",\"close_older_discussions\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[API Coherence] \"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Agentic Workflows\",\"close_older_discussions\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[API Coherence] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -1220,13 +1239,13 @@ jobs: with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 continue-on-error: true with: name: cache-memory path: /tmp/gh-aw/cache-memory - name: Save cache-memory to cache (default) - uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: memory-${{ github.workflow }}-${{ github.run_id }} path: /tmp/gh-aw/cache-memory diff --git a/.github/workflows/api-coherence-checker.md b/.github/workflows/api-coherence-checker.md index 8ab558170..9b1f6c52f 100644 --- a/.github/workflows/api-coherence-checker.md +++ b/.github/workflows/api-coherence-checker.md @@ -18,7 +18,6 @@ tools: toolsets: [default] bash: [":*"] edit: {} - grep: {} glob: {} web-search: {} @@ -209,4 +208,4 @@ The following cached issues have been resolved since the last run: - **DO NOT** try to fix the APIs yourself - only document and suggest - **DO NOT** analyze all APIs at once - be incremental and use cache memory - **DO** close older discussions automatically (this is configured) -- **DO** provide enough detail for maintainers to understand and act on your findings +- **DO** provide enough detail for maintainers to understand and act on your findings \ No newline at end of file diff --git a/.github/workflows/build-warning-fixer.lock.yml b/.github/workflows/build-warning-fixer.lock.yml index e6485a035..ff6bb4e69 100644 --- a/.github/workflows/build-warning-fixer.lock.yml +++ b/.github/workflows/build-warning-fixer.lock.yml @@ -13,7 +13,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.36.0). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.37.0). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -28,7 +28,7 @@ name: "Build Warning Fixer" # Friendly format: daily (scattered) workflow_dispatch: -permissions: read-all +permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}" @@ -66,6 +66,10 @@ jobs: 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: /tmp/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json @@ -75,13 +79,14 @@ jobs: model: ${{ steps.generate_aw_info.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts uses: githubnext/gh-aw/actions/setup@v0.37.0 with: destination: /opt/gh-aw/actions - name: Checkout repository - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v5.0.1 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false - name: Create gh-aw temp directory @@ -111,7 +116,8 @@ jobs: const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -120,7 +126,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -128,23 +135,19 @@ jobs: # Verify installation copilot --version - name: Install awf binary - run: | - echo "Installing awf via installer script (requested version: v0.8.2)" - curl -sSL https://raw.githubusercontent.com/githubnext/gh-aw-firewall/main/install.sh | sudo AWF_VERSION=v0.8.2 bash - which awf - awf --version + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.10.0 - name: Determine automatic lockdown mode for GitHub MCP server id: determine-automatic-lockdown env: TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} if: env.TOKEN_CHECK != '' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - - name: Downloading container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.27.0 + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.29.0 ghcr.io/githubnext/gh-aw-mcpg:v0.0.71 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs @@ -189,7 +192,7 @@ jobs: "name": "create_pull_request" }, { - "description": "Report that a tool or capability needed to complete the task is not available. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "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": { @@ -198,16 +201,15 @@ jobs: "type": "string" }, "reason": { - "description": "Explanation of why this tool is needed to complete the task (max 256 characters).", + "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": "Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", "type": "string" } }, "required": [ - "tool", "reason" ], "type": "object" @@ -230,6 +232,33 @@ jobs: "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" } ] EOF @@ -299,44 +328,48 @@ jobs: } } EOF - - name: Setup MCPs + - name: Start MCP gateway + id: start-mcp-gateway env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | + set -eo pipefail mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY="" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + export MCP_GATEWAY_API_KEY + + # Register API key as secret to mask it from logs + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + 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 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 -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/githubnext/gh-aw-mcpg:v0.0.71' + mkdir -p /home/runner/.copilot - cat > /home/runner/.copilot/mcp-config.json << EOF + cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh { "mcpServers": { "github": { - "type": "local", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-e", - "GITHUB_PERSONAL_ACCESS_TOKEN", - "-e", - "GITHUB_READ_ONLY=1", - "-e", - "GITHUB_LOCKDOWN_MODE=$GITHUB_MCP_LOCKDOWN", - "-e", - "GITHUB_TOOLSETS=context,repos,issues,pull_requests", - "ghcr.io/github/github-mcp-server:v0.27.0" - ], - "tools": ["*"], + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.29.0", "env": { - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}" + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" } }, "safeoutputs": { - "type": "local", - "command": "node", - "args": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], - "tools": ["*"], + "type": "stdio", + "container": "node:lts-alpine", + "entrypoint": "node", + "entrypointArgs": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], + "mounts": ["/opt/gh-aw:/opt/gh-aw:ro", "/tmp/gh-aw:/tmp/gh-aw:rw"], "env": { "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}", "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", @@ -352,16 +385,14 @@ jobs: "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}" } } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}" } } - EOF - echo "-------START MCP CONFIG-----------" - cat /home/runner/.copilot/mcp-config.json - echo "-------END MCP CONFIG-----------" - echo "-------/home/runner/.copilot-----------" - find /home/runner/.copilot - echo "HOME: $HOME" - echo "GITHUB_COPILOT_CLI_MODE: $GITHUB_COPILOT_CLI_MODE" + MCPCONFIG_EOF - name: Generate agentic run info id: generate_aw_info uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -374,8 +405,8 @@ jobs: engine_name: "GitHub Copilot CLI", model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", version: "", - agent_version: "0.0.375", - cli_version: "v0.36.0", + agent_version: "0.0.387", + cli_version: "v0.37.0", workflow_name: "Build Warning Fixer", experimental: false, supports_tools_allowlist: true, @@ -392,7 +423,8 @@ jobs: network_mode: "defaults", allowed_domains: [], firewall_enabled: true, - awf_version: "v0.8.2", + awf_version: "v0.10.0", + awmg_version: "v0.0.71", steps: { firewall: "squid" }, @@ -413,13 +445,72 @@ jobs: script: | const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); await generateWorkflowOverview(core); - - name: Create prompt + - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" + + PROMPT_EOF + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + **Available tools**: create_pull_request, missing_tool, noop + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + + + 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}} + + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" # Build Warning Fixer You are an AI agent that automatically detects and fixes build warnings in the Z3 theorem prover codebase. @@ -547,77 +638,6 @@ jobs: If you find and fix warnings, create a PR. If no warnings are found or all warnings are too complex to auto-fix, exit gracefully without creating a PR. - PROMPT_EOF - - name: Append XPIA security instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/xpia_prompt.md" >> "$GH_AW_PROMPT" - - name: Append temporary folder instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - - name: Append safe outputs instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - **Available tools**: create_pull_request, missing_tool, noop - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - - PROMPT_EOF - - name: Append GitHub context to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - 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}} - - PROMPT_EOF - name: Substitute placeholders uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -659,6 +679,10 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); await main(); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - name: Print prompt env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -673,7 +697,7 @@ jobs: timeout-minutes: 60 run: | set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --image-tag 0.8.2 \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.10.0 \ -- /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 github --allow-tool safeoutputs --allow-tool shell --allow-tool write --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} \ 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: @@ -684,7 +708,6 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} 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_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} GITHUB_WORKSPACE: ${{ github.workspace }} @@ -706,6 +729,15 @@ jobs: 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.0.0 @@ -768,12 +800,25 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); await main(); - - name: Firewall summary + - name: Parse MCP gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs if: always() continue-on-error: true env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: awf logs summary >> $GITHUB_STEP_SUMMARY + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - name: Upload agent artifacts if: always() continue-on-error: true @@ -824,7 +869,7 @@ jobs: echo "Agent Conclusion: $AGENT_CONCLUSION" - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -862,6 +907,22 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Build Warning Fixer" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); - name: Update reaction comment with completion status id: conclusion uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -898,13 +959,13 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent artifacts continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-artifacts path: /tmp/gh-aw/threat-detection/ - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/threat-detection/ @@ -972,7 +1033,8 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -981,7 +1043,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -1060,7 +1123,7 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -1071,13 +1134,13 @@ jobs: echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - name: Download patch artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v5.0.1 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: token: ${{ github.token }} persist-credentials: false @@ -1087,19 +1150,20 @@ jobs: env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ github.token }} run: | git config --global user.email "github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions[bot]" # Re-authenticate git with GitHub token SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" - name: Process Safe Outputs id: process_safe_outputs uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":1024}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/build-warning-fixer.md b/.github/workflows/build-warning-fixer.md index 4d43227d1..c8844bf5d 100644 --- a/.github/workflows/build-warning-fixer.md +++ b/.github/workflows/build-warning-fixer.md @@ -6,7 +6,6 @@ on: permissions: read-all tools: view: {} - grep: {} glob: {} edit: bash: @@ -143,4 +142,4 @@ You are an AI agent that automatically detects and fixes build warnings in the Z ## Output -If you find and fix warnings, create a PR. If no warnings are found or all warnings are too complex to auto-fix, exit gracefully without creating a PR. +If you find and fix warnings, create a PR. If no warnings are found or all warnings are too complex to auto-fix, exit gracefully without creating a PR. \ No newline at end of file diff --git a/.github/workflows/code-conventions-analyzer.lock.yml b/.github/workflows/code-conventions-analyzer.lock.yml index f923b5483..0f589c59a 100644 --- a/.github/workflows/code-conventions-analyzer.lock.yml +++ b/.github/workflows/code-conventions-analyzer.lock.yml @@ -13,7 +13,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.36.0). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.37.0). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -28,7 +28,7 @@ name: "Code Conventions Analyzer" # Friendly format: daily (scattered) workflow_dispatch: -permissions: read-all +permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}" @@ -66,6 +66,10 @@ jobs: 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: /tmp/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json @@ -75,6 +79,7 @@ jobs: model: ${{ steps.generate_aw_info.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts uses: githubnext/gh-aw/actions/setup@v0.37.0 @@ -89,8 +94,8 @@ jobs: # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory run: bash /opt/gh-aw/actions/create_cache_memory_dir.sh - - name: Restore cache memory file share data - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + - name: Restore cache-memory file share data + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: memory-${{ github.workflow }}-${{ github.run_id }} path: /tmp/gh-aw/cache-memory @@ -122,7 +127,8 @@ jobs: const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -131,7 +137,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -139,23 +146,19 @@ jobs: # Verify installation copilot --version - name: Install awf binary - run: | - echo "Installing awf via installer script (requested version: v0.8.2)" - curl -sSL https://raw.githubusercontent.com/githubnext/gh-aw-firewall/main/install.sh | sudo AWF_VERSION=v0.8.2 bash - which awf - awf --version + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.10.0 - name: Determine automatic lockdown mode for GitHub MCP server id: determine-automatic-lockdown env: TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} if: env.TOKEN_CHECK != '' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - - name: Downloading container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.27.0 + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.29.0 ghcr.io/githubnext/gh-aw-mcpg:v0.0.71 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs @@ -193,7 +196,7 @@ jobs: "name": "create_discussion" }, { - "description": "Report that a tool or capability needed to complete the task is not available. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "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": { @@ -202,16 +205,15 @@ jobs: "type": "string" }, "reason": { - "description": "Explanation of why this tool is needed to complete the task (max 256 characters).", + "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": "Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", "type": "string" } }, "required": [ - "tool", "reason" ], "type": "object" @@ -234,6 +236,33 @@ jobs: "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" } ] EOF @@ -300,44 +329,48 @@ jobs: } } EOF - - name: Setup MCPs + - name: Start MCP gateway + id: start-mcp-gateway env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | + set -eo pipefail mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY="" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + export MCP_GATEWAY_API_KEY + + # Register API key as secret to mask it from logs + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + 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 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 -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/githubnext/gh-aw-mcpg:v0.0.71' + mkdir -p /home/runner/.copilot - cat > /home/runner/.copilot/mcp-config.json << EOF + cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh { "mcpServers": { "github": { - "type": "local", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-e", - "GITHUB_PERSONAL_ACCESS_TOKEN", - "-e", - "GITHUB_READ_ONLY=1", - "-e", - "GITHUB_LOCKDOWN_MODE=$GITHUB_MCP_LOCKDOWN", - "-e", - "GITHUB_TOOLSETS=context,repos,issues,pull_requests", - "ghcr.io/github/github-mcp-server:v0.27.0" - ], - "tools": ["*"], + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.29.0", "env": { - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}" + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" } }, "safeoutputs": { - "type": "local", - "command": "node", - "args": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], - "tools": ["*"], + "type": "stdio", + "container": "node:lts-alpine", + "entrypoint": "node", + "entrypointArgs": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], + "mounts": ["/opt/gh-aw:/opt/gh-aw:ro", "/tmp/gh-aw:/tmp/gh-aw:rw"], "env": { "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}", "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", @@ -353,16 +386,14 @@ jobs: "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}" } } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}" } } - EOF - echo "-------START MCP CONFIG-----------" - cat /home/runner/.copilot/mcp-config.json - echo "-------END MCP CONFIG-----------" - echo "-------/home/runner/.copilot-----------" - find /home/runner/.copilot - echo "HOME: $HOME" - echo "GITHUB_COPILOT_CLI_MODE: $GITHUB_COPILOT_CLI_MODE" + MCPCONFIG_EOF - name: Generate agentic run info id: generate_aw_info uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -375,8 +406,8 @@ jobs: engine_name: "GitHub Copilot CLI", model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", version: "", - agent_version: "0.0.375", - cli_version: "v0.36.0", + agent_version: "0.0.387", + cli_version: "v0.37.0", workflow_name: "Code Conventions Analyzer", experimental: false, supports_tools_allowlist: true, @@ -393,7 +424,8 @@ jobs: network_mode: "defaults", allowed_domains: [], firewall_enabled: true, - awf_version: "v0.8.2", + awf_version: "v0.10.0", + awmg_version: "v0.0.71", steps: { firewall: "squid" }, @@ -414,13 +446,92 @@ jobs: script: | const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); await generateWorkflowOverview(core); - - name: Create prompt + - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" + + PROMPT_EOF + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + --- + + ## Cache Folder Available + + You have access to a persistent cache folder at `/tmp/gh-aw/cache-memory/` where you can read and write files to create memories and store information. + + - **Read/Write Access**: You can freely read from and write to any files in this folder + - **Persistence**: Files in this folder persist across workflow runs via GitHub Actions cache + - **Last Write Wins**: If multiple processes write to the same file, the last write will be preserved + - **File Share**: Use this as a simple file share - organize files as you see fit + + Examples of what you can store: + - `/tmp/gh-aw/cache-memory/notes.txt` - general notes and observations + - `/tmp/gh-aw/cache-memory/preferences.json` - user preferences and settings + - `/tmp/gh-aw/cache-memory/history.log` - activity history and logs + - `/tmp/gh-aw/cache-memory/state/` - organized state files in subdirectories + + Feel free to create, read, update, and organize files in this folder as needed for your tasks. + + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + **Available tools**: create_discussion, missing_tool, noop + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + + + 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}} + + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" # Code Conventions Analyzer You are an expert C++ code quality analyst specializing in the Z3 theorem prover codebase. Your mission is to examine the codebase for consistent coding conventions and identify opportunities to use modern C++ features (C++17, C++20) that can simplify and improve the code. @@ -830,10 +941,6 @@ jobs: - Examples: [File:line references] PROMPT_EOF - - name: Append prompt (part 2) - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" #### 4.1.3 Non-Virtual Destructor Safety Analysis - **Classes with Virtual Methods but Non-Virtual Destructors**: Potential polymorphism issues @@ -1205,102 +1312,6 @@ jobs: - Provide actionable recommendations - Previous discussions created by this workflow will be automatically closed (using `close-older-discussions: true`) - PROMPT_EOF - - name: Append XPIA security instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/xpia_prompt.md" >> "$GH_AW_PROMPT" - - name: Append temporary folder instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - - name: Append cache memory instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - --- - - ## Cache Folder Available - - You have access to a persistent cache folder at `/tmp/gh-aw/cache-memory/` where you can read and write files to create memories and store information. - - - **Read/Write Access**: You can freely read from and write to any files in this folder - - **Persistence**: Files in this folder persist across workflow runs via GitHub Actions cache - - **Last Write Wins**: If multiple processes write to the same file, the last write will be preserved - - **File Share**: Use this as a simple file share - organize files as you see fit - - Examples of what you can store: - - `/tmp/gh-aw/cache-memory/notes.txt` - general notes and observations - - `/tmp/gh-aw/cache-memory/preferences.json` - user preferences and settings - - `/tmp/gh-aw/cache-memory/history.log` - activity history and logs - - `/tmp/gh-aw/cache-memory/state/` - organized state files in subdirectories - - Feel free to create, read, update, and organize files in this folder as needed for your tasks. - PROMPT_EOF - - name: Append safe outputs instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - **Available tools**: create_discussion, missing_tool, noop - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - - PROMPT_EOF - - name: Append GitHub context to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - 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}} - - PROMPT_EOF - name: Substitute placeholders uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -1342,6 +1353,10 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); await main(); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - name: Print prompt env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -1371,7 +1386,7 @@ jobs: timeout-minutes: 20 run: | set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --image-tag 0.8.2 \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.10.0 \ -- /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 github --allow-tool safeoutputs --allow-tool 'shell(cat)' --allow-tool 'shell(clang-format --version)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(git diff:*)' --allow-tool 'shell(git log:*)' --allow-tool 'shell(git show:*)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(pwd)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} \ 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: @@ -1382,7 +1397,6 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} 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_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} GITHUB_WORKSPACE: ${{ github.workspace }} @@ -1404,6 +1418,15 @@ jobs: 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.0.0 @@ -1466,12 +1489,25 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); await main(); - - name: Firewall summary + - name: Parse MCP gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs if: always() continue-on-error: true env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: awf logs summary >> $GITHUB_STEP_SUMMARY + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - name: Upload cache-memory data as artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 if: always() @@ -1528,7 +1564,7 @@ jobs: echo "Agent Conclusion: $AGENT_CONCLUSION" - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -1566,6 +1602,22 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Conventions Analyzer" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); - name: Update reaction comment with completion status id: conclusion uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -1602,13 +1654,13 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent artifacts continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-artifacts path: /tmp/gh-aw/threat-detection/ - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/threat-detection/ @@ -1676,7 +1728,8 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -1685,7 +1738,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -1762,7 +1816,7 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -1776,7 +1830,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Agentic Workflows\",\"close_older_discussions\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"Code Conventions Analysis\"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Agentic Workflows\",\"close_older_discussions\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"Code Conventions Analysis\"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1798,13 +1852,13 @@ jobs: with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 continue-on-error: true with: name: cache-memory path: /tmp/gh-aw/cache-memory - name: Save cache-memory to cache (default) - uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: memory-${{ github.workflow }}-${{ github.run_id }} path: /tmp/gh-aw/cache-memory diff --git a/.github/workflows/code-conventions-analyzer.md b/.github/workflows/code-conventions-analyzer.md index e1234c8db..fceca5464 100644 --- a/.github/workflows/code-conventions-analyzer.md +++ b/.github/workflows/code-conventions-analyzer.md @@ -9,7 +9,6 @@ tools: github: toolsets: [default] view: {} - grep: {} glob: {} bash: - "clang-format --version" @@ -803,4 +802,4 @@ grep pattern: "catch.*continue|catch.*break" glob: "src/**/*.cpp" - Use the structured format above - Include specific file references for all examples - Provide actionable recommendations -- Previous discussions created by this workflow will be automatically closed (using `close-older-discussions: true`) +- Previous discussions created by this workflow will be automatically closed (using `close-older-discussions: true`) \ No newline at end of file diff --git a/.github/workflows/release-notes-updater.lock.yml b/.github/workflows/release-notes-updater.lock.yml index 8bcee8b93..15ba6a3cd 100644 --- a/.github/workflows/release-notes-updater.lock.yml +++ b/.github/workflows/release-notes-updater.lock.yml @@ -13,7 +13,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.36.0). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.37.0). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -28,7 +28,7 @@ name: "Release Notes Updater" # Friendly format: weekly (scattered) workflow_dispatch: -permissions: read-all +permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}" @@ -66,6 +66,10 @@ jobs: 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: /tmp/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json @@ -75,6 +79,7 @@ jobs: model: ${{ steps.generate_aw_info.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts uses: githubnext/gh-aw/actions/setup@v0.37.0 @@ -83,7 +88,7 @@ jobs: - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Checkout repository - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: fetch-depth: 0 @@ -112,7 +117,8 @@ jobs: const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -121,7 +127,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -129,23 +136,19 @@ jobs: # Verify installation copilot --version - name: Install awf binary - run: | - echo "Installing awf via installer script (requested version: v0.8.2)" - curl -sSL https://raw.githubusercontent.com/githubnext/gh-aw-firewall/main/install.sh | sudo AWF_VERSION=v0.8.2 bash - which awf - awf --version + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.10.0 - name: Determine automatic lockdown mode for GitHub MCP server id: determine-automatic-lockdown env: TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} if: env.TOKEN_CHECK != '' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - - name: Downloading container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.27.0 + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.29.0 ghcr.io/githubnext/gh-aw-mcpg:v0.0.71 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs @@ -183,7 +186,7 @@ jobs: "name": "create_discussion" }, { - "description": "Report that a tool or capability needed to complete the task is not available. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "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": { @@ -192,16 +195,15 @@ jobs: "type": "string" }, "reason": { - "description": "Explanation of why this tool is needed to complete the task (max 256 characters).", + "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": "Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", "type": "string" } }, "required": [ - "tool", "reason" ], "type": "object" @@ -224,6 +226,33 @@ jobs: "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" } ] EOF @@ -290,44 +319,48 @@ jobs: } } EOF - - name: Setup MCPs + - name: Start MCP gateway + id: start-mcp-gateway env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | + set -eo pipefail mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY="" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + export MCP_GATEWAY_API_KEY + + # Register API key as secret to mask it from logs + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + 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 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 -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/githubnext/gh-aw-mcpg:v0.0.71' + mkdir -p /home/runner/.copilot - cat > /home/runner/.copilot/mcp-config.json << EOF + cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh { "mcpServers": { "github": { - "type": "local", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-e", - "GITHUB_PERSONAL_ACCESS_TOKEN", - "-e", - "GITHUB_READ_ONLY=1", - "-e", - "GITHUB_LOCKDOWN_MODE=$GITHUB_MCP_LOCKDOWN", - "-e", - "GITHUB_TOOLSETS=context,repos,issues,pull_requests", - "ghcr.io/github/github-mcp-server:v0.27.0" - ], - "tools": ["*"], + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.29.0", "env": { - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}" + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" } }, "safeoutputs": { - "type": "local", - "command": "node", - "args": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], - "tools": ["*"], + "type": "stdio", + "container": "node:lts-alpine", + "entrypoint": "node", + "entrypointArgs": ["/opt/gh-aw/safeoutputs/mcp-server.cjs"], + "mounts": ["/opt/gh-aw:/opt/gh-aw:ro", "/tmp/gh-aw:/tmp/gh-aw:rw"], "env": { "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}", "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", @@ -343,16 +376,14 @@ jobs: "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}" } } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}" } } - EOF - echo "-------START MCP CONFIG-----------" - cat /home/runner/.copilot/mcp-config.json - echo "-------END MCP CONFIG-----------" - echo "-------/home/runner/.copilot-----------" - find /home/runner/.copilot - echo "HOME: $HOME" - echo "GITHUB_COPILOT_CLI_MODE: $GITHUB_COPILOT_CLI_MODE" + MCPCONFIG_EOF - name: Generate agentic run info id: generate_aw_info uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -365,8 +396,8 @@ jobs: engine_name: "GitHub Copilot CLI", model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", version: "", - agent_version: "0.0.375", - cli_version: "v0.36.0", + agent_version: "0.0.387", + cli_version: "v0.37.0", workflow_name: "Release Notes Updater", experimental: false, supports_tools_allowlist: true, @@ -383,7 +414,8 @@ jobs: network_mode: "defaults", allowed_domains: [], firewall_enabled: true, - awf_version: "v0.8.2", + awf_version: "v0.10.0", + awmg_version: "v0.0.71", steps: { firewall: "squid" }, @@ -404,15 +436,73 @@ jobs: script: | const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); await generateWorkflowOverview(core); - - name: Create prompt + - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" + + PROMPT_EOF + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + **Available tools**: create_discussion, missing_tool, noop + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + + + 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}} + + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + PROMPT_EOF + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" # Release Notes Updater ## Job Description @@ -601,102 +691,14 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} - with: - script: | - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, - GH_AW_GITHUB_WORKFLOW: process.env.GH_AW_GITHUB_WORKFLOW - } - }); - - name: Append XPIA security instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/xpia_prompt.md" >> "$GH_AW_PROMPT" - - name: Append temporary folder instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - - name: Append safe outputs instructions to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - **Available tools**: create_discussion, missing_tool, noop - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - - PROMPT_EOF - - name: Append GitHub context to prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" - - 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}} - - - PROMPT_EOF - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} with: script: | @@ -713,6 +715,7 @@ jobs: GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKFLOW: process.env.GH_AW_GITHUB_WORKFLOW, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE } }); @@ -728,6 +731,10 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); await main(); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - name: Print prompt env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -738,7 +745,7 @@ jobs: timeout-minutes: 30 run: | set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --image-tag 0.8.2 \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --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 --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.10.0 \ -- /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 --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} \ 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: @@ -749,7 +756,6 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} 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_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} GITHUB_WORKSPACE: ${{ github.workspace }} @@ -771,6 +777,15 @@ jobs: 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.0.0 @@ -833,12 +848,25 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); await main(); - - name: Firewall summary + - name: Parse MCP gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs if: always() continue-on-error: true env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: awf logs summary >> $GITHUB_STEP_SUMMARY + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - name: Upload agent artifacts if: always() continue-on-error: true @@ -888,7 +916,7 @@ jobs: echo "Agent Conclusion: $AGENT_CONCLUSION" - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -924,6 +952,22 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Release Notes Updater" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + 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/handle_agent_failure.cjs'); + await main(); - name: Update reaction comment with completion status id: conclusion uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -960,13 +1004,13 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent artifacts continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-artifacts path: /tmp/gh-aw/threat-detection/ - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/threat-detection/ @@ -1034,7 +1078,8 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Validate COPILOT_GITHUB_TOKEN secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Install GitHub Copilot CLI @@ -1043,7 +1088,8 @@ jobs: curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh # Execute the installer with the specified version - export VERSION=0.0.375 && sudo bash /tmp/copilot-install.sh + # Pass VERSION directly to sudo to ensure it's available to the installer script + sudo VERSION=0.0.387 bash /tmp/copilot-install.sh # Cleanup rm -f /tmp/copilot-install.sh @@ -1120,7 +1166,7 @@ jobs: destination: /opt/gh-aw/actions - name: Download agent output artifact continue-on-error: true - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: agent-output path: /tmp/gh-aw/safeoutputs/ @@ -1134,7 +1180,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Announcements\",\"expires\":168,\"max\":1,\"title_prefix\":\"[Release Notes] \"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"Announcements\",\"expires\":168,\"max\":1,\"title_prefix\":\"[Release Notes] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/release-notes-updater.md b/.github/workflows/release-notes-updater.md index 238cdaf5b..3fadb2163 100644 --- a/.github/workflows/release-notes-updater.md +++ b/.github/workflows/release-notes-updater.md @@ -16,7 +16,6 @@ tools: toolsets: [default] bash: [":*"] edit: {} - grep: {} glob: {} view: {} @@ -216,4 +215,4 @@ If there are NO substantial changes since the last release: 4. Analyze each commit to determine if substantial 5. Format the changes following existing style 6. Check for existing discussions -7. Create discussion with the release notes analysis and formatted content +7. Create discussion with the release notes analysis and formatted content \ No newline at end of file