From e44b42f6aa09a45f671e9fe6fce6a5fb479a8642 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 21:00:47 +0000 Subject: [PATCH 01/10] feat: add edit-wiki safe-output for pushing changes to repository wikis - Add EditWikiConfig struct and parseEditWikiConfig parser - Register edit-wiki in SafeOutputsConfig and safe_outputs_config.go - Extend usesPatchesAndCheckouts to include edit-wiki for patch/auth support - Add usesPRCheckout helper to guard compile-time repo checkout (PR-only) - Update compiler_safe_outputs_job.go to use usesPRCheckout for checkout steps - Add edit_wiki handler config builder in compiler_safe_outputs_handlers.go - Add contents: write permissions for edit-wiki - Add edit_wiki to safe_outputs_tools.json tool definition - Add edit_wiki repo parameter support in safe_outputs_tools_repo_params.go - Add edit-wiki to JSON schema (main_workflow_schema.json) - Create JS handler edit_wiki.cjs that clones wiki, applies patch, pushes - Register edit_wiki in safe_output_handler_manager.cjs - Add comprehensive Go tests for edit-wiki config and compilation Agent-Logs-Url: https://github.com/github/gh-aw/sessions/62d937c5-0490-4dcd-9f26-4bbb6e05442e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/edit_wiki.cjs | 335 ++ .../setup/js/safe_output_handler_manager.cjs | 1 + pkg/parser/schemas/main_workflow_schema.json | 2811 ++++++++++++++--- .../compiler_safe_outputs_handlers.go | 20 + pkg/workflow/compiler_safe_outputs_job.go | 20 +- pkg/workflow/compiler_types.go | 1 + pkg/workflow/edit_wiki.go | 75 + pkg/workflow/edit_wiki_test.go | 372 +++ pkg/workflow/js/safe_outputs_tools.json | 25 + pkg/workflow/safe_outputs_config.go | 6 + pkg/workflow/safe_outputs_permissions.go | 5 +- pkg/workflow/safe_outputs_runtime.go | 24 +- .../safe_outputs_tools_repo_params.go | 5 + 13 files changed, 3190 insertions(+), 510 deletions(-) create mode 100644 actions/setup/js/edit_wiki.cjs create mode 100644 pkg/workflow/edit_wiki.go create mode 100644 pkg/workflow/edit_wiki_test.go diff --git a/actions/setup/js/edit_wiki.cjs b/actions/setup/js/edit_wiki.cjs new file mode 100644 index 00000000000..565ff7af8e8 --- /dev/null +++ b/actions/setup/js/edit_wiki.cjs @@ -0,0 +1,335 @@ +// @ts-check +/// + +/** @type {typeof import("fs")} */ +const fs = require("fs"); +const os = require("os"); +const nodePath = require("path"); +const { generateStagedPreview } = require("./staged_preview.cjs"); +const { isStagedMode } = require("./safe_output_helpers.cjs"); +const { getErrorMessage } = require("./error_helpers.cjs"); +const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs"); +const { createAuthenticatedGitHubClient } = require("./handler_auth.cjs"); +const { getGitAuthEnv } = require("./git_helpers.cjs"); + +/** + * @typedef {import('./types/handler-factory').HandlerFactoryFunction} HandlerFactoryFunction + */ + +/** @type {string} Safe output type handled by this module */ +const HANDLER_TYPE = "edit_wiki"; + +/** + * Main handler factory for edit_wiki + * Returns a message handler function that processes individual edit_wiki messages + * @type {HandlerFactoryFunction} + */ +async function main(config = {}) { + const ifNoChanges = config.if_no_changes || "warn"; + const commitTitleSuffix = config.commit_title_suffix || ""; + const maxSizeKb = config.max_patch_size ? parseInt(String(config.max_patch_size), 10) : 1024; + const maxCount = config.max || 0; // 0 means no limit + + // Cross-repo support: resolve target repository from config + const { defaultTargetRepo, allowedRepos } = resolveTargetRepoConfig(config); + + // Build git auth env once for all network operations in this handler. + const gitAuthEnv = getGitAuthEnv(config["github-token"]); + + // Check if we're in staged mode + const isStaged = isStagedMode(config); + + core.info(`If no changes: ${ifNoChanges}`); + if (commitTitleSuffix) { + core.info(`Commit title suffix: ${commitTitleSuffix}`); + } + core.info(`Max patch size: ${maxSizeKb} KB`); + core.info(`Max count: ${maxCount || "unlimited"}`); + core.info(`Default target repo: ${defaultTargetRepo}`); + if (allowedRepos.size > 0) { + core.info(`Allowed repos: ${[...allowedRepos].join(", ")}`); + } + + // Track how many items we've processed for max limit + let processedCount = 0; + + /** + * Message handler function - processes individual edit_wiki messages + * @param {any} message - The edit_wiki message to process + * @param {import('./types/handler-factory').ResolvedTemporaryIds} resolvedTemporaryIds - Map of temporary IDs to resolved IDs + * @returns {Promise} + */ + return async function handleEditWiki(message, resolvedTemporaryIds) { + // Check max count + if (maxCount > 0 && processedCount >= maxCount) { + core.info(`Skipping message - max count (${maxCount}) reached`); + return { success: false, error: `Max count (${maxCount}) reached`, skipped: true }; + } + + processedCount++; + + // Determine the patch file path from the message + const patchFilePath = message.patch_path; + core.info(`Patch file path: ${patchFilePath || "(not set)"}`); + + // Check if patch file exists and has valid content + if (!patchFilePath || !fs.existsSync(patchFilePath)) { + const msg = "No patch file found - cannot push wiki changes without a patch"; + + switch (ifNoChanges) { + case "error": + return { success: false, error: msg }; + case "ignore": + return { success: false, error: msg, skipped: true }; + case "warn": + default: + core.info(msg); + return { success: false, error: msg, skipped: true }; + } + } + + const patchContent = fs.readFileSync(patchFilePath, "utf8"); + + // Check for actual error conditions + if (patchContent.includes("Failed to generate patch")) { + const msg = "Patch file contains error message - cannot push wiki changes"; + core.error("Patch file generation failed"); + core.error(`Patch file location: ${patchFilePath}`); + return { success: false, error: msg }; + } + + const isEmpty = !patchContent || !patchContent.trim(); + + // Validate patch size + if (!isEmpty) { + const patchSizeBytes = Buffer.byteLength(patchContent, "utf8"); + const patchSizeKb = Math.ceil(patchSizeBytes / 1024); + + const diffSizeBytesRaw = message.diff_size; + const haveDiffSize = typeof diffSizeBytesRaw === "number" && diffSizeBytesRaw >= 0; + + let sizeForCheckBytes; + let sizeLabel; + if (haveDiffSize) { + sizeForCheckBytes = diffSizeBytesRaw; + sizeLabel = "Incremental diff size"; + } else { + sizeForCheckBytes = patchSizeBytes; + sizeLabel = "Patch size"; + } + const sizeForCheckKb = Math.ceil(sizeForCheckBytes / 1024); + + core.info(`Patch file size: ${patchSizeKb} KB`); + core.info(`${sizeLabel}: ${sizeForCheckKb} KB (maximum allowed: ${maxSizeKb} KB)`); + + if (sizeForCheckKb > maxSizeKb) { + const msg = `${sizeLabel} (${sizeForCheckKb} KB) exceeds maximum allowed size (${maxSizeKb} KB)`; + return { success: false, error: msg }; + } + + core.info("Patch size validation passed"); + } + + if (isEmpty) { + const msg = "Patch file is empty - no changes to apply to wiki"; + + switch (ifNoChanges) { + case "error": + return { success: false, error: "No wiki changes to push - failing as configured by if-no-changes: error" }; + case "ignore": + return { success: false, error: msg, skipped: true }; + case "warn": + default: + core.info(msg); + return { success: false, error: msg, skipped: true }; + } + } + + // If in staged mode, emit staged preview + if (isStaged) { + await generateStagedPreview({ + title: "Edit Wiki", + description: "The following wiki changes would be pushed if staged mode was disabled:", + items: [{ commit_message: message.message || message.commit_message || "(no message)" }], + renderItem: item => { + let content = `**Wiki:** ${defaultTargetRepo || process.env.GITHUB_REPOSITORY || "(current repo)"}\n\n`; + if (item.commit_message) { + content += `**Commit Message:** ${item.commit_message}\n\n`; + } + if (patchFilePath && fs.existsSync(patchFilePath)) { + const patchStats = fs.readFileSync(patchFilePath, "utf8"); + if (patchStats.trim()) { + content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`; + content += `
Show patch preview\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n
\n\n`; + } else { + content += `**Changes:** No changes (empty patch)\n\n`; + } + } + return content; + }, + }); + return { success: true, staged: true }; + } + + // Resolve and validate target repository + const repoResult = resolveAndValidateRepo(message, defaultTargetRepo, allowedRepos, "edit wiki"); + if (!repoResult.success) { + return { success: false, error: repoResult.error }; + } + const itemRepo = repoResult.repo; + const repoParts = repoResult.repoParts; + + core.info(`Target repository: ${itemRepo}`); + + // Build the wiki git URL + const serverUrl = (process.env.GITHUB_SERVER_URL || "https://github.com").replace(/\/$/, ""); + const wikiGitUrl = `${serverUrl}/${repoParts.owner}/${repoParts.repo}.wiki.git`; + core.info(`Wiki git URL: ${wikiGitUrl.replace(/:\/\/[^@]+@/, "://***@")}`); + + // Clone wiki to a temp directory + const wikiCloneDir = fs.mkdtempSync(nodePath.join(os.tmpdir(), "gh-aw-wiki-")); + core.info(`Cloning wiki to: ${wikiCloneDir}`); + + try { + // Clone the wiki repo using auth env vars for authentication + const cloneResult = await exec.getExecOutput("git", ["clone", wikiGitUrl, wikiCloneDir], { + env: { ...process.env, ...gitAuthEnv }, + ignoreReturnCode: true, + }); + + if (cloneResult.exitCode !== 0) { + const stderr = (cloneResult.stderr || "").trim(); + // Distinguish empty wiki (no commits yet) from a real error + if (stderr.includes("You appear to have cloned an empty repository") || stderr.includes("warning: You appear to have cloned an empty repository")) { + core.info("Wiki repository is empty - will initialize with first commit"); + // Initialize a new git repo in the clone dir + await exec.exec("git", ["init", wikiCloneDir]); + await exec.exec("git", ["remote", "add", "origin", wikiGitUrl], { cwd: wikiCloneDir, env: { ...process.env, ...gitAuthEnv } }); + } else { + return { + success: false, + error: `Failed to clone wiki repository: ${stderr || `git clone exited with code ${cloneResult.exitCode}`}`, + }; + } + } + + core.info("Wiki cloned successfully"); + + // Configure git identity in the wiki clone + await exec.exec("git", ["config", "user.email", "github-actions[bot]@users.noreply.github.com"], { cwd: wikiCloneDir }); + await exec.exec("git", ["config", "user.name", "github-actions[bot]"], { cwd: wikiCloneDir }); + await exec.exec("git", ["config", "am.keepcr", "true"], { cwd: wikiCloneDir }); + + // Determine the current branch name (wiki default is typically 'master') + let wikiBranch = "master"; + try { + const branchResult = await exec.getExecOutput("git", ["rev-parse", "--abbrev-ref", "HEAD"], { + cwd: wikiCloneDir, + ignoreReturnCode: true, + }); + if (branchResult.exitCode === 0 && branchResult.stdout.trim() && branchResult.stdout.trim() !== "HEAD") { + wikiBranch = branchResult.stdout.trim(); + } + } catch { + // Use default 'master' + } + core.info(`Wiki branch: ${wikiBranch}`); + + // Apply patch to wiki clone + let patchFileToApply = patchFilePath; + + if (commitTitleSuffix) { + core.info(`Appending commit title suffix: "${commitTitleSuffix}"`); + let patchFileContent = fs.readFileSync(patchFilePath, "utf8"); + patchFileContent = patchFileContent.replace(/^Subject: (?:\[PATCH\] )?(.*)$/gm, (match, title) => `Subject: [PATCH] ${title}${commitTitleSuffix}`); + patchFileToApply = nodePath.join(wikiCloneDir, "..", `aw-wiki-modified-${Date.now()}.patch`); + fs.writeFileSync(patchFileToApply, patchFileContent, "utf8"); + core.info(`Patch modified with commit title suffix`); + } + + // Log first 100 lines of patch for debugging + const finalPatchContent = fs.readFileSync(patchFileToApply, "utf8"); + const patchLines = finalPatchContent.split("\n"); + const previewLineCount = Math.min(100, patchLines.length); + core.info(`Patch preview (first ${previewLineCount} of ${patchLines.length} lines):`); + for (let i = 0; i < previewLineCount; i++) { + core.info(patchLines[i]); + } + + // Apply the patch with git am --3way + // --3way handles cases where the patch base may differ from the wiki state + const amResult = await exec.getExecOutput("git", ["am", "--3way", patchFileToApply], { + cwd: wikiCloneDir, + ignoreReturnCode: true, + }); + + if (amResult.exitCode !== 0) { + const amError = (amResult.stderr || amResult.stdout || "").trim(); + core.error(`Failed to apply patch to wiki: ${amError}`); + + // Log debug info + try { + const statusResult = await exec.getExecOutput("git", ["status"], { cwd: wikiCloneDir }); + core.info(`Git status:\n${statusResult.stdout}`); + } catch { + // Non-fatal + } + + // Abort git am in case of partial apply + try { + await exec.exec("git", ["am", "--abort"], { cwd: wikiCloneDir }); + } catch { + // Ignore abort errors + } + + return { success: false, error: `Failed to apply patch to wiki: ${amError || "git am failed"}` }; + } + + core.info("Patch applied to wiki successfully"); + + // Push to the wiki branch + core.info(`Pushing wiki changes to: ${wikiBranch}`); + const pushResult = await exec.getExecOutput("git", ["push", "origin", `HEAD:refs/heads/${wikiBranch}`], { + cwd: wikiCloneDir, + env: { ...process.env, ...gitAuthEnv }, + ignoreReturnCode: true, + }); + + if (pushResult.exitCode !== 0) { + const pushError = (pushResult.stderr || pushResult.stdout || "").trim(); + core.error(`Failed to push wiki changes: ${pushError}`); + return { success: false, error: `Failed to push wiki changes: ${pushError || "git push failed"}` }; + } + + core.info("Wiki changes pushed successfully"); + + // Get the commit SHA for the activation comment update + let commitSha = ""; + try { + const shaResult = await exec.getExecOutput("git", ["rev-parse", "HEAD"], { cwd: wikiCloneDir }); + commitSha = shaResult.stdout.trim(); + } catch { + // Non-fatal + } + + const wikiUrl = `${serverUrl}/${repoParts.owner}/${repoParts.repo}/wiki`; + core.info(`Wiki URL: ${wikiUrl}`); + + return { + success: true, + url: wikiUrl, + sha: commitSha, + }; + } finally { + // Clean up wiki clone directory + try { + fs.rmSync(wikiCloneDir, { recursive: true, force: true }); + core.info("Cleaned up wiki clone directory"); + } catch (cleanupError) { + core.warning(`Failed to clean up wiki clone directory: ${getErrorMessage(cleanupError)}`); + } + } + }; +} + +module.exports = { main }; diff --git a/actions/setup/js/safe_output_handler_manager.cjs b/actions/setup/js/safe_output_handler_manager.cjs index e9fd0baae2f..737f2ac8cb1 100644 --- a/actions/setup/js/safe_output_handler_manager.cjs +++ b/actions/setup/js/safe_output_handler_manager.cjs @@ -51,6 +51,7 @@ const HANDLER_MAP = { resolve_pull_request_review_thread: "./resolve_pr_review_thread.cjs", create_pull_request: "./create_pull_request.cjs", push_to_pull_request_branch: "./push_to_pull_request_branch.cjs", + edit_wiki: "./edit_wiki.cjs", update_pull_request: "./update_pull_request.cjs", merge_pull_request: "./merge_pull_request.cjs", close_pull_request: "./close_pull_request.cjs", diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 3ff7a9d8b61..a91117d0bbb 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -5,30 +5,44 @@ "description": "JSON Schema for validating agentic workflow frontmatter configuration", "version": "1.0.0", "type": "object", - "required": ["on"], + "required": [ + "on" + ], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 256, "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"] + "examples": [ + "Copilot Agent PR Analysis", + "Dev Hawk", + "Smoke Claude" + ] }, "description": { "type": "string", "maxLength": 10000, "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"] + "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"] + "examples": [ + "githubnext/agentics/workflows/ci-doctor.md", + "githubnext/agentics/workflows/daily-perf-improver.md@1f181b37d3fe5862ab590648f25a292e345b5de6" + ] }, "redirect": { "type": "string", "description": "Optional workflow location redirect for updates. Format: workflow spec or GitHub URL (e.g., owner/repo/path@ref or https://github.com/owner/repo/blob/main/path.md). When present, update follows this location and rewrites source.", - "examples": ["githubnext/agentics/workflows/ci-doctor-v2.md@main", "https://github.com/githubnext/agentics/blob/main/workflows/ci-doctor-v2.md"] + "examples": [ + "githubnext/agentics/workflows/ci-doctor-v2.md@main", + "https://github.com/githubnext/agentics/blob/main/workflows/ci-doctor-v2.md" + ] }, "tracker-id": { "type": "string", @@ -36,7 +50,11 @@ "maxLength": 128, "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"] + "examples": [ + "workflow-2024-q1", + "team-alpha-bot", + "security_audit_v2" + ] }, "labels": { "type": "array", @@ -46,9 +64,18 @@ "minLength": 1 }, "examples": [ - ["automation", "security"], - ["docs", "maintenance"], - ["ci", "testing"] + [ + "automation", + "security" + ], + [ + "docs", + "maintenance" + ], + [ + "ci", + "testing" + ] ] }, "metadata": { @@ -85,7 +112,9 @@ { "type": "object", "description": "Import specification with path and optional inputs", - "required": ["path"], + "required": [ + "path" + ], "additionalProperties": false, "properties": { "path": { @@ -131,7 +160,9 @@ { "type": "object", "description": "Import specification with 'uses'/'with' syntax (mirrors GitHub Actions reusable workflow syntax). 'uses' references the workflow path and 'with' provides input values.", - "required": ["uses"], + "required": [ + "uses" + ], "additionalProperties": false, "properties": { "uses": { @@ -216,7 +247,9 @@ { "type": "object", "description": "Import specification with path and optional inputs", - "required": ["path"], + "required": [ + "path" + ], "additionalProperties": false, "properties": { "path": { @@ -262,7 +295,9 @@ { "type": "object", "description": "Import specification with 'uses'/'with' syntax.", - "required": ["uses"], + "required": [ + "uses" + ], "additionalProperties": false, "properties": { "uses": { @@ -334,10 +369,21 @@ } ], "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"], + [ + "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", @@ -347,7 +393,10 @@ } ], { - "aw": ["shared/common-tools.md", "shared/mcp/tavily.md"] + "aw": [ + "shared/common-tools.md", + "shared/mcp/tavily.md" + ] } ] }, @@ -361,25 +410,45 @@ "pattern": "\\$\\{\\{" } }, - "examples": [["triage-issue.md", "label-issue.md"], ["my-custom-action.yml"], ["shared/helper-action.yml", "close-stale.md"]] + "examples": [ + [ + "triage-issue.md", + "label-issue.md" + ], + [ + "my-custom-action.yml" + ], + [ + "shared/helper-action.yml", + "close-stale.md" + ] + ] }, "inlined-imports": { "type": "boolean", "default": false, "description": "If true, inline all imports (including those without inputs) at compilation time in the generated lock.yml instead of using runtime-import macros. When enabled, the frontmatter hash covers the entire markdown body so any change to the content will invalidate the hash.", - "examples": [true, false] + "examples": [ + true, + false + ] }, "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"] + "types": [ + "opened" + ] } }, { "pull_request": { - "types": ["opened", "synchronize"] + "types": [ + "opened", + "synchronize" + ] } }, "workflow_dispatch", @@ -393,7 +462,13 @@ "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"] + "examples": [ + "push", + "issues", + "workflow_dispatch", + "daily", + "/my-bot" + ] }, { "type": "object", @@ -445,7 +520,16 @@ { "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"] + "enum": [ + "*", + "issues", + "issue_comment", + "pull_request_comment", + "pull_request", + "pull_request_review_comment", + "discussion", + "discussion_comment" + ] }, { "type": "array", @@ -454,7 +538,16 @@ "items": { "type": "string", "description": "GitHub Actions event name.", - "enum": ["*", "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" + ] }, "maxItems": 25 } @@ -511,7 +604,16 @@ { "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"] + "enum": [ + "*", + "issues", + "issue_comment", + "pull_request_comment", + "pull_request", + "pull_request_review_comment", + "discussion", + "discussion_comment" + ] }, { "type": "array", @@ -520,7 +622,16 @@ "items": { "type": "string", "description": "GitHub Actions event name.", - "enum": ["*", "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" + ] }, "maxItems": 25 } @@ -591,7 +702,12 @@ { "type": "string", "description": "Single item type or '*' for all types.", - "enum": ["*", "issues", "pull_request", "discussion"] + "enum": [ + "*", + "issues", + "pull_request", + "discussion" + ] }, { "type": "array", @@ -600,7 +716,12 @@ "items": { "type": "string", "description": "Item type.", - "enum": ["*", "issues", "pull_request", "discussion"] + "enum": [ + "*", + "issues", + "pull_request", + "discussion" + ] }, "maxItems": 3 } @@ -669,25 +790,37 @@ }, "oneOf": [ { - "required": ["branches"], + "required": [ + "branches" + ], "not": { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } }, { - "required": ["branches-ignore"], + "required": [ + "branches-ignore" + ], "not": { - "required": ["branches"] + "required": [ + "branches" + ] } }, { "not": { "anyOf": [ { - "required": ["branches"] + "required": [ + "branches" + ] }, { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } ] } @@ -697,25 +830,37 @@ { "oneOf": [ { - "required": ["paths"], + "required": [ + "paths" + ], "not": { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } }, { - "required": ["paths-ignore"], + "required": [ + "paths-ignore" + ], "not": { - "required": ["paths"] + "required": [ + "paths" + ] } }, { "not": { "anyOf": [ { - "required": ["paths"] + "required": [ + "paths" + ] }, { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } ] } @@ -835,25 +980,37 @@ "additionalProperties": false, "oneOf": [ { - "required": ["branches"], + "required": [ + "branches" + ], "not": { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } }, { - "required": ["branches-ignore"], + "required": [ + "branches-ignore" + ], "not": { - "required": ["branches"] + "required": [ + "branches" + ] } }, { "not": { "anyOf": [ { - "required": ["branches"] + "required": [ + "branches" + ] }, { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } ] } @@ -863,25 +1020,37 @@ { "oneOf": [ { - "required": ["paths"], + "required": [ + "paths" + ], "not": { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } }, { - "required": ["paths-ignore"], + "required": [ + "paths-ignore" + ], "not": { - "required": ["paths"] + "required": [ + "paths" + ] } }, { "not": { "anyOf": [ { - "required": ["paths"] + "required": [ + "paths" + ] }, { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } ] } @@ -900,7 +1069,26 @@ "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"] + "enum": [ + "opened", + "edited", + "deleted", + "transferred", + "pinned", + "unpinned", + "closed", + "reopened", + "assigned", + "unassigned", + "labeled", + "unlabeled", + "locked", + "unlocked", + "milestoned", + "demilestoned", + "typed", + "untyped" + ] } }, "names": { @@ -938,7 +1126,11 @@ "description": "Types of issue comment events", "items": { "type": "string", - "enum": ["created", "edited", "deleted"] + "enum": [ + "created", + "edited", + "deleted" + ] } }, "lock-for-agent": { @@ -957,7 +1149,21 @@ "description": "Types of discussion events", "items": { "type": "string", - "enum": ["created", "edited", "deleted", "transferred", "pinned", "unpinned", "labeled", "unlabeled", "locked", "unlocked", "category_changed", "answered", "unanswered"] + "enum": [ + "created", + "edited", + "deleted", + "transferred", + "pinned", + "unpinned", + "labeled", + "unlabeled", + "locked", + "unlocked", + "category_changed", + "answered", + "unanswered" + ] } } } @@ -972,7 +1178,11 @@ "description": "Types of discussion comment events", "items": { "type": "string", - "enum": ["created", "edited", "deleted"] + "enum": [ + "created", + "edited", + "deleted" + ] } } } @@ -1001,7 +1211,9 @@ "description": "Optional IANA timezone string for timezone-aware scheduling (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'UTC'). When set, the cron expression is interpreted in the specified timezone instead of UTC." } }, - "required": ["cron"], + "required": [ + "cron" + ], "additionalProperties": false }, "maxItems": 10 @@ -1051,7 +1263,13 @@ }, "type": { "type": "string", - "enum": ["string", "choice", "boolean", "number", "environment"], + "enum": [ + "string", + "choice", + "boolean", + "number", + "environment" + ], "description": "Input type. GitHub Actions supports: string (default), boolean, choice (string with predefined options), number, and environment (string referencing a GitHub environment)" }, "options": { @@ -1085,7 +1303,11 @@ "description": "Types of workflow run events", "items": { "type": "string", - "enum": ["completed", "requested", "in_progress"] + "enum": [ + "completed", + "requested", + "in_progress" + ] } }, "branches": { @@ -1107,25 +1329,37 @@ }, "oneOf": [ { - "required": ["branches"], + "required": [ + "branches" + ], "not": { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } }, { - "required": ["branches-ignore"], + "required": [ + "branches-ignore" + ], "not": { - "required": ["branches"] + "required": [ + "branches" + ] } }, { "not": { "anyOf": [ { - "required": ["branches"] + "required": [ + "branches" + ] }, { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } ] } @@ -1142,7 +1376,15 @@ "description": "Types of release events", "items": { "type": "string", - "enum": ["published", "unpublished", "created", "edited", "deleted", "prereleased", "released"] + "enum": [ + "published", + "unpublished", + "created", + "edited", + "deleted", + "prereleased", + "released" + ] } } } @@ -1157,7 +1399,11 @@ "description": "Types of pull request review comment events", "items": { "type": "string", - "enum": ["created", "edited", "deleted"] + "enum": [ + "created", + "edited", + "deleted" + ] } } } @@ -1172,7 +1418,11 @@ "description": "Types of branch protection rule events", "items": { "type": "string", - "enum": ["created", "edited", "deleted"] + "enum": [ + "created", + "edited", + "deleted" + ] } } } @@ -1187,7 +1437,12 @@ "description": "Types of check run events", "items": { "type": "string", - "enum": ["created", "rerequested", "completed", "requested_action"] + "enum": [ + "created", + "rerequested", + "completed", + "requested_action" + ] } } } @@ -1202,7 +1457,9 @@ "description": "Types of check suite events", "items": { "type": "string", - "enum": ["completed"] + "enum": [ + "completed" + ] } } } @@ -1262,13 +1519,31 @@ "oneOf": [ { "type": "string", - "enum": ["error", "failure", "pending", "success", "inactive", "in_progress", "queued", "waiting"] + "enum": [ + "error", + "failure", + "pending", + "success", + "inactive", + "in_progress", + "queued", + "waiting" + ] }, { "type": "array", "items": { "type": "string", - "enum": ["error", "failure", "pending", "success", "inactive", "in_progress", "queued", "waiting"] + "enum": [ + "error", + "failure", + "pending", + "success", + "inactive", + "in_progress", + "queued", + "waiting" + ] }, "minItems": 1 } @@ -1314,7 +1589,11 @@ "description": "Types of label events", "items": { "type": "string", - "enum": ["created", "edited", "deleted"] + "enum": [ + "created", + "edited", + "deleted" + ] } } } @@ -1329,7 +1608,9 @@ "description": "Types of merge group events", "items": { "type": "string", - "enum": ["checks_requested"] + "enum": [ + "checks_requested" + ] } } } @@ -1344,7 +1625,13 @@ "description": "Types of milestone events", "items": { "type": "string", - "enum": ["created", "closed", "opened", "edited", "deleted"] + "enum": [ + "created", + "closed", + "opened", + "edited", + "deleted" + ] } } } @@ -1462,25 +1749,37 @@ "additionalProperties": false, "oneOf": [ { - "required": ["branches"], + "required": [ + "branches" + ], "not": { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } }, { - "required": ["branches-ignore"], + "required": [ + "branches-ignore" + ], "not": { - "required": ["branches"] + "required": [ + "branches" + ] } }, { "not": { "anyOf": [ { - "required": ["branches"] + "required": [ + "branches" + ] }, { - "required": ["branches-ignore"] + "required": [ + "branches-ignore" + ] } ] } @@ -1490,25 +1789,37 @@ { "oneOf": [ { - "required": ["paths"], + "required": [ + "paths" + ], "not": { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } }, { - "required": ["paths-ignore"], + "required": [ + "paths-ignore" + ], "not": { - "required": ["paths"] + "required": [ + "paths" + ] } }, { "not": { "anyOf": [ { - "required": ["paths"] + "required": [ + "paths" + ] }, { - "required": ["paths-ignore"] + "required": [ + "paths-ignore" + ] } ] } @@ -1527,7 +1838,11 @@ "description": "Types of pull request review events", "items": { "type": "string", - "enum": ["submitted", "edited", "dismissed"] + "enum": [ + "submitted", + "edited", + "dismissed" + ] } } } @@ -1542,7 +1857,10 @@ "description": "Types of registry package events", "items": { "type": "string", - "enum": ["published", "updated"] + "enum": [ + "published", + "updated" + ] } } } @@ -1584,7 +1902,9 @@ "description": "Types of watch events", "items": { "type": "string", - "enum": ["started"] + "enum": [ + "started" + ] } } } @@ -1616,7 +1936,11 @@ }, "type": { "type": "string", - "enum": ["string", "number", "boolean"], + "enum": [ + "string", + "number", + "boolean" + ], "description": "Type of the input parameter" }, "default": { @@ -1658,7 +1982,9 @@ }, { "type": "object", - "required": ["query"], + "required": [ + "query" + ], "properties": { "query": { "type": "string", @@ -1680,7 +2006,9 @@ }, "scope": { "type": "string", - "enum": ["none"], + "enum": [ + "none" + ], "description": "Scope for the search query. Set to 'none' to disable the automatic 'repo:owner/repo' scoping, enabling org-wide or cross-repo queries." } }, @@ -1698,7 +2026,9 @@ }, { "type": "object", - "required": ["query"], + "required": [ + "query" + ], "properties": { "query": { "type": "string", @@ -1711,7 +2041,9 @@ }, "scope": { "type": "string", - "enum": ["none"], + "enum": [ + "none" + ], "description": "Scope for the search query. Set to 'none' to disable the automatic 'repo:owner/repo' scoping, enabling org-wide or cross-repo queries." } }, @@ -1729,7 +2061,9 @@ }, { "type": "boolean", - "enum": [true], + "enum": [ + true + ], "description": "Skip workflow execution if any CI checks on the target branch are currently failing. For pull_request events, checks the base branch. For other events, checks the current ref." }, { @@ -1803,7 +2137,15 @@ "oneOf": [ { "type": "string", - "enum": ["admin", "maintainer", "maintain", "write", "triage", "read", "all"], + "enum": [ + "admin", + "maintainer", + "maintain", + "write", + "triage", + "read", + "all" + ], "description": "Single repository permission level that can trigger the workflow. Use 'all' to allow any authenticated user (\u26a0\ufe0f disables permission checking entirely - use with caution)" }, { @@ -1811,7 +2153,14 @@ "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", "read"], + "enum": [ + "admin", + "maintainer", + "maintain", + "write", + "triage", + "read" + ], "description": "Repository permission level: 'admin' (full access), 'maintainer'/'maintain' (repository management), 'write' (push access), 'triage' (issue management), 'read' (read-only access)" }, "minItems": 1, @@ -1854,11 +2203,24 @@ "oneOf": [ { "type": "string", - "enum": ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes", "none"] + "enum": [ + "+1", + "-1", + "laugh", + "confused", + "heart", + "hooray", + "rocket", + "eyes", + "none" + ] }, { "type": "integer", - "enum": [1, -1], + "enum": [ + 1, + -1 + ], "description": "YAML parses +1 and -1 without quotes as integers. These are converted to +1 and -1 strings respectively." }, { @@ -1869,11 +2231,24 @@ "oneOf": [ { "type": "string", - "enum": ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes", "none"] + "enum": [ + "+1", + "-1", + "laugh", + "confused", + "heart", + "hooray", + "rocket", + "eyes", + "none" + ] }, { "type": "integer", - "enum": [1, -1], + "enum": [ + 1, + -1 + ], "description": "YAML parses +1 and -1 without quotes as integers. These are converted to +1 and -1 strings respectively." } ], @@ -1960,7 +2335,9 @@ "github-token": { "type": "string", "description": "Custom GitHub token for pre-activation reactions, activation status comments, and skip-if search queries. When specified, overrides the default GITHUB_TOKEN for these operations.", - "examples": ["${{ secrets.MY_GITHUB_TOKEN }}"] + "examples": [ + "${{ secrets.MY_GITHUB_TOKEN }}" + ] }, "github-app": { "$ref": "#/$defs/github_app", @@ -1982,7 +2359,11 @@ "additionalItems": false, "uniqueItems": true, "default": [], - "examples": [["secrets_fetcher"]] + "examples": [ + [ + "secrets_fetcher" + ] + ] }, "steps": { "type": "array", @@ -2094,51 +2475,99 @@ "properties": { "actions": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "checks": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "contents": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "deployments": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "discussions": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "issues": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "packages": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "pages": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "pull-requests": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "repository-projects": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "security-events": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] }, "statuses": { "type": "string", - "enum": ["read", "write", "none"] + "enum": [ + "read", + "write", + "none" + ] } }, "additionalProperties": false @@ -2181,25 +2610,37 @@ { "command": { "name": "mergefest", - "events": ["pull_request_comment"] + "events": [ + "pull_request_comment" + ] } }, { "workflow_run": { - "workflows": ["Dev"], - "types": ["completed"], - "branches": ["copilot/**"] + "workflows": [ + "Dev" + ], + "types": [ + "completed" + ], + "branches": [ + "copilot/**" + ] } }, { "pull_request": { - "types": ["ready_for_review"] + "types": [ + "ready_for_review" + ] }, "workflow_dispatch": null }, { "push": { - "branches": ["main"] + "branches": [ + "main" + ] } } ] @@ -2226,7 +2667,10 @@ "oneOf": [ { "type": "string", - "enum": ["read-all", "write-all"], + "enum": [ + "read-all", + "write-all" + ], "description": "Simple permissions string: 'read-all' (all read permissions) or 'write-all' (all write permissions)" }, { @@ -2237,7 +2681,10 @@ "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 }}"] + "examples": [ + "Deploy to ${{ github.event.inputs.environment }}", + "Build #${{ github.run_number }}" + ] }, "jobs": { "type": "object", @@ -2280,10 +2727,14 @@ "additionalProperties": false, "oneOf": [ { - "required": ["uses"] + "required": [ + "uses" + ] }, { - "required": ["run"] + "required": [ + "run" + ] } ], "properties": { @@ -2503,7 +2954,9 @@ "description": "The URL to set as the environment URL in the deployment." } }, - "required": ["name"] + "required": [ + "name" + ] } ], "description": "The GitHub Actions environment this job references. When set, any protection rules for the environment must pass before the job runs. Use this to gate jobs on manual approval workflows." @@ -2616,17 +3069,26 @@ ], "examples": [ "ubuntu-latest", - ["ubuntu-latest", "self-hosted"], + [ + "ubuntu-latest", + "self-hosted" + ], { "group": "larger-runners", - "labels": ["ubuntu-latest-8-cores"] + "labels": [ + "ubuntu-latest-8-cores" + ] } ] }, "runs-on-slim": { "type": "string", "description": "Runner for all framework/generated jobs (activation, pre-activation, safe-outputs, unlock, APM, etc.). Provides a compile-stable override for generated job runners without requiring a safe-outputs section. Overridden by safe-outputs.runs-on when both are set. Defaults to 'ubuntu-slim'. Use this when your infrastructure does not provide the default runner or when you need consistent runner selection across all jobs.", - "examples": ["self-hosted", "ubuntu-latest", "ubuntu-22.04"] + "examples": [ + "self-hosted", + "ubuntu-latest", + "ubuntu-22.04" + ] }, "timeout-minutes": { "description": "Workflow timeout in minutes (GitHub Actions standard field). Defaults to 20 minutes for agentic workflows. Has sensible defaults and can typically be omitted. Custom runners support longer timeouts beyond the GitHub-hosted runner limit. Supports GitHub Actions expressions (e.g. '${{ inputs.timeout }}') for reusable workflow_call workflows.", @@ -2634,7 +3096,11 @@ { "type": "integer", "minimum": 1, - "examples": [5, 10, 30] + "examples": [ + 5, + 10, + 30 + ] }, { "type": "string", @@ -2649,7 +3115,10 @@ { "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 }}"] + "examples": [ + "my-workflow-group", + "workflow-${{ github.ref }}" + ] }, { "type": "object", @@ -2667,7 +3136,11 @@ "job-discriminator": { "type": "string", "description": "Additional discriminator expression appended to compiler-generated job-level concurrency groups (agent, output jobs). Use this when multiple workflow instances are dispatched concurrently with different inputs (fan-out pattern) to prevent job-level concurrency groups from colliding. For example, '${{ inputs.finding_id }}' ensures each dispatched run gets a unique job-level group. Supports GitHub Actions expressions. This field is stripped from the compiled lock file (it is a gh-aw extension, not a GitHub Actions field).", - "examples": ["${{ inputs.finding_id }}", "${{ inputs.item_id }}", "${{ github.run_id }}"] + "examples": [ + "${{ inputs.finding_id }}", + "${{ inputs.item_id }}", + "${{ github.run_id }}" + ] } }, "required": [], @@ -2739,29 +3212,45 @@ }, "additionalProperties": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "minItems": 2, "description": "Array of variant values for this experiment. Must contain at least two variants." }, "examples": [ { - "feature1": ["A", "B"] + "feature1": [ + "A", + "B" + ] }, { - "prompt_style": ["concise", "detailed", "structured"], - "model_temp": ["low", "high"] + "prompt_style": [ + "concise", + "detailed", + "structured" + ], + "model_temp": [ + "low", + "high" + ] } ] }, "infer": { "type": "boolean", "description": "DEPRECATED: Use 'disable-model-invocation' instead. Controls whether the custom agent should infer additional context from the conversation. This field is maintained for backward compatibility with existing custom agent files.", - "examples": [false] + "examples": [ + false + ] }, "disable-model-invocation": { "type": "boolean", "description": "Controls whether the custom agent should disable model invocation. When set to true, the agent will not make additional model calls. This is the preferred field name for custom agent files (replaces the deprecated 'infer' field).", - "examples": [true] + "examples": [ + true + ] }, "secrets": { "description": "Secret values passed to workflow execution. Secrets can be defined as simple strings (GitHub Actions expressions) or objects with 'value' and 'description' properties. Typically used to provide secrets to MCP servers or custom engines. Note: For passing secrets to reusable workflows, use the jobs..secrets field instead.", @@ -2775,7 +3264,9 @@ { "type": "object", "description": "Secret with metadata", - "required": ["value"], + "required": [ + "value" + ], "properties": { "value": { "type": "string", @@ -2827,7 +3318,9 @@ "description": "A deployment URL" } }, - "required": ["name"], + "required": [ + "name" + ], "additionalProperties": false } ] @@ -2895,7 +3388,9 @@ "description": "Additional Docker container options" } }, - "required": ["image"], + "required": [ + "image" + ], "additionalProperties": false } ] @@ -2965,7 +3460,9 @@ "description": "Additional Docker container options" } }, - "required": ["image"], + "required": [ + "image" + ], "additionalProperties": false } ] @@ -2977,16 +3474,26 @@ "examples": [ "defaults", { - "allowed": ["defaults", "github"] + "allowed": [ + "defaults", + "github" + ] }, { - "allowed": ["defaults", "python", "node", "*.example.com"] + "allowed": [ + "defaults", + "python", + "node", + "*.example.com" + ] } ], "oneOf": [ { "type": "string", - "enum": ["defaults"], + "enum": [ + "defaults" + ], "description": "Use default network permissions (basic infrastructure: certificates, JSON schema, Ubuntu, etc.)" }, { @@ -3021,7 +3528,10 @@ "oneOf": [ { "type": "string", - "enum": ["default", "awf"], + "enum": [ + "default", + "awf" + ], "description": "String format for sandbox type: 'default' for no sandbox, 'awf' for Agent Workflow Firewall. Note: Legacy 'srt' and 'sandbox-runtime' values are automatically migrated to 'awf'" }, { @@ -3030,7 +3540,10 @@ "properties": { "type": { "type": "string", - "enum": ["default", "awf"], + "enum": [ + "default", + "awf" + ], "description": "Legacy sandbox type field (use agent instead). Note: Legacy 'srt' and 'sandbox-runtime' values are automatically migrated to 'awf'" }, "agent": { @@ -3044,7 +3557,9 @@ }, { "type": "string", - "enum": ["awf"], + "enum": [ + "awf" + ], "description": "Sandbox type: 'awf' for Agent Workflow Firewall" }, { @@ -3053,12 +3568,16 @@ "properties": { "id": { "type": "string", - "enum": ["awf"], + "enum": [ + "awf" + ], "description": "Agent identifier (replaces 'type' field in new format): 'awf' for Agent Workflow Firewall" }, "type": { "type": "string", - "enum": ["awf"], + "enum": [ + "awf" + ], "description": "Legacy: Sandbox type to use (use 'id' instead)" }, "version": { @@ -3094,13 +3613,22 @@ "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"]] + "examples": [ + [ + "/host/data:/data:ro", + "/usr/local/bin/custom-tool:/usr/local/bin/custom-tool:ro" + ] + ] }, "memory": { "type": "string", "description": "Memory limit for the AWF container (e.g., '4g', '8g'). Passed as --memory-limit to AWF. If not specified, AWF's default memory limit is used.", "pattern": "^[0-9]+(b|k|m|g|kb|mb|gb|B|K|M|G|KB|MB|GB)$", - "examples": ["4g", "8g", "512m"] + "examples": [ + "4g", + "8g", + "512m" + ] }, "config": { "type": "object", @@ -3216,16 +3744,26 @@ "description": "Container image for the MCP gateway executable (required)" }, "version": { - "type": ["string", "number"], + "type": [ + "string", + "number" + ], "x-internal": true, "description": "Optional version/tag for the container image (e.g., 'latest', 'v1.0.0')", - "examples": ["latest", "v1.0.0"] + "examples": [ + "latest", + "v1.0.0" + ] }, "entrypoint": { "type": "string", "x-internal": true, "description": "Optional custom entrypoint for the MCP gateway container. Overrides the container's default entrypoint.", - "examples": ["/bin/bash", "/custom/start.sh", "/usr/bin/env"] + "examples": [ + "/bin/bash", + "/custom/start.sh", + "/usr/bin/env" + ] }, "args": { "type": "array", @@ -3251,7 +3789,12 @@ "pattern": "^[^:]+:[^:]+:(ro|rw)$", "description": "Mount specification in format 'source:destination:mode'" }, - "examples": [["/host/data:/container/data:ro", "/host/config:/container/config:rw"]] + "examples": [ + [ + "/host/data:/container/data:ro", + "/host/config:/container/config:rw" + ] + ] }, "env": { "type": "object", @@ -3276,14 +3819,22 @@ }, "domain": { "type": "string", - "enum": ["localhost", "host.docker.internal"], + "enum": [ + "localhost", + "host.docker.internal" + ], "description": "Gateway domain for URL generation (default: 'host.docker.internal' when agent is enabled, 'localhost' when disabled)" }, "keepalive-interval": { "type": "integer", "description": "Keepalive ping interval in seconds for HTTP MCP backends. Sends periodic pings to prevent session expiry during long-running agent tasks. Set to -1 to disable keepalive pings. Unset or 0 uses the gateway default (1500 seconds = 25 minutes).", "minimum": -1, - "examples": [-1, 300, 600, 1500] + "examples": [ + -1, + 300, + 600, + 1500 + ] } }, "additionalProperties": false @@ -3316,7 +3867,10 @@ "if": { "type": "string", "description": "Conditional execution expression", - "examples": ["${{ github.event.workflow_run.event == 'workflow_dispatch' }}", "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}"] + "examples": [ + "${{ github.event.workflow_run.event == 'workflow_dispatch' }}", + "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}" + ] }, "steps": { "description": "Custom workflow steps", @@ -3500,7 +4054,10 @@ "filesystem": { "type": "stdio", "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem"] + "args": [ + "-y", + "@modelcontextprotocol/server-filesystem" + ] } }, { @@ -3577,18 +4134,33 @@ }, "mode": { "type": "string", - "enum": ["gh-proxy", "local", "remote"], + "enum": [ + "gh-proxy", + "local", + "remote" + ], "description": "GitHub access mode. Prefer 'gh-proxy' for better performance (uses pre-authenticated gh CLI prompt guidance). Legacy MCP transport values 'local' and 'remote' are accepted for backward compatibility and use GitHub MCP server prompt guidance." }, "type": { "type": "string", - "enum": ["local", "remote"], + "enum": [ + "local", + "remote" + ], "description": "GitHub MCP transport type: 'local' (Docker-based, default) or 'remote' (hosted at api.githubcopilot.com)" }, "version": { - "type": ["string", "number"], + "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] + "examples": [ + "v1.0.0", + "latest", + 20, + 3.11 + ] }, "args": { "type": "array", @@ -3661,14 +4233,25 @@ "pattern": "^[^:]+:[^:]+(:(ro|rw))?$", "description": "Mount specification in format 'host:container:mode'" }, - "examples": [["/data:/data:ro", "/tmp:/tmp:rw"], ["/opt:/opt:ro"]] + "examples": [ + [ + "/data:/data:ro", + "/tmp:/tmp:rw" + ], + [ + "/opt:/opt:ro" + ] + ] }, "allowed-repos": { "description": "Guard policy: repository access configuration. Restricts which repositories the agent can access. Use 'all' to allow all repos, 'public' for public repositories only, or an array of repository patterns (e.g., 'owner/repo', 'owner/*', 'owner/prefix*').", "oneOf": [ { "type": "string", - "enum": ["all", "public"], + "enum": [ + "all", + "public" + ], "description": "Allow access to all repositories ('all') or only public repositories ('public')" }, { @@ -3688,7 +4271,10 @@ "oneOf": [ { "type": "string", - "enum": ["all", "public"], + "enum": [ + "all", + "public" + ], "description": "Allow access to all repositories ('all') or only public repositories ('public')" }, { @@ -3705,7 +4291,12 @@ "min-integrity": { "type": "string", "description": "Guard policy: minimum required integrity level for repository access. Restricts the agent to users with at least the specified permission level.", - "enum": ["none", "unapproved", "approved", "merged"] + "enum": [ + "none", + "unapproved", + "approved", + "merged" + ] }, "blocked-users": { "description": "Guard policy: GitHub usernames whose content is unconditionally blocked. Items from these users receive 'blocked' integrity (below 'none') and are always denied, even when 'min-integrity' is 'none'. Cannot be overridden by 'approval-labels'. Requires 'min-integrity' to be set. Accepts an array of usernames, a comma-separated string, a newline-separated string, or a GitHub Actions expression (e.g. '${{ vars.BLOCKED_USERS }}').", @@ -3767,10 +4358,27 @@ "items": { "type": "string", "description": "GitHub ReactionContent enum value", - "enum": ["THUMBS_UP", "THUMBS_DOWN", "HEART", "HOORAY", "CONFUSED", "ROCKET", "EYES", "LAUGH"] + "enum": [ + "THUMBS_UP", + "THUMBS_DOWN", + "HEART", + "HOORAY", + "CONFUSED", + "ROCKET", + "EYES", + "LAUGH" + ] }, - "default": ["THUMBS_UP", "HEART"], - "examples": [["THUMBS_UP", "HEART"]] + "default": [ + "THUMBS_UP", + "HEART" + ], + "examples": [ + [ + "THUMBS_UP", + "HEART" + ] + ] }, "disapproval-reactions": { "type": "array", @@ -3778,21 +4386,47 @@ "items": { "type": "string", "description": "GitHub ReactionContent enum value", - "enum": ["THUMBS_UP", "THUMBS_DOWN", "HEART", "HOORAY", "CONFUSED", "ROCKET", "EYES", "LAUGH"] + "enum": [ + "THUMBS_UP", + "THUMBS_DOWN", + "HEART", + "HOORAY", + "CONFUSED", + "ROCKET", + "EYES", + "LAUGH" + ] }, - "default": ["THUMBS_DOWN", "CONFUSED"], - "examples": [["THUMBS_DOWN", "CONFUSED"]] + "default": [ + "THUMBS_DOWN", + "CONFUSED" + ], + "examples": [ + [ + "THUMBS_DOWN", + "CONFUSED" + ] + ] }, "disapproval-integrity": { "type": "string", "description": "Guard policy: integrity level assigned when a disapproval reaction is present. Optional, defaults to 'none'. Requires the 'integrity-reactions' feature flag and MCPG >= v0.2.18.", - "enum": ["none", "unapproved", "approved", "merged"], + "enum": [ + "none", + "unapproved", + "approved", + "merged" + ], "default": "none" }, "endorser-min-integrity": { "type": "string", "description": "Guard policy: minimum integrity level required for an endorser (reactor) to promote content. Optional, defaults to 'approved'. Requires the 'integrity-reactions' feature flag and MCPG >= v0.2.18.", - "enum": ["unapproved", "approved", "merged"], + "enum": [ + "unapproved", + "approved", + "merged" + ], "default": "approved" }, "github-app": { @@ -3803,16 +4437,30 @@ "additionalProperties": false, "examples": [ { - "toolsets": ["pull_requests", "actions", "repos"] + "toolsets": [ + "pull_requests", + "actions", + "repos" + ] }, { - "allowed": ["search_pull_requests", "pull_request_read", "list_pull_requests", "get_file_contents", "list_commits", "get_commit"] + "allowed": [ + "search_pull_requests", + "pull_request_read", + "list_pull_requests", + "get_file_contents", + "list_commits", + "get_commit" + ] }, { "read-only": true }, { - "toolsets": ["pull_requests", "repos"] + "toolsets": [ + "pull_requests", + "repos" + ] } ] } @@ -3820,14 +4468,25 @@ "examples": [ null, { - "toolsets": ["pull_requests", "actions", "repos"] + "toolsets": [ + "pull_requests", + "actions", + "repos" + ] }, { - "allowed": ["search_pull_requests", "pull_request_read", "get_file_contents"] + "allowed": [ + "search_pull_requests", + "pull_request_read", + "get_file_contents" + ] }, { "read-only": true, - "toolsets": ["repos", "issues"] + "toolsets": [ + "repos", + "issues" + ] }, false ] @@ -3854,10 +4513,36 @@ ], "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"] + [ + "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": { @@ -3934,9 +4619,16 @@ "description": "Playwright tool configuration with custom version and arguments", "properties": { "version": { - "type": ["string", "number"], + "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] + "examples": [ + "v1.41.0", + 1.41, + 20 + ] }, "args": { "type": "array", @@ -3962,7 +4654,10 @@ "description": "Enable agentic-workflows tool with default settings (same as true)" } ], - "examples": [true, null] + "examples": [ + true, + null + ] }, "cache-memory": { "description": "Cache memory MCP configuration for persistent memory storage", @@ -3999,7 +4694,10 @@ }, "scope": { "type": "string", - "enum": ["workflow", "repo"], + "enum": [ + "workflow", + "repo" + ], "default": "workflow", "description": "Cache restore key scope: 'workflow' (default, only restores from same workflow) or 'repo' (restores from any workflow in the repository). Use 'repo' with caution as it allows cross-workflow cache sharing." }, @@ -4052,7 +4750,10 @@ }, "scope": { "type": "string", - "enum": ["workflow", "repo"], + "enum": [ + "workflow", + "repo" + ], "default": "workflow", "description": "Cache restore key scope: 'workflow' (default, only restores from same workflow) or 'repo' (restores from any workflow in the repository). Use 'repo' with caution as it allows cross-workflow cache sharing." }, @@ -4064,7 +4765,10 @@ "description": "List of allowed file extensions (e.g., [\".json\", \".txt\"]). Default: [\".json\", \".jsonl\", \".txt\", \".md\", \".csv\"]" } }, - "required": ["id", "key"], + "required": [ + "id", + "key" + ], "additionalProperties": false }, "minItems": 1, @@ -4155,7 +4859,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -4176,7 +4883,11 @@ { "type": "integer", "minimum": 1, - "examples": [60, 120, 300] + "examples": [ + 60, + 120, + 300 + ] }, { "type": "string", @@ -4191,7 +4902,11 @@ { "type": "integer", "minimum": 1, - "examples": [30, 60, 120] + "examples": [ + 30, + 60, + 120 + ] }, { "type": "string", @@ -4203,7 +4918,9 @@ "cli-proxy": { "type": "boolean", "description": "When true, each user-facing MCP server is mounted as a standalone CLI tool on PATH. The agent can then call MCP servers via shell commands (e.g. 'github issue_read --method get ...'). CLI-mounted servers remain in the MCP gateway config so their containers can start, and are removed only from the agent's final config during convert_gateway_config_*.sh processing. Default: false.", - "examples": [true] + "examples": [ + true + ] }, "serena": { "description": "REMOVED: Built-in support for Serena has been removed. Use the shared/mcp/serena.md workflow instead.", @@ -4490,17 +5207,25 @@ "description": "Optional custom name for the cache step (overrides auto-generated name)" } }, - "required": ["key", "path"], + "required": [ + "key", + "path" + ], "additionalProperties": false, "examples": [ { "key": "node-modules-${{ hashFiles('package-lock.json') }}", "path": "node_modules", - "restore-keys": ["node-modules-"] + "restore-keys": [ + "node-modules-" + ] }, { "key": "build-cache-${{ github.sha }}", - "path": ["dist", ".cache"], + "path": [ + "dist", + ".cache" + ], "restore-keys": "build-cache-", "fail-on-cache-miss": false } @@ -4565,7 +5290,10 @@ "description": "Optional custom name for the cache step (overrides auto-generated name)" } }, - "required": ["key", "path"], + "required": [ + "key", + "path" + ], "additionalProperties": false } } @@ -4573,19 +5301,24 @@ }, "safe-outputs": { "type": "object", - "$comment": "Required if workflow creates or modifies GitHub resources. Operations requiring safe-outputs: autofix-code-scanning-alert, add-comment, add-labels, add-reviewer, assign-milestone, assign-to-agent, assign-to-user, close-discussion, close-issue, close-pull-request, create-agent-session, create-agent-task (deprecated, use create-agent-session), create-code-scanning-alert, create-discussion, create-issue, create-project, create-project-status-update, create-pull-request, create-pull-request-review-comment, dispatch-workflow, hide-comment, link-sub-issue, mark-pull-request-as-ready-for-review, merge-pull-request, missing-data, missing-tool, noop, push-to-pull-request-branch, remove-labels, reply-to-pull-request-review-comment, resolve-pull-request-review-thread, set-issue-type, submit-pull-request-review, threat-detection, unassign-from-user, update-discussion, update-issue, update-project, update-pull-request, update-release, upload-artifact, upload-asset. See documentation for complete details.", + "$comment": "Required if workflow creates or modifies GitHub resources. Operations requiring safe-outputs: autofix-code-scanning-alert, add-comment, add-labels, add-reviewer, assign-milestone, assign-to-agent, assign-to-user, close-discussion, close-issue, close-pull-request, create-agent-session, create-agent-task (deprecated, use create-agent-session), create-code-scanning-alert, create-discussion, create-issue, create-project, create-project-status-update, create-pull-request, create-pull-request-review-comment, dispatch-workflow, hide-comment, link-sub-issue, mark-pull-request-as-ready-for-review, merge-pull-request, missing-data, missing-tool, noop, edit-wiki, push-to-pull-request-branch, remove-labels, reply-to-pull-request-review-comment, resolve-pull-request-review-thread, set-issue-type, submit-pull-request-review, threat-detection, unassign-from-user, update-discussion, update-issue, update-project, update-pull-request, update-release, upload-artifact, 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"] + "labels": [ + "automation", + "ai-generated" + ] } }, { "create-pull-request": { "title-prefix": "[Bot] ", - "labels": ["bot"] + "labels": [ + "bot" + ] } }, { @@ -4607,7 +5340,23 @@ "items": { "type": "string" }, - "examples": [["repo"], ["repo", "octocat/hello-world"], ["microsoft/vscode", "microsoft/typescript"], ["repo", "${{ github.repository }}"]] + "examples": [ + [ + "repo" + ], + [ + "repo", + "octocat/hello-world" + ], + [ + "microsoft/vscode", + "microsoft/typescript" + ], + [ + "repo", + "${{ github.repository }}" + ] + ] }, "create-issue": { "oneOf": [ @@ -4689,7 +5438,9 @@ }, { "type": "boolean", - "enum": [false], + "enum": [ + false + ], "description": "Set to false to explicitly disable expiration" } ], @@ -4728,28 +5479,43 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, "examples": [ { "title-prefix": "[ca] ", - "labels": ["automation", "dependencies"], + "labels": [ + "automation", + "dependencies" + ], "assignees": "copilot" }, { "title-prefix": "[duplicate-code] ", - "labels": ["code-quality", "automated-analysis"], + "labels": [ + "code-quality", + "automated-analysis" + ], "assignees": "copilot" }, { - "allowed-repos": ["org/other-repo", "org/another-repo"], + "allowed-repos": [ + "org/other-repo", + "org/another-repo" + ], "title-prefix": "[cross-repo] " }, { "title-prefix": "[weekly-report] ", - "labels": ["report", "automation"], + "labels": [ + "report", + "automation" + ], "close-older-issues": true } ] @@ -4805,7 +5571,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -4860,7 +5629,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -4877,7 +5649,9 @@ { "type": "object", "description": "Configuration for managing GitHub Projects boards. Enable agents to add issues and pull requests to projects, update custom field values (status, priority, effort, dates), create project fields and views. By default it is update-only: if the project does not exist, the job fails with instructions to create it. To allow workflows to create missing projects, explicitly opt in via agent output field create_if_missing=true. Requires a Personal Access Token (PAT) or GitHub App token with Projects permissions (default GITHUB_TOKEN cannot be used). Agent output includes: project (full URL or temporary project ID like aw_XXXXXXXXXXXX or #aw_XXXXXXXXXXXX from create_project), content_type (issue|pull_request|draft_issue), content_number, fields, create_if_missing. For specialized operations, agent can also provide: operation (create_fields|create_view), field_definitions (array of field configs when operation=create_fields), view (view config object when operation=create_view).", - "required": ["project"], + "required": [ + "project" + ], "properties": { "max": { "description": "Maximum number of project operations to perform (default: 10). Each operation may add a project item, or update its fields. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -4902,7 +5676,10 @@ "type": "string", "description": "Target project URL for update-project operations. This is required in the configuration for documentation purposes. Agent messages MUST explicitly include the project field in their output - the configured value is not used as a fallback. Must be a valid GitHub Projects v2 URL.", "pattern": "^https://github\\.com/(users|orgs)/([^/]+|<[A-Z_]+>)/projects/(\\d+|<[A-Z_]+>)$", - "examples": ["https://github.com/orgs/myorg/projects/123", "https://github.com/users/username/projects/456"] + "examples": [ + "https://github.com/orgs/myorg/projects/123", + "https://github.com/users/username/projects/456" + ] }, "target-repo": { "description": "Default repository in format 'owner/repo' for cross-repository content resolution. When specified, the agent can use 'target_repo' in agent output to resolve issues or PRs from this repository. Wildcards ('*') are not allowed. Supports GitHub Actions expression syntax (e.g., '${{ vars.TARGET_REPO }}').", @@ -4941,7 +5718,10 @@ "items": { "type": "object", "description": "View configuration for creating project views", - "required": ["name", "layout"], + "required": [ + "name", + "layout" + ], "properties": { "name": { "type": "string", @@ -4949,7 +5729,11 @@ }, "layout": { "type": "string", - "enum": ["table", "board", "roadmap"], + "enum": [ + "table", + "board", + "roadmap" + ], "description": "The layout type of the view" }, "filter": { @@ -4976,7 +5760,10 @@ "description": "Optional array of project custom fields to create up-front.", "items": { "type": "object", - "required": ["name", "data-type"], + "required": [ + "name", + "data-type" + ], "properties": { "name": { "type": "string", @@ -4984,7 +5771,13 @@ }, "data-type": { "type": "string", - "enum": ["DATE", "TEXT", "NUMBER", "SINGLE_SELECT", "ITERATION"], + "enum": [ + "DATE", + "TEXT", + "NUMBER", + "SINGLE_SELECT", + "ITERATION" + ], "description": "The GitHub Projects v2 custom field type" }, "options": { @@ -5001,7 +5794,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5061,7 +5857,10 @@ "items": { "type": "object", "description": "View configuration for creating project views", - "required": ["name", "layout"], + "required": [ + "name", + "layout" + ], "properties": { "name": { "type": "string", @@ -5069,7 +5868,11 @@ }, "layout": { "type": "string", - "enum": ["table", "board", "roadmap"], + "enum": [ + "table", + "board", + "roadmap" + ], "description": "The layout type of the view" }, "filter": { @@ -5096,7 +5899,10 @@ "description": "Optional array of project custom fields to create automatically after project creation.", "items": { "type": "object", - "required": ["name", "data-type"], + "required": [ + "name", + "data-type" + ], "properties": { "name": { "type": "string", @@ -5104,7 +5910,13 @@ }, "data-type": { "type": "string", - "enum": ["DATE", "TEXT", "NUMBER", "SINGLE_SELECT", "ITERATION"], + "enum": [ + "DATE", + "TEXT", + "NUMBER", + "SINGLE_SELECT", + "ITERATION" + ], "description": "The GitHub Projects v2 custom field type" }, "options": { @@ -5121,7 +5933,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -5141,7 +5956,9 @@ { "type": "object", "description": "Configuration for posting status updates to GitHub Projects. Status updates provide stakeholder communication about project progress, health, and timeline. Each update appears in the project's Updates tab and creates a historical record. Requires a Personal Access Token (PAT) or GitHub App token with Projects read & write permission (default GITHUB_TOKEN cannot be used). Typically used by scheduled workflows or orchestrators to post regular progress summaries with status indicators (on-track, at-risk, off-track, complete, inactive), dates, and progress details.", - "required": ["project"], + "required": [ + "project" + ], "properties": { "max": { "description": "Maximum number of status updates to create (default: 1). Typically 1 per orchestrator run. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -5166,12 +5983,18 @@ "type": "string", "description": "Target project URL for status update operations. This is required in the configuration for documentation purposes. Agent messages MUST explicitly include the project field in their output - the configured value is not used as a fallback. Must be a valid GitHub Projects v2 URL.", "pattern": "^https://github\\.com/(users|orgs)/([^/]+|<[A-Z_]+>)/projects/(\\d+|<[A-Z_]+>)$", - "examples": ["https://github.com/orgs/myorg/projects/123", "https://github.com/users/username/projects/456"] + "examples": [ + "https://github.com/orgs/myorg/projects/123", + "https://github.com/users/username/projects/456" + ] }, "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5203,9 +6026,16 @@ "description": "Optional prefix for the discussion title" }, "category": { - "type": ["string", "number"], + "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] + "examples": [ + "General", + "audits", + 123456789 + ] }, "labels": { "type": "array", @@ -5282,7 +6112,9 @@ }, { "type": "boolean", - "enum": [false], + "enum": [ + false + ], "description": "Set to false to explicitly disable expiration" } ], @@ -5296,7 +6128,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5318,12 +6153,17 @@ "close-older-discussions": true }, { - "labels": ["weekly-report", "automation"], + "labels": [ + "weekly-report", + "automation" + ], "category": "reports", "close-older-discussions": true }, { - "allowed-repos": ["org/other-repo"], + "allowed-repos": [ + "org/other-repo" + ], "category": "General" } ] @@ -5382,7 +6222,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5391,7 +6234,10 @@ "required-category": "Ideas" }, { - "required-labels": ["resolved", "completed"], + "required-labels": [ + "resolved", + "completed" + ], "max": 1 } ] @@ -5459,7 +6305,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] }, "github-token": { "$ref": "#/$defs/github_token", @@ -5525,11 +6374,18 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] }, "state-reason": { "type": "string", - "enum": ["completed", "not_planned", "duplicate"], + "enum": [ + "completed", + "not_planned", + "duplicate" + ], "default": "completed", "description": "Reason for closing the issue (default: completed)" } @@ -5540,7 +6396,10 @@ "required-title-prefix": "[refactor] " }, { - "required-labels": ["automated", "stale"], + "required-labels": [ + "automated", + "stale" + ], "max": 10 } ] @@ -5599,7 +6458,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5608,7 +6470,10 @@ "required-title-prefix": "[bot] " }, { - "required-labels": ["automated", "outdated"], + "required-labels": [ + "automated", + "outdated" + ], "max": 5 } ] @@ -5667,7 +6532,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5676,7 +6544,10 @@ "required-title-prefix": "[bot] " }, { - "required-labels": ["automated", "ready"], + "required-labels": [ + "automated", + "ready" + ], "max": 1 } ] @@ -5743,7 +6614,14 @@ "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, low_quality).", "items": { "type": "string", - "enum": ["spam", "abuse", "off_topic", "outdated", "resolved", "low_quality"] + "enum": [ + "spam", + "abuse", + "off_topic", + "outdated", + "resolved", + "low_quality" + ] } }, "discussions": { @@ -5770,7 +6648,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, @@ -5907,7 +6788,11 @@ }, "if-no-changes": { "type": "string", - "enum": ["warn", "error", "ignore"], + "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": { @@ -6007,7 +6892,11 @@ "oneOf": [ { "type": "string", - "enum": ["blocked", "allowed", "fallback-to-issue"], + "enum": [ + "blocked", + "allowed", + "fallback-to-issue" + ], "description": "Controls protected-file protection. blocked (default): hard-block any patch that modifies package manifests (e.g. package.json, go.mod), engine instruction files (e.g. AGENTS.md, CLAUDE.md) or .github/ files. allowed: allow all changes. fallback-to-issue: push the branch but create a review issue instead of a PR, so a human can review the manifest changes before merging.", "default": "blocked" }, @@ -6023,7 +6912,11 @@ "oneOf": [ { "type": "string", - "enum": ["blocked", "allowed", "fallback-to-issue"], + "enum": [ + "blocked", + "allowed", + "fallback-to-issue" + ], "description": "Protection policy. blocked (default): hard-block any patch that modifies protected files. allowed: allow all changes. fallback-to-issue: push the branch but create a review issue instead of a PR.", "default": "blocked" }, @@ -6040,7 +6933,15 @@ "type": "string" }, "description": "List of filenames or path prefixes to remove from the default protected-file set. Items are matched by basename (e.g. \"AGENTS.md\") or path prefix (e.g. \".agents/\"). Use this to allow the agent to modify specific files that are otherwise blocked by default.", - "examples": [["AGENTS.md"], ["AGENTS.md", ".agents/"]] + "examples": [ + [ + "AGENTS.md" + ], + [ + "AGENTS.md", + ".agents/" + ] + ] } }, "additionalProperties": false, @@ -6077,7 +6978,10 @@ "oneOf": [ { "type": "string", - "enum": ["am", "bundle"], + "enum": [ + "am", + "bundle" + ], "default": "am", "description": "Transport format for packaging changes. \"am\" (default) uses git format-patch/git am. \"bundle\" uses git bundle, which preserves merge commit topology, per-commit authorship, and merge-resolution-only content." }, @@ -6092,26 +6996,38 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] }, "allow-workflows": { "type": "boolean", "description": "When true, adds workflows: write to the GitHub App token permissions. Required when allowed-files targets .github/workflows/ paths. Requires safe-outputs.github-app to be configured because the workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.", "default": false, - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false, "examples": [ { "title-prefix": "[docs] ", - "labels": ["documentation", "automation"], + "labels": [ + "documentation", + "automation" + ], "reviewers": "copilot", "draft": false }, { "title-prefix": "[security-fix] ", - "labels": ["security", "automated-fix"], + "labels": [ + "security", + "automated-fix" + ], "reviewers": "copilot" } ] @@ -6147,7 +7063,10 @@ "side": { "type": "string", "description": "Side of the diff for comments: 'LEFT' or 'RIGHT' (default: 'RIGHT')", - "enum": ["LEFT", "RIGHT"] + "enum": [ + "LEFT", + "RIGHT" + ] }, "target": { "type": "string", @@ -6171,7 +7090,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6212,7 +7134,11 @@ }, { "type": "string", - "enum": ["always", "none", "if-body"], + "enum": [ + "always", + "none", + "if-body" + ], "description": "Controls when AI-generated footer is added to the review body: 'always' (default), 'none' (never), or 'if-body' (only when review has body text)." } ], @@ -6237,7 +7163,11 @@ "type": "array", "items": { "type": "string", - "enum": ["APPROVE", "COMMENT", "REQUEST_CHANGES"] + "enum": [ + "APPROVE", + "COMMENT", + "REQUEST_CHANGES" + ] }, "description": "Optional list of allowed review event types. If omitted, all event types (APPROVE, COMMENT, REQUEST_CHANGES) are allowed. Use this to restrict the agent to specific event types, e.g. [COMMENT, REQUEST_CHANGES] to prevent approvals.", "minItems": 1 @@ -6253,7 +7183,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6313,7 +7246,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6353,7 +7289,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6407,7 +7346,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6446,7 +7388,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6522,7 +7467,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6594,7 +7542,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6666,7 +7617,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6718,7 +7672,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6774,7 +7731,10 @@ ] }, "target": { - "type": ["string", "number"], + "type": [ + "string", + "number" + ], "description": "Target issue/PR to assign agents to. Use 'triggering' (default) for the triggering issue/PR, '*' to require explicit issue_number/pull_number, or a specific issue/PR number. With 'triggering', auto-resolves from github.event.issue.number or github.event.pull_request.number." }, "target-repo": { @@ -6808,7 +7768,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6855,7 +7818,10 @@ ] }, "target": { - "type": ["string", "number"], + "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": { @@ -6881,7 +7847,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -6928,7 +7897,10 @@ ] }, "target": { - "type": ["string", "number"], + "type": [ + "string", + "number" + ], "description": "Target issue to unassign users from. Use 'triggering' (default) for the triggering issue, '*' to allow any issue, or a specific issue number." }, "target-repo": { @@ -6949,7 +7921,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7019,7 +7994,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7046,7 +8024,10 @@ "description": "Allow updating issue title - presence of key indicates field can be updated" }, "body": { - "type": ["boolean", "null"], + "type": [ + "boolean", + "null" + ], "description": "Allow updating issue body. Set to true to enable body updates, false to disable. For backward compatibility, null (body:) also enables body updates.", "default": true }, @@ -7092,7 +8073,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7129,7 +8113,11 @@ "operation": { "type": "string", "description": "Default operation for body updates: 'append' (add to end), 'prepend' (add to start), or 'replace' (overwrite completely). Defaults to 'replace' if not specified.", - "enum": ["append", "prepend", "replace"] + "enum": [ + "append", + "prepend", + "replace" + ] }, "footer": { "type": "boolean", @@ -7162,7 +8150,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7228,7 +8219,10 @@ "staged": { "type": "boolean", "description": "If true, evaluate merge gates and emit preview results without executing the merge API call.", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7293,7 +8287,11 @@ }, "if-no-changes": { "type": "string", - "enum": ["warn", "error", "ignore"], + "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)" }, "ignore-missing-branch-failure": { @@ -7312,7 +8310,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] }, "github-token-for-extra-empty-commit": { "type": "string", @@ -7348,7 +8349,11 @@ "oneOf": [ { "type": "string", - "enum": ["blocked", "allowed", "fallback-to-issue"], + "enum": [ + "blocked", + "allowed", + "fallback-to-issue" + ], "description": "Controls protected-file protection. blocked (default): hard-block any patch that modifies package manifests (e.g. package.json, go.mod), engine instruction files (e.g. AGENTS.md, CLAUDE.md) or .github/ files. allowed: allow all changes. fallback-to-issue: create a review issue instead of pushing to the PR branch, so a human can review the changes before applying.", "default": "blocked" }, @@ -7364,7 +8369,11 @@ "oneOf": [ { "type": "string", - "enum": ["blocked", "allowed", "fallback-to-issue"], + "enum": [ + "blocked", + "allowed", + "fallback-to-issue" + ], "description": "Protection policy. blocked (default): hard-block any patch that modifies protected files. allowed: allow all changes. fallback-to-issue: create a review issue instead of pushing.", "default": "blocked" }, @@ -7381,7 +8390,15 @@ "type": "string" }, "description": "List of filenames or path prefixes to remove from the default protected-file set. Items are matched by basename (e.g. \"AGENTS.md\") or path prefix (e.g. \".agents/\"). Use this to allow the agent to modify specific files that are otherwise blocked by default.", - "examples": [["AGENTS.md"], ["AGENTS.md", ".agents/"]] + "examples": [ + [ + "AGENTS.md" + ], + [ + "AGENTS.md", + ".agents/" + ] + ] } }, "additionalProperties": false, @@ -7408,7 +8425,10 @@ "oneOf": [ { "type": "string", - "enum": ["am", "bundle"], + "enum": [ + "am", + "bundle" + ], "default": "am", "description": "Transport format for packaging changes. \"am\" (default) uses git format-patch/git am. \"bundle\" uses git bundle, which preserves merge commit topology, per-commit authorship, and merge-resolution-only content." }, @@ -7424,7 +8444,10 @@ "type": "boolean", "description": "When true, adds workflows: write to the GitHub App token permissions. Required when allowed-files targets .github/workflows/ paths. Requires safe-outputs.github-app to be configured because the workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.", "default": false, - "examples": [true, false] + "examples": [ + true, + false + ] }, "check-branch-protection": { "type": "boolean", @@ -7471,7 +8494,14 @@ "description": "List of allowed reasons for hiding comments. Default: all reasons allowed (spam, abuse, off_topic, outdated, resolved, low_quality).", "items": { "type": "string", - "enum": ["spam", "abuse", "off_topic", "outdated", "resolved", "low_quality"] + "enum": [ + "spam", + "abuse", + "off_topic", + "outdated", + "resolved", + "low_quality" + ] } }, "discussions": { @@ -7481,7 +8511,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7544,7 +8577,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7599,10 +8635,15 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, - "required": ["workflows"], + "required": [ + "workflows" + ], "additionalProperties": false }, { @@ -7661,7 +8702,13 @@ "properties": { "type": { "type": "string", - "enum": ["string", "number", "boolean", "choice", "environment"], + "enum": [ + "string", + "number", + "boolean", + "choice", + "environment" + ], "description": "Input type" }, "description": { @@ -7708,10 +8755,16 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, - "required": ["workflow", "event_type"], + "required": [ + "workflow", + "event_type" + ], "additionalProperties": false } }, @@ -7754,10 +8807,15 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, - "required": ["workflows"], + "required": [ + "workflows" + ], "additionalProperties": false }, { @@ -7818,7 +8876,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7880,7 +8941,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7930,7 +8994,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -7995,7 +9062,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -8087,7 +9157,10 @@ "if-no-files": { "type": "string", "description": "Behaviour when no files match: 'error' (default) or 'ignore'", - "enum": ["error", "ignore"], + "enum": [ + "error", + "ignore" + ], "default": "error" } }, @@ -8100,7 +9173,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub Actions artifact uploads (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -8147,7 +9223,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -8162,7 +9241,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] }, "env": { "type": "object", @@ -8178,7 +9260,11 @@ "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 }}"] + "examples": [ + "${{ secrets.GITHUB_TOKEN }}", + "${{ secrets.CUSTOM_PAT }}", + "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}" + ] }, "github-app": { "$ref": "#/$defs/github_app", @@ -8364,7 +9450,13 @@ }, "type": { "type": "string", - "enum": ["string", "boolean", "choice", "number", "environment"], + "enum": [ + "string", + "boolean", + "choice", + "number", + "environment" + ], "description": "Input parameter type. Supports: string (default), boolean, choice (string with predefined options), number, and environment (string referencing a GitHub environment)", "default": "string" }, @@ -8460,7 +9552,11 @@ }, "type": { "type": "string", - "enum": ["string", "boolean", "number"], + "enum": [ + "string", + "boolean", + "number" + ], "description": "Input parameter type", "default": "string" } @@ -8475,7 +9571,9 @@ "description": "JavaScript handler body. Write only the code that runs inside the handler for each item \u2014 the compiler generates the full outer wrapper including config input destructuring (`const { channel, message } = config;`) and the handler function (`return async function handleX(item, resolvedTemporaryIds) { ... }`). The body has access to `item` (runtime message with input values), `resolvedTemporaryIds` (map of temporary IDs), and config-destructured local variables for each declared input." } }, - "required": ["script"], + "required": [ + "script" + ], "additionalProperties": false } }, @@ -8488,77 +9586,121 @@ "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}"] + "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})"] + "examples": [ + "> Install: `gh aw add {workflow_source}`", + "> [Add this workflow]({workflow_source_url})" + ] }, "footer-workflow-recompile": { "type": "string", "description": "Custom footer message template for workflow recompile issues. Available placeholders: {workflow_name}, {run_url}, {repository}. Example: '> Workflow sync report by [{workflow_name}]({run_url}) for {repository}'", - "examples": ["> Workflow sync report by [{workflow_name}]({run_url}) for {repository}", "> Maintenance report by [{workflow_name}]({run_url})"] + "examples": [ + "> Workflow sync report by [{workflow_name}]({run_url}) for {repository}", + "> Maintenance report by [{workflow_name}]({run_url})" + ] }, "footer-workflow-recompile-comment": { "type": "string", "description": "Custom footer message template for comments on workflow recompile issues. Available placeholders: {workflow_name}, {run_url}, {repository}. Example: '> Update from [{workflow_name}]({run_url}) for {repository}'", - "examples": ["> Update from [{workflow_name}]({run_url}) for {repository}", "> Maintenance update by [{workflow_name}]({run_url})"] + "examples": [ + "> Update from [{workflow_name}]({run_url}) for {repository}", + "> Maintenance update by [{workflow_name}]({run_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}"] + "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:"] + "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}."] + "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."] + "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}."] + "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})."] + "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})." + ] }, "agent-failure-issue": { "type": "string", "description": "Custom footer template for agent failure tracking issues. Available placeholders: {workflow_name}, {run_url}. Default: '> Agent failure tracked by [{workflow_name}]({run_url})'", - "examples": ["> Agent failure tracked by [{workflow_name}]({run_url})", "> Failure report from [{workflow_name}]({run_url})"] + "examples": [ + "> Agent failure tracked by [{workflow_name}]({run_url})", + "> Failure report from [{workflow_name}]({run_url})" + ] }, "agent-failure-comment": { "type": "string", "description": "Custom footer template for comments on agent failure tracking issues. Available placeholders: {workflow_name}, {run_url}. Default: '> Agent failure update from [{workflow_name}]({run_url})'", - "examples": ["> Agent failure update from [{workflow_name}]({run_url})", "> Update from [{workflow_name}]({run_url})"] + "examples": [ + "> Agent failure update from [{workflow_name}]({run_url})", + "> Update from [{workflow_name}]({run_url})" + ] }, "pull-request-created": { "type": "string", "description": "Custom message template for pull request creation link appended to the activation comment. Available placeholders: {item_number}, {item_url}. Default: 'Pull request created: [#{item_number}]({item_url})'", - "examples": ["Pull request created: [#{item_number}]({item_url})", "[#{item_number}]({item_url}) opened"] + "examples": [ + "Pull request created: [#{item_number}]({item_url})", + "[#{item_number}]({item_url}) opened" + ] }, "issue-created": { "type": "string", "description": "Custom message template for issue creation link appended to the activation comment. Available placeholders: {item_number}, {item_url}. Default: 'Issue created: [#{item_number}]({item_url})'", - "examples": ["Issue created: [#{item_number}]({item_url})", "[#{item_number}]({item_url}) filed"] + "examples": [ + "Issue created: [#{item_number}]({item_url})", + "[#{item_number}]({item_url}) filed" + ] }, "commit-pushed": { "type": "string", "description": "Custom message template for commit push link appended to the activation comment. Available placeholders: {commit_sha}, {short_sha}, {commit_url}. Default: 'Commit pushed: [`{short_sha}`]({commit_url})'", - "examples": ["Commit pushed: [`{short_sha}`]({commit_url})", "[`{short_sha}`]({commit_url}) pushed"] + "examples": [ + "Commit pushed: [`{short_sha}`]({commit_url})", + "[`{short_sha}`]({commit_url}) pushed" + ] }, "append-only-comments": { "type": "boolean", @@ -8621,31 +9763,50 @@ "type": "boolean", "description": "Global footer control for all safe outputs. When false, omits visible AI-generated footer content from all created/updated entities (issues, PRs, discussions, releases) while still including XML markers for searchability. Individual safe-output types (create-issue, update-issue, etc.) can override this by specifying their own footer field. Defaults to true.", "default": true, - "examples": [false, true] + "examples": [ + false, + true + ] }, "activation-comments": { - "type": ["boolean", "string"], + "type": [ + "boolean", + "string" + ], "description": "When set to false or \"false\", disables all activation and fallback comments entirely (run-started, run-success, run-failure, PR/issue creation links). Supports templatable boolean values including GitHub Actions expressions (e.g. ${{ inputs.activation-comments }}). Default: true", "default": true, - "examples": [false, true, "${{ inputs.activation-comments }}"] + "examples": [ + false, + true, + "${{ inputs.activation-comments }}" + ] }, "group-reports": { "type": "boolean", "description": "When true, creates a parent '[aw] Failed runs' issue that tracks all workflow failures as sub-issues. Helps organize failure tracking but may be unnecessary in smaller repositories. Defaults to false.", "default": false, - "examples": [false, true] + "examples": [ + false, + true + ] }, "report-failure-as-issue": { "type": "boolean", "description": "When false, disables creating failure tracking issues when workflows fail. Useful for workflows where failures are expected or handled elsewhere. Defaults to true.", "default": true, - "examples": [false, true] - }, + "examples": [ + false, + true + ] + }, "failure-issue-repo": { "type": "string", "description": "Repository to create failure tracking issues in, in the format 'owner/repo'. Useful when the current repository has issues disabled. Defaults to the current repository.", "pattern": "^[^/]+/[^/]+$", - "examples": ["github/docs-engineering", "myorg/infra-alerts"] + "examples": [ + "github/docs-engineering", + "myorg/infra-alerts" + ] }, "max-bot-mentions": { "description": "Maximum number of bot trigger references (e.g. 'fixes #123', 'closes #456') allowed in output before all of them are neutralized. Default: 10. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max-bot-mentions }}').", @@ -8664,14 +9825,23 @@ }, "id-token": { "type": "string", - "enum": ["write", "none"], + "enum": [ + "write", + "none" + ], "description": "Override the id-token permission for the safe-outputs job. Use 'write' to force-enable the id-token: write permission (required for OIDC authentication with cloud providers). Use 'none' to suppress automatic detection and prevent adding id-token: write even when vault/OIDC actions are detected in steps. By default, the compiler auto-detects known OIDC/vault actions (aws-actions/configure-aws-credentials, azure/login, google-github-actions/auth, hashicorp/vault-action, cyberark/conjur-action) and adds id-token: write automatically.", - "examples": ["write", "none"] + "examples": [ + "write", + "none" + ] }, "concurrency-group": { "type": "string", "description": "Concurrency group for the safe-outputs job. When set, the safe-outputs job will use this concurrency group with cancel-in-progress: false. Supports GitHub Actions expressions.", - "examples": ["my-workflow-safe-outputs", "safe-outputs-${{ github.repository }}"] + "examples": [ + "my-workflow-safe-outputs", + "safe-outputs-${{ github.repository }}" + ] }, "needs": { "type": "array", @@ -8683,7 +9853,11 @@ "additionalItems": false, "uniqueItems": true, "default": [], - "examples": [["secrets_fetcher"]] + "examples": [ + [ + "secrets_fetcher" + ] + ] }, "environment": { "description": "Override the GitHub deployment environment for the safe-outputs job. When set, this environment is used instead of the top-level environment: field. When not set, the top-level environment: field is propagated automatically so that environment-scoped secrets are accessible in the safe-outputs job.", @@ -8705,7 +9879,9 @@ "description": "A deployment URL" } }, - "required": ["name"], + "required": [ + "name" + ], "additionalProperties": false } ] @@ -8740,7 +9916,11 @@ "uses": { "type": "string", "description": "The GitHub Action to use. Supports owner/repo@ref, owner/repo/subdir@ref, or ./local/path.", - "examples": ["actions-ecosystem/action-add-labels@v1", "owner/repo@v1", "owner/repo/subdir@v1"] + "examples": [ + "actions-ecosystem/action-add-labels@v1", + "owner/repo@v1", + "owner/repo/subdir@v1" + ] }, "description": { "type": "string", @@ -8785,7 +9965,9 @@ "additionalProperties": false } }, - "required": ["uses"], + "required": [ + "uses" + ], "additionalProperties": false } } @@ -8835,7 +10017,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [true, false] + "examples": [ + true, + false + ] } }, "additionalProperties": false @@ -8851,6 +10036,82 @@ } ], "description": "Enable AI agents to signal that a task could not be completed due to infrastructure or tool failures (e.g., MCP crash, missing auth, inaccessible repository). Activates failure handling even when the agent exits 0." + }, + "edit-wiki": { + "oneOf": [ + { + "type": "null", + "description": "Use default configuration (if-no-changes: 'warn')" + }, + { + "type": "object", + "description": "Configuration for pushing committed changes to a repository wiki. Changes are applied to the main branch of the wiki.", + "properties": { + "max": { + "description": "Maximum number of wiki edit operations to perform (default: 1). Supports integer or GitHub Actions expression.", + "oneOf": [ + { + "type": "integer", + "minimum": 1, + "maximum": 10, + "default": 1 + }, + { + "type": "string", + "pattern": "^\\$\\{\\{.*\\}\\}$", + "description": "GitHub Actions expression that resolves to an integer at runtime" + } + ] + }, + "repo": { + "type": "string", + "description": "Target repository for wiki edits in 'owner/repo' format. Defaults to the current repository. Must be in allowed-repos if allowed-repos is configured." + }, + "allowed-repos": { + "description": "List of repositories in 'owner/repo' format that the wiki edit can target. When configured, allows specifying a 'repo' field in the tool call. Accepts an array of repository slugs or a GitHub Actions expression.", + "oneOf": [ + { + "type": "array", + "description": "Array of repository slugs", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^\\$\\{\\{.*\\}\\}$", + "description": "GitHub Actions expression that resolves to a comma-separated list of repository slugs" + } + ] + }, + "if-no-changes": { + "type": "string", + "enum": [ + "warn", + "error", + "ignore" + ], + "default": "warn", + "description": "Behavior when no changes are present in the patch: 'warn' (default, skip with warning), 'error' (fail the step), 'ignore' (skip silently)" + }, + "commit-title-suffix": { + "type": "string", + "description": "Optional suffix to append to the generated commit title (e.g., ' [automated]')" + }, + "github-token": { + "type": "string", + "description": "GitHub token for wiki push operations. Supports GitHub Actions secret expressions (e.g. '${{ secrets.MY_TOKEN }}'). Defaults to the safe-outputs github-token or GITHUB_TOKEN." + }, + "staged": { + "type": "boolean", + "default": false, + "description": "If true, emit a step summary preview instead of pushing to the wiki. Useful for testing workflow configuration." + } + }, + "additionalProperties": false + } + ], + "description": "Push committed changes to a repository wiki. Changes are applied to the main branch of the wiki using a git patch." } }, "additionalProperties": false @@ -8913,7 +10174,9 @@ "rate-limit": { "type": "object", "description": "Rate limiting configuration to restrict how frequently users can trigger the workflow. Helps prevent abuse and resource exhaustion from programmatically triggered events.", - "required": ["max"], + "required": [ + "max" + ], "properties": { "max": { "description": "Maximum number of workflow runs allowed per user within the time window. Required field. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -8942,7 +10205,16 @@ "description": "Optional list of event types to apply rate limiting to. If not specified, rate limiting applies to all programmatically triggered events (e.g., workflow_dispatch, issue_comment, pull_request_review).", "items": { "type": "string", - "enum": ["workflow_dispatch", "issue_comment", "pull_request_review", "pull_request_review_comment", "issues", "pull_request", "discussion_comment", "discussion"] + "enum": [ + "workflow_dispatch", + "issue_comment", + "pull_request_review", + "pull_request_review_comment", + "issues", + "pull_request", + "discussion_comment", + "discussion" + ] }, "minItems": 1 }, @@ -8951,7 +10223,13 @@ "description": "Optional list of roles that are exempt from rate limiting. Defaults to ['admin', 'maintain', 'write'] if not specified. Users with any of these roles will not be subject to rate limiting checks. To apply rate limiting to all users, set to an empty array: []", "items": { "type": "string", - "enum": ["admin", "maintain", "write", "triage", "read"] + "enum": [ + "admin", + "maintain", + "write", + "triage", + "read" + ] }, "minItems": 0 } @@ -8965,12 +10243,18 @@ { "max": 10, "window": 30, - "events": ["workflow_dispatch", "issue_comment"] + "events": [ + "workflow_dispatch", + "issue_comment" + ] }, { "max": 5, "window": 60, - "ignored-roles": ["admin", "maintain"] + "ignored-roles": [ + "admin", + "maintain" + ] } ] }, @@ -8979,25 +10263,37 @@ "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://github.github.com/gh-aw/reference/frontmatter/#strict-mode-strict", - "examples": [true, false] + "examples": [ + true, + false + ] }, "private": { "type": "boolean", "default": false, "description": "Mark the workflow as private, preventing it from being added to other repositories via 'gh aw add'. A workflow with private: true is not meant to be shared outside its repository.", - "examples": [true, false] + "examples": [ + true, + false + ] }, "check-for-updates": { "type": "boolean", "default": true, "description": "Control whether the compile-agentic version update check runs in the activation job. When true (default), the activation job downloads config.json from the gh-aw repository and verifies the compiled version is not blocked and meets the minimum supported version. Set to false to disable the check (not allowed in strict mode). See: https://github.github.com/gh-aw/reference/frontmatter/#check-for-updates", - "examples": [true, false] + "examples": [ + true, + false + ] }, "run-install-scripts": { "type": "boolean", "default": false, "description": "Allow npm pre/post install scripts to execute during package installation. By default, --ignore-scripts is added to all generated npm install commands to prevent supply chain attacks via malicious install hooks. Setting run-install-scripts: true disables this protection globally (all runtimes). A supply chain security warning is emitted at compile time; in strict mode this is an error. Per-runtime control is also available via runtimes..run-install-scripts. See: https://github.github.com/gh-aw/reference/frontmatter/#run-install-scripts", - "examples": [false, true] + "examples": [ + false, + true + ] }, "mcp-scripts": { "type": "object", @@ -9006,7 +10302,9 @@ "^([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"], + "required": [ + "description" + ], "properties": { "description": { "type": "string", @@ -9020,7 +10318,13 @@ "properties": { "type": { "type": "string", - "enum": ["string", "number", "boolean", "array", "object"], + "enum": [ + "string", + "number", + "boolean", + "array", + "object" + ], "default": "string", "description": "The JSON schema type of the input parameter." }, @@ -9074,71 +10378,108 @@ "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] + "examples": [ + 30, + 60, + 120, + 300 + ] } }, "additionalProperties": false, "oneOf": [ { - "required": ["script"], + "required": [ + "script" + ], "not": { "anyOf": [ { - "required": ["run"] + "required": [ + "run" + ] }, { - "required": ["py"] + "required": [ + "py" + ] }, { - "required": ["go"] + "required": [ + "go" + ] } ] } }, { - "required": ["run"], + "required": [ + "run" + ], "not": { "anyOf": [ { - "required": ["script"] + "required": [ + "script" + ] }, { - "required": ["py"] + "required": [ + "py" + ] }, { - "required": ["go"] + "required": [ + "go" + ] } ] } }, { - "required": ["py"], + "required": [ + "py" + ], "not": { "anyOf": [ { - "required": ["script"] + "required": [ + "script" + ] }, { - "required": ["run"] + "required": [ + "run" + ] }, { - "required": ["go"] + "required": [ + "go" + ] } ] } }, { - "required": ["go"], + "required": [ + "go" + ], "not": { "anyOf": [ { - "required": ["script"] + "required": [ + "script" + ] }, { - "required": ["run"] + "required": [ + "run" + ] }, { - "required": ["py"] + "required": [ + "py" + ] } ] } @@ -9196,9 +10537,18 @@ "description": "Runtime configuration object identified by runtime ID (e.g., 'node', 'python', 'go')", "properties": { "version": { - "type": ["string", "number"], + "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] + "examples": [ + "22", + "3.12", + "latest", + 22, + 3.12 + ] }, "action-repo": { "type": "string", @@ -9211,13 +10561,22 @@ "if": { "type": "string", "description": "Optional GitHub Actions if condition to control when the runtime setup step runs. Supports standard GitHub Actions expression syntax. Useful for conditionally installing runtimes based on file presence (e.g., \"hashFiles('go.mod') != ''\" to install Go only when go.mod exists).", - "examples": ["hashFiles('go.mod') != ''", "hashFiles('package.json') != ''", "hashFiles('requirements.txt') != '' || hashFiles('pyproject.toml') != ''", "hashFiles('uv.lock') != ''", "github.event_name == 'workflow_dispatch'"] + "examples": [ + "hashFiles('go.mod') != ''", + "hashFiles('package.json') != ''", + "hashFiles('requirements.txt') != '' || hashFiles('pyproject.toml') != ''", + "hashFiles('uv.lock') != ''", + "github.event_name == 'workflow_dispatch'" + ] }, "run-install-scripts": { "type": "boolean", "default": false, "description": "Allow npm pre/post install scripts to execute for this runtime during package installation. Overrides the global run-install-scripts setting for this specific runtime. Only affects runtimes that generate npm install commands (node). A supply chain security warning is emitted at compile time; in strict mode this is an error.", - "examples": [false, true] + "examples": [ + false, + true + ] } }, "additionalProperties": false @@ -9241,7 +10600,9 @@ }, { "type": "boolean", - "enum": [false], + "enum": [ + false + ], "description": "Set to false to disable the default checkout step. The agent job will not check out any repository (dev-mode checkouts are unaffected)." } ] @@ -9249,9 +10610,14 @@ "dependencies": { "description": "APM package references to install. Supports array format (list of package slugs) or object format with packages and isolated fields.", "examples": [ - ["microsoft/apm-sample-package", "acme/custom-tools"], + [ + "microsoft/apm-sample-package", + "acme/custom-tools" + ], { - "packages": ["microsoft/apm-sample-package"], + "packages": [ + "microsoft/apm-sample-package" + ], "isolated": true } ], @@ -9296,10 +10662,15 @@ "github-token": { "type": "string", "description": "GitHub token expression to authenticate APM with private package repositories. Uses cascading fallback (GH_AW_PLUGINS_TOKEN \u2192 GH_AW_GITHUB_TOKEN \u2192 GITHUB_TOKEN) when not specified. Takes effect unless github-app is also configured (which takes precedence).", - "examples": ["${{ secrets.MY_TOKEN }}", "${{ secrets.GH_AW_GITHUB_TOKEN }}"] + "examples": [ + "${{ secrets.MY_TOKEN }}", + "${{ secrets.GH_AW_GITHUB_TOKEN }}" + ] } }, - "required": ["packages"], + "required": [ + "packages" + ], "additionalProperties": false } ] @@ -9331,7 +10702,13 @@ }, "type": { "type": "string", - "enum": ["string", "number", "boolean", "choice", "array"], + "enum": [ + "string", + "number", + "boolean", + "choice", + "array" + ], "description": "The type of the input value." }, "options": { @@ -9347,7 +10724,11 @@ "properties": { "type": { "type": "string", - "enum": ["string", "number", "boolean"], + "enum": [ + "string", + "number", + "boolean" + ], "description": "Type of each array item." } }, @@ -9359,7 +10740,9 @@ { "type": "object", "description": "Input parameter definition for object type (one level deep). Use 'properties' to declare the expected sub-fields.", - "required": ["type"], + "required": [ + "type" + ], "properties": { "description": { "type": "string", @@ -9372,7 +10755,9 @@ }, "type": { "type": "string", - "enum": ["object"], + "enum": [ + "object" + ], "description": "The type 'object' enables structured sub-fields accessible via 'github.aw.import-inputs..'." }, "properties": { @@ -9392,7 +10777,12 @@ "default": {}, "type": { "type": "string", - "enum": ["string", "number", "boolean", "choice"], + "enum": [ + "string", + "number", + "boolean", + "choice" + ], "description": "Type of the sub-property." }, "options": { @@ -9462,7 +10852,9 @@ } } }, - "required": ["slash_command"] + "required": [ + "slash_command" + ] }, { "properties": { @@ -9472,7 +10864,9 @@ } } }, - "required": ["command"] + "required": [ + "command" + ] } ] } @@ -9491,7 +10885,9 @@ } } }, - "required": ["issue_comment"] + "required": [ + "issue_comment" + ] }, { "properties": { @@ -9501,7 +10897,9 @@ } } }, - "required": ["pull_request_review_comment"] + "required": [ + "pull_request_review_comment" + ] }, { "properties": { @@ -9511,7 +10909,9 @@ } } }, - "required": ["label"] + "required": [ + "label" + ] } ] } @@ -9684,9 +11084,18 @@ "description": "AI engine identifier: built-in ('claude', 'codex', 'copilot', 'gemini', 'crush') or a named catalog entry" }, "version": { - "type": ["string", "number"], + "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. GitHub Actions expressions (e.g., '${{ inputs.engine-version }}') are accepted and compiled with injection-safe env var handling.", - "examples": ["beta", "stable", 20, 3.11, "${{ inputs.engine-version }}"] + "examples": [ + "beta", + "stable", + 20, + 3.11, + "${{ inputs.engine-version }}" + ] }, "model": { "type": "string", @@ -9729,7 +11138,9 @@ "description": "Whether to cancel in-progress runs of the same concurrency group. Defaults to false for agentic workflow runs." } }, - "required": ["group"], + "required": [ + "group" + ], "additionalProperties": false } ], @@ -9766,7 +11177,11 @@ "api-target": { "type": "string", "description": "Custom API endpoint hostname for the agentic engine. Used for GitHub Enterprise Cloud (GHEC), GitHub Enterprise Server (GHES), or custom AI endpoints. Example: 'api.acme.ghe.com' for GHEC, 'api.enterprise.githubcopilot.com' for GHES, or custom endpoint hostnames.", - "examples": ["api.acme.ghe.com", "api.enterprise.githubcopilot.com", "api.custom.endpoint.com"] + "examples": [ + "api.acme.ghe.com", + "api.enterprise.githubcopilot.com", + "api.custom.endpoint.com" + ] }, "token-weights": { "type": "object", @@ -9840,13 +11255,21 @@ "session-timeout": { "type": "string", "description": "Session timeout for MCP gateway sessions as a Go duration string (e.g. \"30m\", \"4h\", \"24h\"). Must be at least 5m (no upper bound). Omitted or empty uses the effective gateway default (precedence: this field > MCP_GATEWAY_SESSION_TIMEOUT env var > built-in default 6h). Longer timeouts benefit multi-hour workflows such as large-scale migrations; shorter values free gateway resources sooner.", - "examples": ["30m", "1h", "4h", "6h", "12h"] + "examples": [ + "30m", + "1h", + "4h", + "6h", + "12h" + ] } }, "additionalProperties": false } }, - "required": ["id"], + "required": [ + "id" + ], "additionalProperties": false }, { @@ -9860,15 +11283,30 @@ "id": { "type": "string", "description": "Runtime adapter identifier (e.g. 'codex', 'claude', 'copilot', 'gemini', 'crush')", - "examples": ["codex", "claude", "copilot", "gemini", "crush"] + "examples": [ + "codex", + "claude", + "copilot", + "gemini", + "crush" + ] }, "version": { - "type": ["string", "number"], + "type": [ + "string", + "number" + ], "description": "Optional version of the runtime adapter (e.g. '0.105.0', 'beta')", - "examples": ["0.105.0", "beta", "latest"] + "examples": [ + "0.105.0", + "beta", + "latest" + ] } }, - "required": ["id"], + "required": [ + "id" + ], "additionalProperties": false }, "provider": { @@ -9878,12 +11316,21 @@ "id": { "type": "string", "description": "Provider identifier (e.g. 'openai', 'anthropic', 'github', 'google')", - "examples": ["openai", "anthropic", "github", "google"] + "examples": [ + "openai", + "anthropic", + "github", + "google" + ] }, "model": { "type": "string", "description": "Optional specific LLM model to use (e.g. 'gpt-5', 'claude-3-5-sonnet-20241022')", - "examples": ["gpt-5", "claude-3-5-sonnet-20241022", "gpt-4o"] + "examples": [ + "gpt-5", + "claude-3-5-sonnet-20241022", + "gpt-4o" + ] }, "auth": { "type": "object", @@ -9892,37 +11339,58 @@ "secret": { "type": "string", "description": "Name of the GitHub Actions secret that contains the API key for this provider", - "examples": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "CUSTOM_API_KEY"] + "examples": [ + "OPENAI_API_KEY", + "ANTHROPIC_API_KEY", + "CUSTOM_API_KEY" + ] }, "strategy": { "type": "string", - "enum": ["api-key", "oauth-client-credentials", "bearer"], + "enum": [ + "api-key", + "oauth-client-credentials", + "bearer" + ], "description": "Authentication strategy for the provider (default: api-key when secret is set)" }, "token-url": { "type": "string", "description": "OAuth 2.0 token endpoint URL. Required when strategy is 'oauth-client-credentials'.", - "examples": ["https://auth.example.com/oauth/token"] + "examples": [ + "https://auth.example.com/oauth/token" + ] }, "client-id": { "type": "string", "description": "GitHub Actions secret name that holds the OAuth client ID. Required when strategy is 'oauth-client-credentials'.", - "examples": ["OAUTH_CLIENT_ID"] + "examples": [ + "OAUTH_CLIENT_ID" + ] }, "client-secret": { "type": "string", "description": "GitHub Actions secret name that holds the OAuth client secret. Required when strategy is 'oauth-client-credentials'.", - "examples": ["OAUTH_CLIENT_SECRET"] + "examples": [ + "OAUTH_CLIENT_SECRET" + ] }, "token-field": { "type": "string", "description": "JSON field name in the token response that contains the access token. Defaults to 'access_token'.", - "examples": ["access_token", "token"] + "examples": [ + "access_token", + "token" + ] }, "header-name": { "type": "string", "description": "HTTP header name to inject the API key or token into (e.g. 'api-key', 'x-api-key'). Required when strategy is not 'bearer'.", - "examples": ["api-key", "x-api-key", "Authorization"] + "examples": [ + "api-key", + "x-api-key", + "Authorization" + ] } }, "additionalProperties": false @@ -9934,7 +11402,9 @@ "path-template": { "type": "string", "description": "URL path template with {model} and other variable placeholders (e.g. '/openai/deployments/{model}/chat/completions')", - "examples": ["/openai/deployments/{model}/chat/completions"] + "examples": [ + "/openai/deployments/{model}/chat/completions" + ] }, "query": { "type": "object", @@ -9972,7 +11442,9 @@ "default": false } }, - "required": ["runtime"], + "required": [ + "runtime" + ], "additionalProperties": false }, { @@ -10013,7 +11485,11 @@ }, "strategy": { "type": "string", - "enum": ["api-key", "oauth-client-credentials", "bearer"], + "enum": [ + "api-key", + "oauth-client-credentials", + "bearer" + ], "description": "Authentication strategy" }, "token-url": { @@ -10100,7 +11576,10 @@ "description": "Name of the GitHub Actions secret that provides credentials for this role" } }, - "required": ["role", "secret"], + "required": [ + "role", + "secret" + ], "additionalProperties": false } }, @@ -10110,7 +11589,10 @@ "additionalProperties": true } }, - "required": ["id", "display-name"], + "required": [ + "id", + "display-name" + ], "additionalProperties": false } ] @@ -10121,13 +11603,18 @@ "properties": { "type": { "type": "string", - "enum": ["stdio", "local"], + "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", - "examples": ["https://api.mcp.github.com/v0/servers/microsoft/markitdown"] + "examples": [ + "https://api.mcp.github.com/v0/servers/microsoft/markitdown" + ] }, "command": { "type": "string", @@ -10142,9 +11629,17 @@ "description": "Container image for stdio MCP connections" }, "version": { - "type": ["string", "number"], + "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] + "examples": [ + "latest", + "v1.0.0", + 20, + 3.11 + ] }, "args": { "type": "array", @@ -10156,7 +11651,11 @@ "entrypoint": { "type": "string", "description": "Optional entrypoint override for container (equivalent to docker run --entrypoint)", - "examples": ["/bin/sh", "/custom/entrypoint.sh", "python"] + "examples": [ + "/bin/sh", + "/custom/entrypoint.sh", + "python" + ] }, "entrypointArgs": { "type": "array", @@ -10172,7 +11671,15 @@ "pattern": "^[^:]+:[^:]+:(ro|rw)$" }, "description": "Volume mounts for container in format 'source:dest:mode' where mode is 'ro' or 'rw'", - "examples": [["/tmp/data:/data:ro"], ["/workspace:/workspace:rw", "/config:/config:ro"]] + "examples": [ + [ + "/tmp/data:/data:ro" + ], + [ + "/workspace:/workspace:rw", + "/config:/config:ro" + ] + ] }, "env": { "type": "object", @@ -10218,7 +11725,18 @@ "items": { "type": "string" }, - "examples": [["*"], ["store_memory", "retrieve_memory"], ["brave_web_search"]] + "examples": [ + [ + "*" + ], + [ + "store_memory", + "retrieve_memory" + ], + [ + "brave_web_search" + ] + ] }, "proxy-args": { "type": "array", @@ -10232,22 +11750,32 @@ "$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) Type constraint: When 'type' is 'stdio' or 'local', either 'command' or 'container' is required. Note: Per-server 'network' field is deprecated and ignored.", "anyOf": [ { - "required": ["type"] + "required": [ + "type" + ] }, { - "required": ["command"] + "required": [ + "command" + ] }, { - "required": ["container"] + "required": [ + "container" + ] } ], "not": { "allOf": [ { - "required": ["command"] + "required": [ + "command" + ] }, { - "required": ["container"] + "required": [ + "container" + ] } ] }, @@ -10256,17 +11784,24 @@ "if": { "properties": { "type": { - "enum": ["stdio", "local"] + "enum": [ + "stdio", + "local" + ] } } }, "then": { "anyOf": [ { - "required": ["command"] + "required": [ + "command" + ] }, { - "required": ["container"] + "required": [ + "container" + ] } ] } @@ -10279,13 +11814,17 @@ "properties": { "type": { "type": "string", - "enum": ["http"], + "enum": [ + "http" + ], "description": "MCP connection type for HTTP" }, "registry": { "type": "string", "description": "URI to the installation location when MCP is installed from a registry", - "examples": ["https://api.mcp.github.com/v0/servers/microsoft/markitdown"] + "examples": [ + "https://api.mcp.github.com/v0/servers/microsoft/markitdown" + ] }, "url": { "type": "string", @@ -10308,13 +11847,26 @@ "items": { "type": "string" }, - "examples": [["*"], ["store_memory", "retrieve_memory"], ["brave_web_search"]] + "examples": [ + [ + "*" + ], + [ + "store_memory", + "retrieve_memory" + ], + [ + "brave_web_search" + ] + ] }, "auth": { "$ref": "#/$defs/http_mcp_auth" } }, - "required": ["url"], + "required": [ + "url" + ], "additionalProperties": false }, "http_mcp_auth": { @@ -10323,7 +11875,9 @@ "properties": { "type": { "type": "string", - "enum": ["github-oidc"], + "enum": [ + "github-oidc" + ], "description": "Authentication type. Currently only 'github-oidc' is supported, which acquires short-lived JWTs from the GitHub Actions OIDC endpoint." }, "audience": { @@ -10332,14 +11886,21 @@ "format": "uri" } }, - "required": ["type"], + "required": [ + "type" + ], "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_]*)*|needs\\.[A-Za-z_][A-Za-z0-9_]*\\.outputs\\.[A-Za-z_][A-Za-z0-9_]*)\\s*\\}\\}$", "description": "GitHub token expression. Accepts a secrets expression (e.g., `${{ secrets.NAME }}` or `${{ secrets.NAME1 || secrets.NAME2 }}`) or a job output expression (e.g., `${{ needs.auth.outputs.token }}`). Pattern details: secret names match `[A-Za-z_][A-Za-z0-9_]*`; job IDs and output names in dot notation match `[A-Za-z_][A-Za-z0-9_]*` (identifiers without hyphens).", - "examples": ["${{ secrets.GITHUB_TOKEN }}", "${{ secrets.CUSTOM_PAT }}", "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", "${{ needs.auth.outputs.token }}"] + "examples": [ + "${{ secrets.GITHUB_TOKEN }}", + "${{ secrets.CUSTOM_PAT }}", + "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", + "${{ needs.auth.outputs.token }}" + ] }, "github_app": { "type": "object", @@ -10348,17 +11909,23 @@ "app-id": { "type": "string", "description": "Deprecated alias for client-id. GitHub App ID/client ID (e.g., '${{ vars.APP_ID }}').", - "examples": ["${{ vars.APP_ID }}"] + "examples": [ + "${{ vars.APP_ID }}" + ] }, "client-id": { "type": "string", "description": "GitHub App client ID (e.g., '${{ vars.APP_ID }}'). Required to mint a GitHub App token.", - "examples": ["${{ vars.APP_ID }}"] + "examples": [ + "${{ vars.APP_ID }}" + ] }, "private-key": { "type": "string", "description": "GitHub App private key (e.g., '${{ secrets.APP_PRIVATE_KEY }}'). Required to mint a GitHub App token.", - "examples": ["${{ secrets.APP_PRIVATE_KEY }}"] + "examples": [ + "${{ secrets.APP_PRIVATE_KEY }}" + ] }, "owner": { "type": "string", @@ -10378,10 +11945,16 @@ }, "anyOf": [ { - "required": ["client-id", "private-key"] + "required": [ + "client-id", + "private-key" + ] }, { - "required": ["app-id", "private-key"] + "required": [ + "app-id", + "private-key" + ] } ], "additionalProperties": false, @@ -10496,10 +12069,14 @@ "additionalProperties": false, "anyOf": [ { - "required": ["uses"] + "required": [ + "uses" + ] }, { - "required": ["run"] + "required": [ + "run" + ] } ] }, @@ -10511,34 +12088,56 @@ "repository": { "type": "string", "description": "Repository to checkout in owner/repo format. Defaults to the current repository.", - "examples": ["owner/repo", "github/gh-aw"] + "examples": [ + "owner/repo", + "github/gh-aw" + ] }, "ref": { "type": "string", "description": "Branch, tag, or SHA to checkout. Defaults to the ref that triggered the workflow.", - "examples": ["main", "v1.0.0", "feature/my-branch"] + "examples": [ + "main", + "v1.0.0", + "feature/my-branch" + ] }, "path": { "type": "string", "description": "Relative path within GITHUB_WORKSPACE to place the checkout. Defaults to the workspace root.", - "examples": [".", "./libs/other-repo", "./workspace"] + "examples": [ + ".", + "./libs/other-repo", + "./workspace" + ] }, "fetch-depth": { "type": "integer", "minimum": 0, "description": "Number of commits to fetch. 0 fetches all history. 1 (default) is a shallow clone. When multiple configs target the same path, the deepest value is used.", - "examples": [0, 1, 10] + "examples": [ + 0, + 1, + 10 + ] }, "sparse-checkout": { "type": "string", "description": "Enable sparse-checkout with newline-separated patterns. When multiple configs target the same path, patterns are merged.", - "examples": [".github/\nsrc/", "docs/"] + "examples": [ + ".github/\nsrc/", + "docs/" + ] }, "submodules": { "oneOf": [ { "type": "string", - "enum": ["recursive", "true", "false"] + "enum": [ + "recursive", + "true", + "false" + ] }, { "type": "boolean" @@ -10553,12 +12152,18 @@ "token": { "type": "string", "description": "Deprecated: Use github-token instead. GitHub token for authentication. Credentials are always removed after checkout (persist-credentials: false is enforced).", - "examples": ["${{ secrets.MY_PAT }}", "${{ secrets.GITHUB_TOKEN }}"] + "examples": [ + "${{ secrets.MY_PAT }}", + "${{ secrets.GITHUB_TOKEN }}" + ] }, "github-token": { "type": "string", "description": "GitHub token for authentication. Use ${{ secrets.MY_TOKEN }} to reference a secret. Mutually exclusive with github-app (and deprecated app). Credentials are always removed after checkout (persist-credentials: false is enforced).", - "examples": ["${{ secrets.MY_PAT }}", "${{ secrets.CROSS_REPO_PAT }}"] + "examples": [ + "${{ secrets.MY_PAT }}", + "${{ secrets.CROSS_REPO_PAT }}" + ] }, "github-app": { "$ref": "#/$defs/github_app", @@ -10583,12 +12188,29 @@ } ], "description": "Additional Git refs to fetch after the checkout. Supported values: \"*\" (all branches), \"refs/pulls/open/*\" (all open pull-request refs), branch names (e.g. \"main\"), or glob patterns (e.g. \"feature/*\").", - "examples": [["*"], ["refs/pulls/open/*"], ["main", "feature/my-branch"], ["feature/*"]] + "examples": [ + [ + "*" + ], + [ + "refs/pulls/open/*" + ], + [ + "main", + "feature/my-branch" + ], + [ + "feature/*" + ] + ] }, "wiki": { "type": "boolean", "description": "When true, clones the repository's wiki git instead of the regular repository. The effective repository becomes \"{repository}.wiki\" (e.g. \"owner/repo.wiki\"). Defaults to false.", - "examples": [true, false] + "examples": [ + true, + false + ] } } }, @@ -10599,97 +12221,169 @@ "properties": { "actions": { "type": "string", - "enum": ["read", "write", "none"], + "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"], + "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"], + "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"], + "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"], + "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"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission for repository discussions (read: view discussions, write: create/update discussions, none: no access)" }, "id-token": { "type": "string", - "enum": ["write", "none"], + "enum": [ + "write", + "none" + ], "description": "Permission level for OIDC token requests (write/none only - read is not supported). Allows workflows to request JWT tokens for cloud provider authentication." }, "issues": { "type": "string", - "enum": ["read", "write", "none"], + "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"], + "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"], + "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"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for GitHub Packages (read/write/none). Controls access to publish, modify, or delete packages." }, "pages": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for GitHub Pages (read/write/none). Controls access to deploy and manage GitHub Pages sites." }, "pull-requests": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for pull requests (read/write/none). Controls access to create, edit, review, and manage pull requests." }, "repository-projects": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for repository projects (read/write/none). Controls access to manage repository-level GitHub Projects boards." }, "organization-projects": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for organization projects (read/write/none). Controls access to manage organization-level GitHub Projects boards." }, "security-events": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for security events (read/write/none). Controls access to view and manage code scanning alerts and security findings." }, "statuses": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for commit statuses (read/write/none). Controls access to create and update commit status checks." }, "vulnerability-alerts": { "type": "string", - "enum": ["read", "write", "none"], + "enum": [ + "read", + "write", + "none" + ], "description": "Permission level for Dependabot vulnerability alerts (read/write/none). Allows workflows to access the Dependabot alerts API via GITHUB_TOKEN instead of requiring a PAT or GitHub App." }, "all": { "type": "string", - "enum": ["read"], + "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." } } @@ -10701,152 +12395,271 @@ "properties": { "administration": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for repository administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission for repository administration." }, "codespaces": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for Codespaces (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "codespaces-lifecycle-admin": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for Codespaces lifecycle administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "codespaces-metadata": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for Codespaces metadata (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "email-addresses": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for user email addresses (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "environments": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for repository environments (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "git-signing": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for git signing (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "members": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization members (read/none; \"write\" is rejected by the compiler). Required for org team membership API calls." }, "organization-administration": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-announcement-banners": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization announcement banners (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-codespaces": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization Codespaces (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-copilot": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization Copilot (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-org-roles": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization custom org roles (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-properties": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization custom properties (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-repository-roles": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization custom repository roles (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-events": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization events (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-hooks": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization webhooks (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-members": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization members management (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-packages": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization packages (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-personal-access-token-requests": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization personal access token requests (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-personal-access-tokens": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization personal access tokens (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-plan": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization plan (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-self-hosted-runners": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization self-hosted runners (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-user-blocking": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for organization user blocking (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "repository-custom-properties": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for repository custom properties (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "repository-hooks": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for repository webhooks (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "single-file": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for single file access (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "team-discussions": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for team discussions (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "vulnerability-alerts": { "type": "string", - "enum": ["read", "none"], + "enum": [ + "read", + "none" + ], "description": "Permission level for Dependabot vulnerability alerts (read/none; \"write\" is rejected by the compiler). Also available as a GITHUB_TOKEN scope. When used with a GitHub App, forwarded as permission-vulnerability-alerts input." }, "workflows": { "type": "string", - "enum": ["read", "none", "write"], + "enum": [ + "read", + "none", + "write" + ], "description": "Permission level for GitHub Actions workflow files (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." } }, diff --git a/pkg/workflow/compiler_safe_outputs_handlers.go b/pkg/workflow/compiler_safe_outputs_handlers.go index 8c1982522f8..b4a5e6adb5d 100644 --- a/pkg/workflow/compiler_safe_outputs_handlers.go +++ b/pkg/workflow/compiler_safe_outputs_handlers.go @@ -455,6 +455,26 @@ var handlerRegistry = map[string]handlerBuilder{ AddBoolPtr("check_branch_protection", c.CheckBranchProtection). Build() }, + "edit_wiki": func(cfg *SafeOutputsConfig) map[string]any { + if cfg.EditWiki == nil { + return nil + } + c := cfg.EditWiki + maxPatchSize := 1024 // default 1024 KB + if cfg.MaximumPatchSize > 0 { + maxPatchSize = cfg.MaximumPatchSize + } + return newHandlerConfigBuilder(). + AddTemplatableInt("max", c.Max). + AddIfNotEmpty("if_no_changes", c.IfNoChanges). + AddIfNotEmpty("commit_title_suffix", c.CommitTitleSuffix). + AddDefault("max_patch_size", maxPatchSize). + AddIfNotEmpty("target-repo", c.TargetRepoSlug). + AddTemplatableStringSlice("allowed_repos", c.AllowedRepos). + AddIfNotEmpty("github-token", c.GitHubToken). + AddIfTrue("staged", c.Staged). + Build() + }, "update_pull_request": func(cfg *SafeOutputsConfig) map[string]any { if cfg.UpdatePullRequests == nil { return nil diff --git a/pkg/workflow/compiler_safe_outputs_job.go b/pkg/workflow/compiler_safe_outputs_job.go index bd845cafb84..0a28d4d0fca 100644 --- a/pkg/workflow/compiler_safe_outputs_job.go +++ b/pkg/workflow/compiler_safe_outputs_job.go @@ -91,11 +91,11 @@ func (c *Compiler) buildSafeOutputsSetupAndDownloadSteps(data *WorkflowData, age // In workflow_call context, use the per-invocation prefix to avoid artifact name clashes. steps = append(steps, buildAgentOutputDownloadSteps(agentArtifactPrefix)...) - // Add patch artifact download if create-pull-request or push-to-pull-request-branch is enabled - // Both of these safe outputs require the patch file to apply changes + // Add patch artifact download if create-pull-request, push-to-pull-request-branch, or edit-wiki is enabled. + // All of these safe outputs require the patch file to apply changes. // Download from unified agent artifact (prefixed in workflow_call context) if usesPatchesAndCheckouts(data.SafeOutputs) { - consolidatedSafeOutputsJobLog.Print("Adding patch artifact download for create-pull-request or push-to-pull-request-branch") + consolidatedSafeOutputsJobLog.Print("Adding patch artifact download for create-pull-request, push-to-pull-request-branch, or edit-wiki") patchDownloadSteps := buildArtifactDownloadSteps(ArtifactDownloadConfig{ ArtifactName: agentArtifactPrefix + constants.AgentArtifactName, DownloadPath: "/tmp/gh-aw/", @@ -104,10 +104,14 @@ func (c *Compiler) buildSafeOutputsSetupAndDownloadSteps(data *WorkflowData, age }) steps = append(steps, patchDownloadSteps...) - // Add checkout and git config steps for PR operations - consolidatedSafeOutputsJobLog.Print("Adding shared checkout step for PR operations") - checkoutSteps := c.buildSharedPRCheckoutSteps(data) - steps = append(steps, checkoutSteps...) + // Add checkout and git config steps only for PR-based operations. + // edit-wiki clones the wiki repository at runtime in its handler and + // does not need a compile-time checkout of the source repository. + if usesPRCheckout(data.SafeOutputs) { + consolidatedSafeOutputsJobLog.Print("Adding shared checkout step for PR operations") + checkoutSteps := c.buildSharedPRCheckoutSteps(data) + steps = append(steps, checkoutSteps...) + } } // Configure GH_HOST for GHES/GHEC compatibility. @@ -483,7 +487,7 @@ func (c *Compiler) buildSafeOutputsJobFromParts( // "Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under .../actions/setup". // We add a restore checkout step (if: always()) as the last step so the post-step // can always find action.yml and complete its /tmp/gh-aw cleanup. - if c.actionMode.IsDev() && usesPatchesAndCheckouts(data.SafeOutputs) { + if c.actionMode.IsDev() && usesPRCheckout(data.SafeOutputs) { steps = append(steps, c.generateRestoreActionsSetupStep()) consolidatedSafeOutputsJobLog.Print("Added restore actions folder step to safe_outputs job (dev mode with checkout)") } diff --git a/pkg/workflow/compiler_types.go b/pkg/workflow/compiler_types.go index cd6b77d8bfc..9f7054178f6 100644 --- a/pkg/workflow/compiler_types.go +++ b/pkg/workflow/compiler_types.go @@ -587,6 +587,7 @@ type SafeOutputsConfig struct { UpdatePullRequests *UpdatePullRequestsConfig `yaml:"update-pull-request,omitempty"` // Update GitHub pull request title/body MergePullRequest *MergePullRequestConfig `yaml:"merge-pull-request,omitempty"` // Merge pull requests under constrained policy checks PushToPullRequestBranch *PushToPullRequestBranchConfig `yaml:"push-to-pull-request-branch,omitempty"` + EditWiki *EditWikiConfig `yaml:"edit-wiki,omitempty"` // Push changes to a repository's wiki UploadAssets *UploadAssetsConfig `yaml:"upload-asset,omitempty"` UploadArtifact *UploadArtifactConfig `yaml:"upload-artifact,omitempty"` // Upload files as run-scoped GitHub Actions artifacts UpdateRelease *UpdateReleaseConfig `yaml:"update-release,omitempty"` // Update GitHub release descriptions diff --git a/pkg/workflow/edit_wiki.go b/pkg/workflow/edit_wiki.go new file mode 100644 index 00000000000..3b0a8bb77a3 --- /dev/null +++ b/pkg/workflow/edit_wiki.go @@ -0,0 +1,75 @@ +package workflow + +import ( + "fmt" + "os" + + "github.com/github/gh-aw/pkg/logger" +) + +var editWikiLog = logger.New("workflow:edit_wiki") + +// EditWikiConfig holds configuration for pushing changes to a repository's wiki +type EditWikiConfig struct { + BaseSafeOutputConfig `yaml:",inline"` + TargetRepoSlug string `yaml:"repo,omitempty"` // Target repository in format "owner/repo". Defaults to the current repository. + AllowedRepos []string `yaml:"allowed-repos,omitempty"` // List of repositories in format "owner/repo" that the wiki edit can target + IfNoChanges string `yaml:"if-no-changes,omitempty"` // Behavior when no changes to push: "warn", "error", or "ignore" (default: "warn") + CommitTitleSuffix string `yaml:"commit-title-suffix,omitempty"` // Optional suffix to append to generated commit titles +} + +// parseEditWikiConfig handles edit-wiki configuration +func (c *Compiler) parseEditWikiConfig(outputMap map[string]any) *EditWikiConfig { + if configData, exists := outputMap["edit-wiki"]; exists { + editWikiLog.Print("Parsing edit-wiki configuration") + editWikiConfig := &EditWikiConfig{ + IfNoChanges: "warn", // Default behavior: warn when no changes + } + + // Handle the case where configData is nil (edit-wiki: with no value) + if configData == nil { + return editWikiConfig + } + + if configMap, ok := configData.(map[string]any); ok { + // Parse repo (optional, defaults to current repository) + if repo, exists := configMap["repo"]; exists { + if repoStr, ok := repo.(string); ok { + editWikiConfig.TargetRepoSlug = repoStr + } + } + + // Parse allowed-repos (expression-aware) + editWikiConfig.AllowedRepos = ParseStringArrayOrExprFromConfig(configMap, "allowed-repos", editWikiLog) + + // Parse if-no-changes (optional, defaults to "warn") + if ifNoChanges, exists := configMap["if-no-changes"]; exists { + if ifNoChangesStr, ok := ifNoChanges.(string); ok { + switch ifNoChangesStr { + case "warn", "error", "ignore": + editWikiConfig.IfNoChanges = ifNoChangesStr + default: + if c.verbose { + fmt.Fprintf(os.Stderr, "Warning: invalid if-no-changes value '%s' for edit-wiki, using default 'warn'\n", ifNoChangesStr) + } + editWikiConfig.IfNoChanges = "warn" + } + } + } + + // Parse commit-title-suffix (optional) + if commitTitleSuffix, exists := configMap["commit-title-suffix"]; exists { + if commitTitleSuffixStr, ok := commitTitleSuffix.(string); ok { + editWikiConfig.CommitTitleSuffix = commitTitleSuffixStr + } + } + + // Parse common base fields with default max of 0 (no limit) + c.parseBaseSafeOutputConfig(configMap, &editWikiConfig.BaseSafeOutputConfig, 0) + } + + return editWikiConfig + } + + return nil +} diff --git a/pkg/workflow/edit_wiki_test.go b/pkg/workflow/edit_wiki_test.go new file mode 100644 index 00000000000..45be8729eec --- /dev/null +++ b/pkg/workflow/edit_wiki_test.go @@ -0,0 +1,372 @@ +//go:build !integration + +package workflow + +import ( + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/github/gh-aw/pkg/stringutil" + "github.com/github/gh-aw/pkg/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.yaml.in/yaml/v3" +) + +// extractEditWikiHandlerConfig extracts the edit_wiki handler config from a compiled +// lock file's GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG env var. +func extractEditWikiHandlerConfig(t *testing.T, lockContent []byte) map[string]any { + t.Helper() + + var workflowDoc map[string]any + require.NoError(t, yaml.Unmarshal(lockContent, &workflowDoc), "Failed to unmarshal lock workflow YAML") + + jobsRaw, ok := workflowDoc["jobs"].(map[string]any) + require.True(t, ok, "Generated workflow should contain jobs map") + + safeOutputsJobRaw, ok := jobsRaw["safe_outputs"].(map[string]any) + require.True(t, ok, "Generated workflow should contain safe_outputs job") + + stepsRaw, ok := safeOutputsJobRaw["steps"].([]any) + require.True(t, ok, "Generated workflow safe_outputs job should contain steps array") + + var handlerConfigJSON string + for _, step := range stepsRaw { + stepMap, ok := step.(map[string]any) + if !ok { + continue + } + envMap, ok := stepMap["env"].(map[string]any) + if !ok { + continue + } + rawConfig, ok := envMap["GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG"].(string) + if ok && rawConfig != "" { + handlerConfigJSON = rawConfig + break + } + } + + require.NotEmpty(t, handlerConfigJSON, "Generated workflow should contain GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG env var") + + var handlerConfig map[string]any + require.NoError(t, json.Unmarshal([]byte(handlerConfigJSON), &handlerConfig), "Failed to unmarshal GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG JSON") + + editWikiCfgRaw, ok := handlerConfig["edit_wiki"].(map[string]any) + require.True(t, ok, "Handler config should contain edit_wiki object") + + return editWikiCfgRaw +} + +func TestEditWikiConfigParsing(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + issues: + types: [opened] +safe-outputs: + edit-wiki: + noop: + report-as-issue: false +--- + +# Test Edit Wiki + +This is a test workflow to validate edit-wiki configuration parsing. +` + + mdFile := filepath.Join(tmpDir, "test-edit-wiki.md") + require.NoError(t, os.WriteFile(mdFile, []byte(testMarkdown), 0644), "Failed to write test markdown file") + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(mdFile), "Failed to compile workflow") + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + require.NoError(t, err, "Failed to read lock file") + + lockContentStr := string(lockContent) + + // Verify safe_outputs job is generated + assert.Contains(t, lockContentStr, "safe_outputs:", "Generated workflow should contain safe_outputs job") + + // Verify handler manager step is present + assert.Contains(t, lockContentStr, "id: process_safe_outputs", "Generated workflow should contain process_safe_outputs step") + + // Verify edit_wiki config is in handler manager config + assert.Contains(t, lockContentStr, "edit_wiki", "Generated workflow should contain edit_wiki in handler config") + + // Verify that required permissions are present + safeOutputsJobSection := extractJobSection(lockContentStr, "safe_outputs") + assert.NotEmpty(t, safeOutputsJobSection, "safe_outputs job section should be present") + assert.Contains(t, safeOutputsJobSection, "contents: write", "Generated workflow should have contents: write permission") + + // Verify that the patch download step is included (edit-wiki needs patches) + assert.Contains(t, lockContentStr, "Download patch artifact", "Generated workflow should download patch artifact") + + // Verify there is no Checkout repository step specifically for the main repo in the safe_outputs job + // (edit-wiki does not need a compile-time checkout of the source repo) + assert.NotContains(t, safeOutputsJobSection, "Checkout repository", "edit-wiki alone should not generate a repo checkout step") +} + +func TestEditWikiWithAllowedRepos(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + issues: + types: [opened] +safe-outputs: + edit-wiki: + allowed-repos: + - "org/other-repo" + noop: + report-as-issue: false +--- + +# Test Edit Wiki Allowed Repos +` + + mdFile := filepath.Join(tmpDir, "test-edit-wiki-allowed-repos.md") + require.NoError(t, os.WriteFile(mdFile, []byte(testMarkdown), 0644), "Failed to write test markdown file") + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(mdFile), "Failed to compile workflow") + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + require.NoError(t, err, "Failed to read lock file") + + wikiCfg := extractEditWikiHandlerConfig(t, lockContent) + + // Verify allowed_repos is in the handler config + allowedRepos, exists := wikiCfg["allowed_repos"] + assert.True(t, exists, "edit_wiki handler config should contain allowed_repos") + allowedReposSlice, ok := allowedRepos.([]any) + assert.True(t, ok, "allowed_repos should be a slice") + assert.Len(t, allowedReposSlice, 1, "allowed_repos should have 1 entry") + assert.Equal(t, "org/other-repo", allowedReposSlice[0], "allowed_repos should contain org/other-repo") +} + +func TestEditWikiWithTargetRepo(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + issues: + types: [opened] +safe-outputs: + edit-wiki: + repo: "org/target-repo" + noop: + report-as-issue: false +--- + +# Test Edit Wiki Target Repo +` + + mdFile := filepath.Join(tmpDir, "test-edit-wiki-target-repo.md") + require.NoError(t, os.WriteFile(mdFile, []byte(testMarkdown), 0644), "Failed to write test markdown file") + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(mdFile), "Failed to compile workflow") + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + require.NoError(t, err, "Failed to read lock file") + + wikiCfg := extractEditWikiHandlerConfig(t, lockContent) + + // Verify target-repo is in the handler config + targetRepo, exists := wikiCfg["target-repo"] + assert.True(t, exists, "edit_wiki handler config should contain target-repo") + assert.Equal(t, "org/target-repo", targetRepo, "target-repo should be org/target-repo") +} + +func TestEditWikiIfNoChanges(t *testing.T) { + tests := []struct { + name string + ifNoChanges string + expectInJSON string + }{ + { + name: "error value", + ifNoChanges: "error", + expectInJSON: `"if_no_changes":"error"`, + }, + { + name: "ignore value", + ifNoChanges: "ignore", + expectInJSON: `"if_no_changes":"ignore"`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + issues: + types: [opened] +safe-outputs: + edit-wiki: + if-no-changes: ` + tt.ifNoChanges + ` + noop: + report-as-issue: false +--- + +# Test Edit Wiki If No Changes +` + + mdFile := filepath.Join(tmpDir, "test-edit-wiki-if-no-changes.md") + require.NoError(t, os.WriteFile(mdFile, []byte(testMarkdown), 0644), "Failed to write test markdown file") + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(mdFile), "Failed to compile workflow") + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + require.NoError(t, err, "Failed to read lock file") + + lockContentStr := string(lockContent) + assert.True(t, + strings.Contains(lockContentStr, tt.expectInJSON) || + strings.Contains(lockContentStr, strings.ReplaceAll(tt.expectInJSON, `"`, `\"`)), + "Generated workflow should contain if_no_changes=%s in handler config", tt.ifNoChanges, + ) + }) + } +} + +func TestEditWikiPermissions(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + issues: + types: [opened] +safe-outputs: + edit-wiki: + noop: + report-as-issue: false +--- + +# Test Edit Wiki Permissions +` + + mdFile := filepath.Join(tmpDir, "test-edit-wiki-permissions.md") + require.NoError(t, os.WriteFile(mdFile, []byte(testMarkdown), 0644), "Failed to write test markdown file") + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(mdFile), "Failed to compile workflow") + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + require.NoError(t, err, "Failed to read lock file") + + lockContentStr := string(lockContent) + safeOutputsJobSection := extractJobSection(lockContentStr, "safe_outputs") + require.NotEmpty(t, safeOutputsJobSection, "safe_outputs job section should be present") + + // Edit-wiki only requires contents: write (not pull-requests: write) + assert.Contains(t, safeOutputsJobSection, "contents: write", "Generated workflow should have contents: write permission for edit-wiki") + assert.NotContains(t, safeOutputsJobSection, "pull-requests: write", "Generated workflow should NOT have pull-requests: write permission for edit-wiki") +} + +func TestUsesPatchesAndCheckoutsIncludesEditWiki(t *testing.T) { + tests := []struct { + name string + safeOutputs *SafeOutputsConfig + expected bool + }{ + { + name: "nil safe outputs", + safeOutputs: nil, + expected: false, + }, + { + name: "edit-wiki configured", + safeOutputs: &SafeOutputsConfig{ + EditWiki: &EditWikiConfig{}, + }, + expected: true, + }, + { + name: "edit-wiki staged returns false", + safeOutputs: &SafeOutputsConfig{ + EditWiki: &EditWikiConfig{BaseSafeOutputConfig: BaseSafeOutputConfig{Staged: true}}, + }, + expected: false, + }, + { + name: "edit-wiki with globally staged returns false", + safeOutputs: &SafeOutputsConfig{ + Staged: true, + EditWiki: &EditWikiConfig{}, + }, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := usesPatchesAndCheckouts(tt.safeOutputs) + assert.Equal(t, tt.expected, result, "usesPatchesAndCheckouts should return expected value") + }) + } +} + +func TestUsesPRCheckoutExcludesEditWiki(t *testing.T) { + tests := []struct { + name string + safeOutputs *SafeOutputsConfig + expected bool + }{ + { + name: "nil safe outputs", + safeOutputs: nil, + expected: false, + }, + { + name: "edit-wiki only returns false (no PR checkout needed)", + safeOutputs: &SafeOutputsConfig{ + EditWiki: &EditWikiConfig{}, + }, + expected: false, + }, + { + name: "create-pull-request returns true", + safeOutputs: &SafeOutputsConfig{ + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + expected: true, + }, + { + name: "push-to-pull-request-branch returns true", + safeOutputs: &SafeOutputsConfig{ + PushToPullRequestBranch: &PushToPullRequestBranchConfig{}, + }, + expected: true, + }, + { + name: "edit-wiki with create-pull-request returns true", + safeOutputs: &SafeOutputsConfig{ + EditWiki: &EditWikiConfig{}, + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + expected: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := usesPRCheckout(tt.safeOutputs) + assert.Equal(t, tt.expected, result, "usesPRCheckout should return expected value") + }) + } +} diff --git a/pkg/workflow/js/safe_outputs_tools.json b/pkg/workflow/js/safe_outputs_tools.json index 75c123855cb..8714c3fd22e 100644 --- a/pkg/workflow/js/safe_outputs_tools.json +++ b/pkg/workflow/js/safe_outputs_tools.json @@ -1032,6 +1032,31 @@ "additionalProperties": false } }, + { + "name": "edit_wiki", + "description": "Push committed changes to a repository wiki. Use this to add or update wiki pages by committing changes locally and then calling this tool. The changes are applied to the main branch of the wiki.", + "inputSchema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string", + "description": "Commit message describing the wiki changes. Follow repository commit message conventions." + }, + "secrecy": { + "type": "string", + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\")." + }, + "integrity": { + "type": "string", + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\")." + } + }, + "additionalProperties": false + } + }, { "name": "upload_asset", "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content.", diff --git a/pkg/workflow/safe_outputs_config.go b/pkg/workflow/safe_outputs_config.go index b825bc86aa6..aa6b8237646 100644 --- a/pkg/workflow/safe_outputs_config.go +++ b/pkg/workflow/safe_outputs_config.go @@ -271,6 +271,12 @@ func (c *Compiler) extractSafeOutputsConfig(frontmatter map[string]any) *SafeOut config.PushToPullRequestBranch = pushToBranchConfig } + // Handle edit-wiki + editWikiConfig := c.parseEditWikiConfig(outputMap) + if editWikiConfig != nil { + config.EditWiki = editWikiConfig + } + // Handle upload-asset uploadAssetsConfig := c.parseUploadAssetConfig(outputMap) if uploadAssetsConfig != nil { diff --git a/pkg/workflow/safe_outputs_permissions.go b/pkg/workflow/safe_outputs_permissions.go index 6e75492f492..35e85a1354e 100644 --- a/pkg/workflow/safe_outputs_permissions.go +++ b/pkg/workflow/safe_outputs_permissions.go @@ -177,8 +177,11 @@ func ComputePermissionsForSafeOutputs(safeOutputs *SafeOutputsConfig) *Permissio permissions.Set(PermissionAdministration, PermissionRead) } } + if safeOutputs.EditWiki != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.EditWiki.Staged) { + safeOutputsPermissionsLog.Print("Adding permissions for edit-wiki") + permissions.Merge(NewPermissionsContentsWrite()) + } if safeOutputs.UpdatePullRequests != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.UpdatePullRequests.Staged) { - safeOutputsPermissionsLog.Print("Adding permissions for update-pull-request") if safeOutputs.UpdatePullRequests.UpdateBranch != nil && *safeOutputs.UpdatePullRequests.UpdateBranch { safeOutputsPermissionsLog.Print("update-pull-request has update-branch enabled; requiring contents: write") permissions.Merge(NewPermissionsContentsWritePRWrite()) diff --git a/pkg/workflow/safe_outputs_runtime.go b/pkg/workflow/safe_outputs_runtime.go index 04155866f94..5403123adbd 100644 --- a/pkg/workflow/safe_outputs_runtime.go +++ b/pkg/workflow/safe_outputs_runtime.go @@ -36,17 +36,37 @@ func (c *Compiler) formatFrameworkJobRunsOn(data *WorkflowData) string { } // usesPatchesAndCheckouts checks if the workflow uses safe outputs that require -// git patches and checkouts (create-pull-request or push-to-pull-request-branch). +// git patches and checkouts (create-pull-request, push-to-pull-request-branch, or edit-wiki). // Staged handlers are excluded because they only emit preview output and do not // perform real git operations or API calls. func usesPatchesAndCheckouts(safeOutputs *SafeOutputsConfig) bool { + if safeOutputs == nil { + return false + } + createPRNeedsCheckout := safeOutputs.CreatePullRequests != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.CreatePullRequests.Staged) + pushToPRNeedsCheckout := safeOutputs.PushToPullRequestBranch != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.PushToPullRequestBranch.Staged) + editWikiNeedsCheckout := safeOutputs.EditWiki != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.EditWiki.Staged) + result := createPRNeedsCheckout || pushToPRNeedsCheckout || editWikiNeedsCheckout + safeOutputsRuntimeLog.Printf("usesPatchesAndCheckouts: createPR=%v(needsCheckout=%v), pushToPRBranch=%v(needsCheckout=%v), editWiki=%v(needsCheckout=%v), result=%v", + safeOutputs.CreatePullRequests != nil, createPRNeedsCheckout, + safeOutputs.PushToPullRequestBranch != nil, pushToPRNeedsCheckout, + safeOutputs.EditWiki != nil, editWikiNeedsCheckout, + result) + return result +} + +// usesPRCheckout checks if the workflow uses safe outputs that require checking out +// the repository and configuring git (create-pull-request or push-to-pull-request-branch). +// edit-wiki is excluded because the edit-wiki handler clones the wiki repository at +// runtime and does not need a compile-time checkout of the source repository. +func usesPRCheckout(safeOutputs *SafeOutputsConfig) bool { if safeOutputs == nil { return false } createPRNeedsCheckout := safeOutputs.CreatePullRequests != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.CreatePullRequests.Staged) pushToPRNeedsCheckout := safeOutputs.PushToPullRequestBranch != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.PushToPullRequestBranch.Staged) result := createPRNeedsCheckout || pushToPRNeedsCheckout - safeOutputsRuntimeLog.Printf("usesPatchesAndCheckouts: createPR=%v(needsCheckout=%v), pushToPRBranch=%v(needsCheckout=%v), result=%v", + safeOutputsRuntimeLog.Printf("usesPRCheckout: createPR=%v(needsCheckout=%v), pushToPRBranch=%v(needsCheckout=%v), result=%v", safeOutputs.CreatePullRequests != nil, createPRNeedsCheckout, safeOutputs.PushToPullRequestBranch != nil, pushToPRNeedsCheckout, result) diff --git a/pkg/workflow/safe_outputs_tools_repo_params.go b/pkg/workflow/safe_outputs_tools_repo_params.go index 787b213895e..b7cb880f60c 100644 --- a/pkg/workflow/safe_outputs_tools_repo_params.go +++ b/pkg/workflow/safe_outputs_tools_repo_params.go @@ -35,6 +35,11 @@ func addRepoParameterIfNeeded(tool map[string]any, toolName string, safeOutputs hasAllowedRepos = len(config.AllowedRepos) > 0 targetRepoSlug = config.TargetRepoSlug } + case "edit_wiki": + if config := safeOutputs.EditWiki; config != nil { + hasAllowedRepos = len(config.AllowedRepos) > 0 + targetRepoSlug = config.TargetRepoSlug + } case "create_pull_request_review_comment": if config := safeOutputs.CreatePullRequestReviewComments; config != nil { hasAllowedRepos = len(config.AllowedRepos) > 0 From 303202d5adcec1e33b8366c9848db1e9c00fb0ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 21:02:45 +0000 Subject: [PATCH 02/10] fix: restore missing log message for update-pull-request permissions Agent-Logs-Url: https://github.com/github/gh-aw/sessions/62d937c5-0490-4dcd-9f26-4bbb6e05442e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/parser/schemas/main_workflow_schema.json | 2733 ++++-------------- pkg/workflow/safe_outputs_permissions.go | 1 + 2 files changed, 498 insertions(+), 2236 deletions(-) diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index a91117d0bbb..d696597f3d7 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -5,44 +5,30 @@ "description": "JSON Schema for validating agentic workflow frontmatter configuration", "version": "1.0.0", "type": "object", - "required": [ - "on" - ], + "required": ["on"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 256, "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" - ] + "examples": ["Copilot Agent PR Analysis", "Dev Hawk", "Smoke Claude"] }, "description": { "type": "string", "maxLength": 10000, "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" - ] + "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" - ] + "examples": ["githubnext/agentics/workflows/ci-doctor.md", "githubnext/agentics/workflows/daily-perf-improver.md@1f181b37d3fe5862ab590648f25a292e345b5de6"] }, "redirect": { "type": "string", "description": "Optional workflow location redirect for updates. Format: workflow spec or GitHub URL (e.g., owner/repo/path@ref or https://github.com/owner/repo/blob/main/path.md). When present, update follows this location and rewrites source.", - "examples": [ - "githubnext/agentics/workflows/ci-doctor-v2.md@main", - "https://github.com/githubnext/agentics/blob/main/workflows/ci-doctor-v2.md" - ] + "examples": ["githubnext/agentics/workflows/ci-doctor-v2.md@main", "https://github.com/githubnext/agentics/blob/main/workflows/ci-doctor-v2.md"] }, "tracker-id": { "type": "string", @@ -50,11 +36,7 @@ "maxLength": 128, "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" - ] + "examples": ["workflow-2024-q1", "team-alpha-bot", "security_audit_v2"] }, "labels": { "type": "array", @@ -64,18 +46,9 @@ "minLength": 1 }, "examples": [ - [ - "automation", - "security" - ], - [ - "docs", - "maintenance" - ], - [ - "ci", - "testing" - ] + ["automation", "security"], + ["docs", "maintenance"], + ["ci", "testing"] ] }, "metadata": { @@ -112,9 +85,7 @@ { "type": "object", "description": "Import specification with path and optional inputs", - "required": [ - "path" - ], + "required": ["path"], "additionalProperties": false, "properties": { "path": { @@ -160,9 +131,7 @@ { "type": "object", "description": "Import specification with 'uses'/'with' syntax (mirrors GitHub Actions reusable workflow syntax). 'uses' references the workflow path and 'with' provides input values.", - "required": [ - "uses" - ], + "required": ["uses"], "additionalProperties": false, "properties": { "uses": { @@ -247,9 +216,7 @@ { "type": "object", "description": "Import specification with path and optional inputs", - "required": [ - "path" - ], + "required": ["path"], "additionalProperties": false, "properties": { "path": { @@ -295,9 +262,7 @@ { "type": "object", "description": "Import specification with 'uses'/'with' syntax.", - "required": [ - "uses" - ], + "required": ["uses"], "additionalProperties": false, "properties": { "uses": { @@ -369,21 +334,10 @@ } ], "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" - ], + ["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", @@ -393,10 +347,7 @@ } ], { - "aw": [ - "shared/common-tools.md", - "shared/mcp/tavily.md" - ] + "aw": ["shared/common-tools.md", "shared/mcp/tavily.md"] } ] }, @@ -410,45 +361,25 @@ "pattern": "\\$\\{\\{" } }, - "examples": [ - [ - "triage-issue.md", - "label-issue.md" - ], - [ - "my-custom-action.yml" - ], - [ - "shared/helper-action.yml", - "close-stale.md" - ] - ] + "examples": [["triage-issue.md", "label-issue.md"], ["my-custom-action.yml"], ["shared/helper-action.yml", "close-stale.md"]] }, "inlined-imports": { "type": "boolean", "default": false, "description": "If true, inline all imports (including those without inputs) at compilation time in the generated lock.yml instead of using runtime-import macros. When enabled, the frontmatter hash covers the entire markdown body so any change to the content will invalidate the hash.", - "examples": [ - true, - false - ] + "examples": [true, false] }, "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" - ] + "types": ["opened"] } }, { "pull_request": { - "types": [ - "opened", - "synchronize" - ] + "types": ["opened", "synchronize"] } }, "workflow_dispatch", @@ -462,13 +393,7 @@ "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" - ] + "examples": ["push", "issues", "workflow_dispatch", "daily", "/my-bot"] }, { "type": "object", @@ -520,16 +445,7 @@ { "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" - ] + "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] }, { "type": "array", @@ -538,16 +454,7 @@ "items": { "type": "string", "description": "GitHub Actions event name.", - "enum": [ - "*", - "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"] }, "maxItems": 25 } @@ -604,16 +511,7 @@ { "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" - ] + "enum": ["*", "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment", "discussion", "discussion_comment"] }, { "type": "array", @@ -622,16 +520,7 @@ "items": { "type": "string", "description": "GitHub Actions event name.", - "enum": [ - "*", - "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"] }, "maxItems": 25 } @@ -702,12 +591,7 @@ { "type": "string", "description": "Single item type or '*' for all types.", - "enum": [ - "*", - "issues", - "pull_request", - "discussion" - ] + "enum": ["*", "issues", "pull_request", "discussion"] }, { "type": "array", @@ -716,12 +600,7 @@ "items": { "type": "string", "description": "Item type.", - "enum": [ - "*", - "issues", - "pull_request", - "discussion" - ] + "enum": ["*", "issues", "pull_request", "discussion"] }, "maxItems": 3 } @@ -790,37 +669,25 @@ }, "oneOf": [ { - "required": [ - "branches" - ], + "required": ["branches"], "not": { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } }, { - "required": [ - "branches-ignore" - ], + "required": ["branches-ignore"], "not": { - "required": [ - "branches" - ] + "required": ["branches"] } }, { "not": { "anyOf": [ { - "required": [ - "branches" - ] + "required": ["branches"] }, { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } ] } @@ -830,37 +697,25 @@ { "oneOf": [ { - "required": [ - "paths" - ], + "required": ["paths"], "not": { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } }, { - "required": [ - "paths-ignore" - ], + "required": ["paths-ignore"], "not": { - "required": [ - "paths" - ] + "required": ["paths"] } }, { "not": { "anyOf": [ { - "required": [ - "paths" - ] + "required": ["paths"] }, { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } ] } @@ -980,37 +835,25 @@ "additionalProperties": false, "oneOf": [ { - "required": [ - "branches" - ], + "required": ["branches"], "not": { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } }, { - "required": [ - "branches-ignore" - ], + "required": ["branches-ignore"], "not": { - "required": [ - "branches" - ] + "required": ["branches"] } }, { "not": { "anyOf": [ { - "required": [ - "branches" - ] + "required": ["branches"] }, { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } ] } @@ -1020,37 +863,25 @@ { "oneOf": [ { - "required": [ - "paths" - ], + "required": ["paths"], "not": { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } }, { - "required": [ - "paths-ignore" - ], + "required": ["paths-ignore"], "not": { - "required": [ - "paths" - ] + "required": ["paths"] } }, { "not": { "anyOf": [ { - "required": [ - "paths" - ] + "required": ["paths"] }, { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } ] } @@ -1069,26 +900,7 @@ "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" - ] + "enum": ["opened", "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", "milestoned", "demilestoned", "typed", "untyped"] } }, "names": { @@ -1126,11 +938,7 @@ "description": "Types of issue comment events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted" - ] + "enum": ["created", "edited", "deleted"] } }, "lock-for-agent": { @@ -1149,21 +957,7 @@ "description": "Types of discussion events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted", - "transferred", - "pinned", - "unpinned", - "labeled", - "unlabeled", - "locked", - "unlocked", - "category_changed", - "answered", - "unanswered" - ] + "enum": ["created", "edited", "deleted", "transferred", "pinned", "unpinned", "labeled", "unlabeled", "locked", "unlocked", "category_changed", "answered", "unanswered"] } } } @@ -1178,11 +972,7 @@ "description": "Types of discussion comment events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted" - ] + "enum": ["created", "edited", "deleted"] } } } @@ -1211,9 +1001,7 @@ "description": "Optional IANA timezone string for timezone-aware scheduling (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'UTC'). When set, the cron expression is interpreted in the specified timezone instead of UTC." } }, - "required": [ - "cron" - ], + "required": ["cron"], "additionalProperties": false }, "maxItems": 10 @@ -1263,13 +1051,7 @@ }, "type": { "type": "string", - "enum": [ - "string", - "choice", - "boolean", - "number", - "environment" - ], + "enum": ["string", "choice", "boolean", "number", "environment"], "description": "Input type. GitHub Actions supports: string (default), boolean, choice (string with predefined options), number, and environment (string referencing a GitHub environment)" }, "options": { @@ -1303,11 +1085,7 @@ "description": "Types of workflow run events", "items": { "type": "string", - "enum": [ - "completed", - "requested", - "in_progress" - ] + "enum": ["completed", "requested", "in_progress"] } }, "branches": { @@ -1329,37 +1107,25 @@ }, "oneOf": [ { - "required": [ - "branches" - ], + "required": ["branches"], "not": { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } }, { - "required": [ - "branches-ignore" - ], + "required": ["branches-ignore"], "not": { - "required": [ - "branches" - ] + "required": ["branches"] } }, { "not": { "anyOf": [ { - "required": [ - "branches" - ] + "required": ["branches"] }, { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } ] } @@ -1376,15 +1142,7 @@ "description": "Types of release events", "items": { "type": "string", - "enum": [ - "published", - "unpublished", - "created", - "edited", - "deleted", - "prereleased", - "released" - ] + "enum": ["published", "unpublished", "created", "edited", "deleted", "prereleased", "released"] } } } @@ -1399,11 +1157,7 @@ "description": "Types of pull request review comment events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted" - ] + "enum": ["created", "edited", "deleted"] } } } @@ -1418,11 +1172,7 @@ "description": "Types of branch protection rule events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted" - ] + "enum": ["created", "edited", "deleted"] } } } @@ -1437,12 +1187,7 @@ "description": "Types of check run events", "items": { "type": "string", - "enum": [ - "created", - "rerequested", - "completed", - "requested_action" - ] + "enum": ["created", "rerequested", "completed", "requested_action"] } } } @@ -1457,9 +1202,7 @@ "description": "Types of check suite events", "items": { "type": "string", - "enum": [ - "completed" - ] + "enum": ["completed"] } } } @@ -1519,31 +1262,13 @@ "oneOf": [ { "type": "string", - "enum": [ - "error", - "failure", - "pending", - "success", - "inactive", - "in_progress", - "queued", - "waiting" - ] + "enum": ["error", "failure", "pending", "success", "inactive", "in_progress", "queued", "waiting"] }, { "type": "array", "items": { "type": "string", - "enum": [ - "error", - "failure", - "pending", - "success", - "inactive", - "in_progress", - "queued", - "waiting" - ] + "enum": ["error", "failure", "pending", "success", "inactive", "in_progress", "queued", "waiting"] }, "minItems": 1 } @@ -1589,11 +1314,7 @@ "description": "Types of label events", "items": { "type": "string", - "enum": [ - "created", - "edited", - "deleted" - ] + "enum": ["created", "edited", "deleted"] } } } @@ -1608,9 +1329,7 @@ "description": "Types of merge group events", "items": { "type": "string", - "enum": [ - "checks_requested" - ] + "enum": ["checks_requested"] } } } @@ -1625,13 +1344,7 @@ "description": "Types of milestone events", "items": { "type": "string", - "enum": [ - "created", - "closed", - "opened", - "edited", - "deleted" - ] + "enum": ["created", "closed", "opened", "edited", "deleted"] } } } @@ -1749,37 +1462,25 @@ "additionalProperties": false, "oneOf": [ { - "required": [ - "branches" - ], + "required": ["branches"], "not": { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } }, { - "required": [ - "branches-ignore" - ], + "required": ["branches-ignore"], "not": { - "required": [ - "branches" - ] + "required": ["branches"] } }, { "not": { "anyOf": [ { - "required": [ - "branches" - ] + "required": ["branches"] }, { - "required": [ - "branches-ignore" - ] + "required": ["branches-ignore"] } ] } @@ -1789,37 +1490,25 @@ { "oneOf": [ { - "required": [ - "paths" - ], + "required": ["paths"], "not": { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } }, { - "required": [ - "paths-ignore" - ], + "required": ["paths-ignore"], "not": { - "required": [ - "paths" - ] + "required": ["paths"] } }, { "not": { "anyOf": [ { - "required": [ - "paths" - ] + "required": ["paths"] }, { - "required": [ - "paths-ignore" - ] + "required": ["paths-ignore"] } ] } @@ -1838,11 +1527,7 @@ "description": "Types of pull request review events", "items": { "type": "string", - "enum": [ - "submitted", - "edited", - "dismissed" - ] + "enum": ["submitted", "edited", "dismissed"] } } } @@ -1857,10 +1542,7 @@ "description": "Types of registry package events", "items": { "type": "string", - "enum": [ - "published", - "updated" - ] + "enum": ["published", "updated"] } } } @@ -1902,9 +1584,7 @@ "description": "Types of watch events", "items": { "type": "string", - "enum": [ - "started" - ] + "enum": ["started"] } } } @@ -1936,11 +1616,7 @@ }, "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean" - ], + "enum": ["string", "number", "boolean"], "description": "Type of the input parameter" }, "default": { @@ -1982,9 +1658,7 @@ }, { "type": "object", - "required": [ - "query" - ], + "required": ["query"], "properties": { "query": { "type": "string", @@ -2006,9 +1680,7 @@ }, "scope": { "type": "string", - "enum": [ - "none" - ], + "enum": ["none"], "description": "Scope for the search query. Set to 'none' to disable the automatic 'repo:owner/repo' scoping, enabling org-wide or cross-repo queries." } }, @@ -2026,9 +1698,7 @@ }, { "type": "object", - "required": [ - "query" - ], + "required": ["query"], "properties": { "query": { "type": "string", @@ -2041,9 +1711,7 @@ }, "scope": { "type": "string", - "enum": [ - "none" - ], + "enum": ["none"], "description": "Scope for the search query. Set to 'none' to disable the automatic 'repo:owner/repo' scoping, enabling org-wide or cross-repo queries." } }, @@ -2061,9 +1729,7 @@ }, { "type": "boolean", - "enum": [ - true - ], + "enum": [true], "description": "Skip workflow execution if any CI checks on the target branch are currently failing. For pull_request events, checks the base branch. For other events, checks the current ref." }, { @@ -2137,15 +1803,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "admin", - "maintainer", - "maintain", - "write", - "triage", - "read", - "all" - ], + "enum": ["admin", "maintainer", "maintain", "write", "triage", "read", "all"], "description": "Single repository permission level that can trigger the workflow. Use 'all' to allow any authenticated user (\u26a0\ufe0f disables permission checking entirely - use with caution)" }, { @@ -2153,14 +1811,7 @@ "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", - "read" - ], + "enum": ["admin", "maintainer", "maintain", "write", "triage", "read"], "description": "Repository permission level: 'admin' (full access), 'maintainer'/'maintain' (repository management), 'write' (push access), 'triage' (issue management), 'read' (read-only access)" }, "minItems": 1, @@ -2203,24 +1854,11 @@ "oneOf": [ { "type": "string", - "enum": [ - "+1", - "-1", - "laugh", - "confused", - "heart", - "hooray", - "rocket", - "eyes", - "none" - ] + "enum": ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes", "none"] }, { "type": "integer", - "enum": [ - 1, - -1 - ], + "enum": [1, -1], "description": "YAML parses +1 and -1 without quotes as integers. These are converted to +1 and -1 strings respectively." }, { @@ -2231,24 +1869,11 @@ "oneOf": [ { "type": "string", - "enum": [ - "+1", - "-1", - "laugh", - "confused", - "heart", - "hooray", - "rocket", - "eyes", - "none" - ] + "enum": ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes", "none"] }, { "type": "integer", - "enum": [ - 1, - -1 - ], + "enum": [1, -1], "description": "YAML parses +1 and -1 without quotes as integers. These are converted to +1 and -1 strings respectively." } ], @@ -2335,9 +1960,7 @@ "github-token": { "type": "string", "description": "Custom GitHub token for pre-activation reactions, activation status comments, and skip-if search queries. When specified, overrides the default GITHUB_TOKEN for these operations.", - "examples": [ - "${{ secrets.MY_GITHUB_TOKEN }}" - ] + "examples": ["${{ secrets.MY_GITHUB_TOKEN }}"] }, "github-app": { "$ref": "#/$defs/github_app", @@ -2359,11 +1982,7 @@ "additionalItems": false, "uniqueItems": true, "default": [], - "examples": [ - [ - "secrets_fetcher" - ] - ] + "examples": [["secrets_fetcher"]] }, "steps": { "type": "array", @@ -2475,99 +2094,51 @@ "properties": { "actions": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "checks": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "contents": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "deployments": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "discussions": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "issues": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "packages": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "pages": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "pull-requests": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "repository-projects": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "security-events": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] }, "statuses": { "type": "string", - "enum": [ - "read", - "write", - "none" - ] + "enum": ["read", "write", "none"] } }, "additionalProperties": false @@ -2610,37 +2181,25 @@ { "command": { "name": "mergefest", - "events": [ - "pull_request_comment" - ] + "events": ["pull_request_comment"] } }, { "workflow_run": { - "workflows": [ - "Dev" - ], - "types": [ - "completed" - ], - "branches": [ - "copilot/**" - ] + "workflows": ["Dev"], + "types": ["completed"], + "branches": ["copilot/**"] } }, { "pull_request": { - "types": [ - "ready_for_review" - ] + "types": ["ready_for_review"] }, "workflow_dispatch": null }, { "push": { - "branches": [ - "main" - ] + "branches": ["main"] } } ] @@ -2667,10 +2226,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "read-all", - "write-all" - ], + "enum": ["read-all", "write-all"], "description": "Simple permissions string: 'read-all' (all read permissions) or 'write-all' (all write permissions)" }, { @@ -2681,10 +2237,7 @@ "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 }}" - ] + "examples": ["Deploy to ${{ github.event.inputs.environment }}", "Build #${{ github.run_number }}"] }, "jobs": { "type": "object", @@ -2727,14 +2280,10 @@ "additionalProperties": false, "oneOf": [ { - "required": [ - "uses" - ] + "required": ["uses"] }, { - "required": [ - "run" - ] + "required": ["run"] } ], "properties": { @@ -2954,9 +2503,7 @@ "description": "The URL to set as the environment URL in the deployment." } }, - "required": [ - "name" - ] + "required": ["name"] } ], "description": "The GitHub Actions environment this job references. When set, any protection rules for the environment must pass before the job runs. Use this to gate jobs on manual approval workflows." @@ -3069,26 +2616,17 @@ ], "examples": [ "ubuntu-latest", - [ - "ubuntu-latest", - "self-hosted" - ], + ["ubuntu-latest", "self-hosted"], { "group": "larger-runners", - "labels": [ - "ubuntu-latest-8-cores" - ] + "labels": ["ubuntu-latest-8-cores"] } ] }, "runs-on-slim": { "type": "string", "description": "Runner for all framework/generated jobs (activation, pre-activation, safe-outputs, unlock, APM, etc.). Provides a compile-stable override for generated job runners without requiring a safe-outputs section. Overridden by safe-outputs.runs-on when both are set. Defaults to 'ubuntu-slim'. Use this when your infrastructure does not provide the default runner or when you need consistent runner selection across all jobs.", - "examples": [ - "self-hosted", - "ubuntu-latest", - "ubuntu-22.04" - ] + "examples": ["self-hosted", "ubuntu-latest", "ubuntu-22.04"] }, "timeout-minutes": { "description": "Workflow timeout in minutes (GitHub Actions standard field). Defaults to 20 minutes for agentic workflows. Has sensible defaults and can typically be omitted. Custom runners support longer timeouts beyond the GitHub-hosted runner limit. Supports GitHub Actions expressions (e.g. '${{ inputs.timeout }}') for reusable workflow_call workflows.", @@ -3096,11 +2634,7 @@ { "type": "integer", "minimum": 1, - "examples": [ - 5, - 10, - 30 - ] + "examples": [5, 10, 30] }, { "type": "string", @@ -3115,10 +2649,7 @@ { "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 }}" - ] + "examples": ["my-workflow-group", "workflow-${{ github.ref }}"] }, { "type": "object", @@ -3136,11 +2667,7 @@ "job-discriminator": { "type": "string", "description": "Additional discriminator expression appended to compiler-generated job-level concurrency groups (agent, output jobs). Use this when multiple workflow instances are dispatched concurrently with different inputs (fan-out pattern) to prevent job-level concurrency groups from colliding. For example, '${{ inputs.finding_id }}' ensures each dispatched run gets a unique job-level group. Supports GitHub Actions expressions. This field is stripped from the compiled lock file (it is a gh-aw extension, not a GitHub Actions field).", - "examples": [ - "${{ inputs.finding_id }}", - "${{ inputs.item_id }}", - "${{ github.run_id }}" - ] + "examples": ["${{ inputs.finding_id }}", "${{ inputs.item_id }}", "${{ github.run_id }}"] } }, "required": [], @@ -3220,37 +2747,23 @@ }, "examples": [ { - "feature1": [ - "A", - "B" - ] + "feature1": ["A", "B"] }, { - "prompt_style": [ - "concise", - "detailed", - "structured" - ], - "model_temp": [ - "low", - "high" - ] + "prompt_style": ["concise", "detailed", "structured"], + "model_temp": ["low", "high"] } ] }, "infer": { "type": "boolean", "description": "DEPRECATED: Use 'disable-model-invocation' instead. Controls whether the custom agent should infer additional context from the conversation. This field is maintained for backward compatibility with existing custom agent files.", - "examples": [ - false - ] + "examples": [false] }, "disable-model-invocation": { "type": "boolean", "description": "Controls whether the custom agent should disable model invocation. When set to true, the agent will not make additional model calls. This is the preferred field name for custom agent files (replaces the deprecated 'infer' field).", - "examples": [ - true - ] + "examples": [true] }, "secrets": { "description": "Secret values passed to workflow execution. Secrets can be defined as simple strings (GitHub Actions expressions) or objects with 'value' and 'description' properties. Typically used to provide secrets to MCP servers or custom engines. Note: For passing secrets to reusable workflows, use the jobs..secrets field instead.", @@ -3264,9 +2777,7 @@ { "type": "object", "description": "Secret with metadata", - "required": [ - "value" - ], + "required": ["value"], "properties": { "value": { "type": "string", @@ -3318,9 +2829,7 @@ "description": "A deployment URL" } }, - "required": [ - "name" - ], + "required": ["name"], "additionalProperties": false } ] @@ -3388,9 +2897,7 @@ "description": "Additional Docker container options" } }, - "required": [ - "image" - ], + "required": ["image"], "additionalProperties": false } ] @@ -3460,9 +2967,7 @@ "description": "Additional Docker container options" } }, - "required": [ - "image" - ], + "required": ["image"], "additionalProperties": false } ] @@ -3474,26 +2979,16 @@ "examples": [ "defaults", { - "allowed": [ - "defaults", - "github" - ] + "allowed": ["defaults", "github"] }, { - "allowed": [ - "defaults", - "python", - "node", - "*.example.com" - ] + "allowed": ["defaults", "python", "node", "*.example.com"] } ], "oneOf": [ { "type": "string", - "enum": [ - "defaults" - ], + "enum": ["defaults"], "description": "Use default network permissions (basic infrastructure: certificates, JSON schema, Ubuntu, etc.)" }, { @@ -3528,10 +3023,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "default", - "awf" - ], + "enum": ["default", "awf"], "description": "String format for sandbox type: 'default' for no sandbox, 'awf' for Agent Workflow Firewall. Note: Legacy 'srt' and 'sandbox-runtime' values are automatically migrated to 'awf'" }, { @@ -3540,10 +3032,7 @@ "properties": { "type": { "type": "string", - "enum": [ - "default", - "awf" - ], + "enum": ["default", "awf"], "description": "Legacy sandbox type field (use agent instead). Note: Legacy 'srt' and 'sandbox-runtime' values are automatically migrated to 'awf'" }, "agent": { @@ -3557,9 +3046,7 @@ }, { "type": "string", - "enum": [ - "awf" - ], + "enum": ["awf"], "description": "Sandbox type: 'awf' for Agent Workflow Firewall" }, { @@ -3568,16 +3055,12 @@ "properties": { "id": { "type": "string", - "enum": [ - "awf" - ], + "enum": ["awf"], "description": "Agent identifier (replaces 'type' field in new format): 'awf' for Agent Workflow Firewall" }, "type": { "type": "string", - "enum": [ - "awf" - ], + "enum": ["awf"], "description": "Legacy: Sandbox type to use (use 'id' instead)" }, "version": { @@ -3613,22 +3096,13 @@ "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" - ] - ] + "examples": [["/host/data:/data:ro", "/usr/local/bin/custom-tool:/usr/local/bin/custom-tool:ro"]] }, "memory": { "type": "string", "description": "Memory limit for the AWF container (e.g., '4g', '8g'). Passed as --memory-limit to AWF. If not specified, AWF's default memory limit is used.", "pattern": "^[0-9]+(b|k|m|g|kb|mb|gb|B|K|M|G|KB|MB|GB)$", - "examples": [ - "4g", - "8g", - "512m" - ] + "examples": ["4g", "8g", "512m"] }, "config": { "type": "object", @@ -3744,26 +3218,16 @@ "description": "Container image for the MCP gateway executable (required)" }, "version": { - "type": [ - "string", - "number" - ], + "type": ["string", "number"], "x-internal": true, "description": "Optional version/tag for the container image (e.g., 'latest', 'v1.0.0')", - "examples": [ - "latest", - "v1.0.0" - ] + "examples": ["latest", "v1.0.0"] }, "entrypoint": { "type": "string", "x-internal": true, "description": "Optional custom entrypoint for the MCP gateway container. Overrides the container's default entrypoint.", - "examples": [ - "/bin/bash", - "/custom/start.sh", - "/usr/bin/env" - ] + "examples": ["/bin/bash", "/custom/start.sh", "/usr/bin/env"] }, "args": { "type": "array", @@ -3789,12 +3253,7 @@ "pattern": "^[^:]+:[^:]+:(ro|rw)$", "description": "Mount specification in format 'source:destination:mode'" }, - "examples": [ - [ - "/host/data:/container/data:ro", - "/host/config:/container/config:rw" - ] - ] + "examples": [["/host/data:/container/data:ro", "/host/config:/container/config:rw"]] }, "env": { "type": "object", @@ -3819,22 +3278,14 @@ }, "domain": { "type": "string", - "enum": [ - "localhost", - "host.docker.internal" - ], + "enum": ["localhost", "host.docker.internal"], "description": "Gateway domain for URL generation (default: 'host.docker.internal' when agent is enabled, 'localhost' when disabled)" }, "keepalive-interval": { "type": "integer", "description": "Keepalive ping interval in seconds for HTTP MCP backends. Sends periodic pings to prevent session expiry during long-running agent tasks. Set to -1 to disable keepalive pings. Unset or 0 uses the gateway default (1500 seconds = 25 minutes).", "minimum": -1, - "examples": [ - -1, - 300, - 600, - 1500 - ] + "examples": [-1, 300, 600, 1500] } }, "additionalProperties": false @@ -3867,10 +3318,7 @@ "if": { "type": "string", "description": "Conditional execution expression", - "examples": [ - "${{ github.event.workflow_run.event == 'workflow_dispatch' }}", - "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}" - ] + "examples": ["${{ github.event.workflow_run.event == 'workflow_dispatch' }}", "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}"] }, "steps": { "description": "Custom workflow steps", @@ -4054,10 +3502,7 @@ "filesystem": { "type": "stdio", "command": "npx", - "args": [ - "-y", - "@modelcontextprotocol/server-filesystem" - ] + "args": ["-y", "@modelcontextprotocol/server-filesystem"] } }, { @@ -4134,33 +3579,18 @@ }, "mode": { "type": "string", - "enum": [ - "gh-proxy", - "local", - "remote" - ], + "enum": ["gh-proxy", "local", "remote"], "description": "GitHub access mode. Prefer 'gh-proxy' for better performance (uses pre-authenticated gh CLI prompt guidance). Legacy MCP transport values 'local' and 'remote' are accepted for backward compatibility and use GitHub MCP server prompt guidance." }, "type": { "type": "string", - "enum": [ - "local", - "remote" - ], + "enum": ["local", "remote"], "description": "GitHub MCP transport type: 'local' (Docker-based, default) or 'remote' (hosted at api.githubcopilot.com)" }, "version": { - "type": [ - "string", - "number" - ], + "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 - ] + "examples": ["v1.0.0", "latest", 20, 3.11] }, "args": { "type": "array", @@ -4233,25 +3663,14 @@ "pattern": "^[^:]+:[^:]+(:(ro|rw))?$", "description": "Mount specification in format 'host:container:mode'" }, - "examples": [ - [ - "/data:/data:ro", - "/tmp:/tmp:rw" - ], - [ - "/opt:/opt:ro" - ] - ] + "examples": [["/data:/data:ro", "/tmp:/tmp:rw"], ["/opt:/opt:ro"]] }, "allowed-repos": { "description": "Guard policy: repository access configuration. Restricts which repositories the agent can access. Use 'all' to allow all repos, 'public' for public repositories only, or an array of repository patterns (e.g., 'owner/repo', 'owner/*', 'owner/prefix*').", "oneOf": [ { "type": "string", - "enum": [ - "all", - "public" - ], + "enum": ["all", "public"], "description": "Allow access to all repositories ('all') or only public repositories ('public')" }, { @@ -4271,10 +3690,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "all", - "public" - ], + "enum": ["all", "public"], "description": "Allow access to all repositories ('all') or only public repositories ('public')" }, { @@ -4291,12 +3707,7 @@ "min-integrity": { "type": "string", "description": "Guard policy: minimum required integrity level for repository access. Restricts the agent to users with at least the specified permission level.", - "enum": [ - "none", - "unapproved", - "approved", - "merged" - ] + "enum": ["none", "unapproved", "approved", "merged"] }, "blocked-users": { "description": "Guard policy: GitHub usernames whose content is unconditionally blocked. Items from these users receive 'blocked' integrity (below 'none') and are always denied, even when 'min-integrity' is 'none'. Cannot be overridden by 'approval-labels'. Requires 'min-integrity' to be set. Accepts an array of usernames, a comma-separated string, a newline-separated string, or a GitHub Actions expression (e.g. '${{ vars.BLOCKED_USERS }}').", @@ -4358,27 +3769,10 @@ "items": { "type": "string", "description": "GitHub ReactionContent enum value", - "enum": [ - "THUMBS_UP", - "THUMBS_DOWN", - "HEART", - "HOORAY", - "CONFUSED", - "ROCKET", - "EYES", - "LAUGH" - ] + "enum": ["THUMBS_UP", "THUMBS_DOWN", "HEART", "HOORAY", "CONFUSED", "ROCKET", "EYES", "LAUGH"] }, - "default": [ - "THUMBS_UP", - "HEART" - ], - "examples": [ - [ - "THUMBS_UP", - "HEART" - ] - ] + "default": ["THUMBS_UP", "HEART"], + "examples": [["THUMBS_UP", "HEART"]] }, "disapproval-reactions": { "type": "array", @@ -4386,47 +3780,21 @@ "items": { "type": "string", "description": "GitHub ReactionContent enum value", - "enum": [ - "THUMBS_UP", - "THUMBS_DOWN", - "HEART", - "HOORAY", - "CONFUSED", - "ROCKET", - "EYES", - "LAUGH" - ] + "enum": ["THUMBS_UP", "THUMBS_DOWN", "HEART", "HOORAY", "CONFUSED", "ROCKET", "EYES", "LAUGH"] }, - "default": [ - "THUMBS_DOWN", - "CONFUSED" - ], - "examples": [ - [ - "THUMBS_DOWN", - "CONFUSED" - ] - ] + "default": ["THUMBS_DOWN", "CONFUSED"], + "examples": [["THUMBS_DOWN", "CONFUSED"]] }, "disapproval-integrity": { "type": "string", "description": "Guard policy: integrity level assigned when a disapproval reaction is present. Optional, defaults to 'none'. Requires the 'integrity-reactions' feature flag and MCPG >= v0.2.18.", - "enum": [ - "none", - "unapproved", - "approved", - "merged" - ], + "enum": ["none", "unapproved", "approved", "merged"], "default": "none" }, "endorser-min-integrity": { "type": "string", "description": "Guard policy: minimum integrity level required for an endorser (reactor) to promote content. Optional, defaults to 'approved'. Requires the 'integrity-reactions' feature flag and MCPG >= v0.2.18.", - "enum": [ - "unapproved", - "approved", - "merged" - ], + "enum": ["unapproved", "approved", "merged"], "default": "approved" }, "github-app": { @@ -4437,30 +3805,16 @@ "additionalProperties": false, "examples": [ { - "toolsets": [ - "pull_requests", - "actions", - "repos" - ] + "toolsets": ["pull_requests", "actions", "repos"] }, { - "allowed": [ - "search_pull_requests", - "pull_request_read", - "list_pull_requests", - "get_file_contents", - "list_commits", - "get_commit" - ] + "allowed": ["search_pull_requests", "pull_request_read", "list_pull_requests", "get_file_contents", "list_commits", "get_commit"] }, { "read-only": true }, { - "toolsets": [ - "pull_requests", - "repos" - ] + "toolsets": ["pull_requests", "repos"] } ] } @@ -4468,25 +3822,14 @@ "examples": [ null, { - "toolsets": [ - "pull_requests", - "actions", - "repos" - ] + "toolsets": ["pull_requests", "actions", "repos"] }, { - "allowed": [ - "search_pull_requests", - "pull_request_read", - "get_file_contents" - ] + "allowed": ["search_pull_requests", "pull_request_read", "get_file_contents"] }, { "read-only": true, - "toolsets": [ - "repos", - "issues" - ] + "toolsets": ["repos", "issues"] }, false ] @@ -4513,36 +3856,10 @@ ], "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" - ] + ["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": { @@ -4619,16 +3936,9 @@ "description": "Playwright tool configuration with custom version and arguments", "properties": { "version": { - "type": [ - "string", - "number" - ], + "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 - ] + "examples": ["v1.41.0", 1.41, 20] }, "args": { "type": "array", @@ -4654,10 +3964,7 @@ "description": "Enable agentic-workflows tool with default settings (same as true)" } ], - "examples": [ - true, - null - ] + "examples": [true, null] }, "cache-memory": { "description": "Cache memory MCP configuration for persistent memory storage", @@ -4694,10 +4001,7 @@ }, "scope": { "type": "string", - "enum": [ - "workflow", - "repo" - ], + "enum": ["workflow", "repo"], "default": "workflow", "description": "Cache restore key scope: 'workflow' (default, only restores from same workflow) or 'repo' (restores from any workflow in the repository). Use 'repo' with caution as it allows cross-workflow cache sharing." }, @@ -4750,10 +4054,7 @@ }, "scope": { "type": "string", - "enum": [ - "workflow", - "repo" - ], + "enum": ["workflow", "repo"], "default": "workflow", "description": "Cache restore key scope: 'workflow' (default, only restores from same workflow) or 'repo' (restores from any workflow in the repository). Use 'repo' with caution as it allows cross-workflow cache sharing." }, @@ -4765,10 +4066,7 @@ "description": "List of allowed file extensions (e.g., [\".json\", \".txt\"]). Default: [\".json\", \".jsonl\", \".txt\", \".md\", \".csv\"]" } }, - "required": [ - "id", - "key" - ], + "required": ["id", "key"], "additionalProperties": false }, "minItems": 1, @@ -4859,10 +4157,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -4883,11 +4178,7 @@ { "type": "integer", "minimum": 1, - "examples": [ - 60, - 120, - 300 - ] + "examples": [60, 120, 300] }, { "type": "string", @@ -4902,11 +4193,7 @@ { "type": "integer", "minimum": 1, - "examples": [ - 30, - 60, - 120 - ] + "examples": [30, 60, 120] }, { "type": "string", @@ -4918,9 +4205,7 @@ "cli-proxy": { "type": "boolean", "description": "When true, each user-facing MCP server is mounted as a standalone CLI tool on PATH. The agent can then call MCP servers via shell commands (e.g. 'github issue_read --method get ...'). CLI-mounted servers remain in the MCP gateway config so their containers can start, and are removed only from the agent's final config during convert_gateway_config_*.sh processing. Default: false.", - "examples": [ - true - ] + "examples": [true] }, "serena": { "description": "REMOVED: Built-in support for Serena has been removed. Use the shared/mcp/serena.md workflow instead.", @@ -5207,25 +4492,17 @@ "description": "Optional custom name for the cache step (overrides auto-generated name)" } }, - "required": [ - "key", - "path" - ], + "required": ["key", "path"], "additionalProperties": false, "examples": [ { "key": "node-modules-${{ hashFiles('package-lock.json') }}", "path": "node_modules", - "restore-keys": [ - "node-modules-" - ] + "restore-keys": ["node-modules-"] }, { "key": "build-cache-${{ github.sha }}", - "path": [ - "dist", - ".cache" - ], + "path": ["dist", ".cache"], "restore-keys": "build-cache-", "fail-on-cache-miss": false } @@ -5290,10 +4567,7 @@ "description": "Optional custom name for the cache step (overrides auto-generated name)" } }, - "required": [ - "key", - "path" - ], + "required": ["key", "path"], "additionalProperties": false } } @@ -5307,18 +4581,13 @@ { "create-issue": { "title-prefix": "[AI] ", - "labels": [ - "automation", - "ai-generated" - ] + "labels": ["automation", "ai-generated"] } }, { "create-pull-request": { "title-prefix": "[Bot] ", - "labels": [ - "bot" - ] + "labels": ["bot"] } }, { @@ -5340,23 +4609,7 @@ "items": { "type": "string" }, - "examples": [ - [ - "repo" - ], - [ - "repo", - "octocat/hello-world" - ], - [ - "microsoft/vscode", - "microsoft/typescript" - ], - [ - "repo", - "${{ github.repository }}" - ] - ] + "examples": [["repo"], ["repo", "octocat/hello-world"], ["microsoft/vscode", "microsoft/typescript"], ["repo", "${{ github.repository }}"]] }, "create-issue": { "oneOf": [ @@ -5438,9 +4691,7 @@ }, { "type": "boolean", - "enum": [ - false - ], + "enum": [false], "description": "Set to false to explicitly disable expiration" } ], @@ -5479,43 +4730,28 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, "examples": [ { "title-prefix": "[ca] ", - "labels": [ - "automation", - "dependencies" - ], + "labels": ["automation", "dependencies"], "assignees": "copilot" }, { "title-prefix": "[duplicate-code] ", - "labels": [ - "code-quality", - "automated-analysis" - ], + "labels": ["code-quality", "automated-analysis"], "assignees": "copilot" }, { - "allowed-repos": [ - "org/other-repo", - "org/another-repo" - ], + "allowed-repos": ["org/other-repo", "org/another-repo"], "title-prefix": "[cross-repo] " }, { "title-prefix": "[weekly-report] ", - "labels": [ - "report", - "automation" - ], + "labels": ["report", "automation"], "close-older-issues": true } ] @@ -5571,10 +4807,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -5629,10 +4862,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -5649,9 +4879,7 @@ { "type": "object", "description": "Configuration for managing GitHub Projects boards. Enable agents to add issues and pull requests to projects, update custom field values (status, priority, effort, dates), create project fields and views. By default it is update-only: if the project does not exist, the job fails with instructions to create it. To allow workflows to create missing projects, explicitly opt in via agent output field create_if_missing=true. Requires a Personal Access Token (PAT) or GitHub App token with Projects permissions (default GITHUB_TOKEN cannot be used). Agent output includes: project (full URL or temporary project ID like aw_XXXXXXXXXXXX or #aw_XXXXXXXXXXXX from create_project), content_type (issue|pull_request|draft_issue), content_number, fields, create_if_missing. For specialized operations, agent can also provide: operation (create_fields|create_view), field_definitions (array of field configs when operation=create_fields), view (view config object when operation=create_view).", - "required": [ - "project" - ], + "required": ["project"], "properties": { "max": { "description": "Maximum number of project operations to perform (default: 10). Each operation may add a project item, or update its fields. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -5676,10 +4904,7 @@ "type": "string", "description": "Target project URL for update-project operations. This is required in the configuration for documentation purposes. Agent messages MUST explicitly include the project field in their output - the configured value is not used as a fallback. Must be a valid GitHub Projects v2 URL.", "pattern": "^https://github\\.com/(users|orgs)/([^/]+|<[A-Z_]+>)/projects/(\\d+|<[A-Z_]+>)$", - "examples": [ - "https://github.com/orgs/myorg/projects/123", - "https://github.com/users/username/projects/456" - ] + "examples": ["https://github.com/orgs/myorg/projects/123", "https://github.com/users/username/projects/456"] }, "target-repo": { "description": "Default repository in format 'owner/repo' for cross-repository content resolution. When specified, the agent can use 'target_repo' in agent output to resolve issues or PRs from this repository. Wildcards ('*') are not allowed. Supports GitHub Actions expression syntax (e.g., '${{ vars.TARGET_REPO }}').", @@ -5718,10 +4943,7 @@ "items": { "type": "object", "description": "View configuration for creating project views", - "required": [ - "name", - "layout" - ], + "required": ["name", "layout"], "properties": { "name": { "type": "string", @@ -5729,11 +4951,7 @@ }, "layout": { "type": "string", - "enum": [ - "table", - "board", - "roadmap" - ], + "enum": ["table", "board", "roadmap"], "description": "The layout type of the view" }, "filter": { @@ -5760,10 +4978,7 @@ "description": "Optional array of project custom fields to create up-front.", "items": { "type": "object", - "required": [ - "name", - "data-type" - ], + "required": ["name", "data-type"], "properties": { "name": { "type": "string", @@ -5771,13 +4986,7 @@ }, "data-type": { "type": "string", - "enum": [ - "DATE", - "TEXT", - "NUMBER", - "SINGLE_SELECT", - "ITERATION" - ], + "enum": ["DATE", "TEXT", "NUMBER", "SINGLE_SELECT", "ITERATION"], "description": "The GitHub Projects v2 custom field type" }, "options": { @@ -5794,10 +5003,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -5857,10 +5063,7 @@ "items": { "type": "object", "description": "View configuration for creating project views", - "required": [ - "name", - "layout" - ], + "required": ["name", "layout"], "properties": { "name": { "type": "string", @@ -5868,11 +5071,7 @@ }, "layout": { "type": "string", - "enum": [ - "table", - "board", - "roadmap" - ], + "enum": ["table", "board", "roadmap"], "description": "The layout type of the view" }, "filter": { @@ -5899,10 +5098,7 @@ "description": "Optional array of project custom fields to create automatically after project creation.", "items": { "type": "object", - "required": [ - "name", - "data-type" - ], + "required": ["name", "data-type"], "properties": { "name": { "type": "string", @@ -5910,13 +5106,7 @@ }, "data-type": { "type": "string", - "enum": [ - "DATE", - "TEXT", - "NUMBER", - "SINGLE_SELECT", - "ITERATION" - ], + "enum": ["DATE", "TEXT", "NUMBER", "SINGLE_SELECT", "ITERATION"], "description": "The GitHub Projects v2 custom field type" }, "options": { @@ -5933,10 +5123,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -5956,9 +5143,7 @@ { "type": "object", "description": "Configuration for posting status updates to GitHub Projects. Status updates provide stakeholder communication about project progress, health, and timeline. Each update appears in the project's Updates tab and creates a historical record. Requires a Personal Access Token (PAT) or GitHub App token with Projects read & write permission (default GITHUB_TOKEN cannot be used). Typically used by scheduled workflows or orchestrators to post regular progress summaries with status indicators (on-track, at-risk, off-track, complete, inactive), dates, and progress details.", - "required": [ - "project" - ], + "required": ["project"], "properties": { "max": { "description": "Maximum number of status updates to create (default: 1). Typically 1 per orchestrator run. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -5983,18 +5168,12 @@ "type": "string", "description": "Target project URL for status update operations. This is required in the configuration for documentation purposes. Agent messages MUST explicitly include the project field in their output - the configured value is not used as a fallback. Must be a valid GitHub Projects v2 URL.", "pattern": "^https://github\\.com/(users|orgs)/([^/]+|<[A-Z_]+>)/projects/(\\d+|<[A-Z_]+>)$", - "examples": [ - "https://github.com/orgs/myorg/projects/123", - "https://github.com/users/username/projects/456" - ] + "examples": ["https://github.com/orgs/myorg/projects/123", "https://github.com/users/username/projects/456"] }, "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6026,16 +5205,9 @@ "description": "Optional prefix for the discussion title" }, "category": { - "type": [ - "string", - "number" - ], + "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 - ] + "examples": ["General", "audits", 123456789] }, "labels": { "type": "array", @@ -6112,9 +5284,7 @@ }, { "type": "boolean", - "enum": [ - false - ], + "enum": [false], "description": "Set to false to explicitly disable expiration" } ], @@ -6128,10 +5298,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6153,17 +5320,12 @@ "close-older-discussions": true }, { - "labels": [ - "weekly-report", - "automation" - ], + "labels": ["weekly-report", "automation"], "category": "reports", "close-older-discussions": true }, { - "allowed-repos": [ - "org/other-repo" - ], + "allowed-repos": ["org/other-repo"], "category": "General" } ] @@ -6222,10 +5384,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6234,10 +5393,7 @@ "required-category": "Ideas" }, { - "required-labels": [ - "resolved", - "completed" - ], + "required-labels": ["resolved", "completed"], "max": 1 } ] @@ -6305,10 +5461,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] }, "github-token": { "$ref": "#/$defs/github_token", @@ -6374,18 +5527,11 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] }, "state-reason": { "type": "string", - "enum": [ - "completed", - "not_planned", - "duplicate" - ], + "enum": ["completed", "not_planned", "duplicate"], "default": "completed", "description": "Reason for closing the issue (default: completed)" } @@ -6396,10 +5542,7 @@ "required-title-prefix": "[refactor] " }, { - "required-labels": [ - "automated", - "stale" - ], + "required-labels": ["automated", "stale"], "max": 10 } ] @@ -6458,10 +5601,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6470,10 +5610,7 @@ "required-title-prefix": "[bot] " }, { - "required-labels": [ - "automated", - "outdated" - ], + "required-labels": ["automated", "outdated"], "max": 5 } ] @@ -6532,10 +5669,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6544,10 +5678,7 @@ "required-title-prefix": "[bot] " }, { - "required-labels": [ - "automated", - "ready" - ], + "required-labels": ["automated", "ready"], "max": 1 } ] @@ -6614,14 +5745,7 @@ "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, low_quality).", "items": { "type": "string", - "enum": [ - "spam", - "abuse", - "off_topic", - "outdated", - "resolved", - "low_quality" - ] + "enum": ["spam", "abuse", "off_topic", "outdated", "resolved", "low_quality"] } }, "discussions": { @@ -6648,10 +5772,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, @@ -6788,11 +5909,7 @@ }, "if-no-changes": { "type": "string", - "enum": [ - "warn", - "error", - "ignore" - ], + "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": { @@ -6892,11 +6009,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "blocked", - "allowed", - "fallback-to-issue" - ], + "enum": ["blocked", "allowed", "fallback-to-issue"], "description": "Controls protected-file protection. blocked (default): hard-block any patch that modifies package manifests (e.g. package.json, go.mod), engine instruction files (e.g. AGENTS.md, CLAUDE.md) or .github/ files. allowed: allow all changes. fallback-to-issue: push the branch but create a review issue instead of a PR, so a human can review the manifest changes before merging.", "default": "blocked" }, @@ -6912,11 +6025,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "blocked", - "allowed", - "fallback-to-issue" - ], + "enum": ["blocked", "allowed", "fallback-to-issue"], "description": "Protection policy. blocked (default): hard-block any patch that modifies protected files. allowed: allow all changes. fallback-to-issue: push the branch but create a review issue instead of a PR.", "default": "blocked" }, @@ -6933,15 +6042,7 @@ "type": "string" }, "description": "List of filenames or path prefixes to remove from the default protected-file set. Items are matched by basename (e.g. \"AGENTS.md\") or path prefix (e.g. \".agents/\"). Use this to allow the agent to modify specific files that are otherwise blocked by default.", - "examples": [ - [ - "AGENTS.md" - ], - [ - "AGENTS.md", - ".agents/" - ] - ] + "examples": [["AGENTS.md"], ["AGENTS.md", ".agents/"]] } }, "additionalProperties": false, @@ -6978,10 +6079,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "am", - "bundle" - ], + "enum": ["am", "bundle"], "default": "am", "description": "Transport format for packaging changes. \"am\" (default) uses git format-patch/git am. \"bundle\" uses git bundle, which preserves merge commit topology, per-commit authorship, and merge-resolution-only content." }, @@ -6996,38 +6094,26 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] }, "allow-workflows": { "type": "boolean", "description": "When true, adds workflows: write to the GitHub App token permissions. Required when allowed-files targets .github/workflows/ paths. Requires safe-outputs.github-app to be configured because the workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.", "default": false, - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false, "examples": [ { "title-prefix": "[docs] ", - "labels": [ - "documentation", - "automation" - ], + "labels": ["documentation", "automation"], "reviewers": "copilot", "draft": false }, { "title-prefix": "[security-fix] ", - "labels": [ - "security", - "automated-fix" - ], + "labels": ["security", "automated-fix"], "reviewers": "copilot" } ] @@ -7063,10 +6149,7 @@ "side": { "type": "string", "description": "Side of the diff for comments: 'LEFT' or 'RIGHT' (default: 'RIGHT')", - "enum": [ - "LEFT", - "RIGHT" - ] + "enum": ["LEFT", "RIGHT"] }, "target": { "type": "string", @@ -7090,10 +6173,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7134,11 +6214,7 @@ }, { "type": "string", - "enum": [ - "always", - "none", - "if-body" - ], + "enum": ["always", "none", "if-body"], "description": "Controls when AI-generated footer is added to the review body: 'always' (default), 'none' (never), or 'if-body' (only when review has body text)." } ], @@ -7163,11 +6239,7 @@ "type": "array", "items": { "type": "string", - "enum": [ - "APPROVE", - "COMMENT", - "REQUEST_CHANGES" - ] + "enum": ["APPROVE", "COMMENT", "REQUEST_CHANGES"] }, "description": "Optional list of allowed review event types. If omitted, all event types (APPROVE, COMMENT, REQUEST_CHANGES) are allowed. Use this to restrict the agent to specific event types, e.g. [COMMENT, REQUEST_CHANGES] to prevent approvals.", "minItems": 1 @@ -7183,10 +6255,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7246,10 +6315,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7289,10 +6355,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7346,10 +6409,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7388,10 +6448,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7467,10 +6524,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7542,10 +6596,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7617,10 +6668,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7672,10 +6720,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7731,10 +6776,7 @@ ] }, "target": { - "type": [ - "string", - "number" - ], + "type": ["string", "number"], "description": "Target issue/PR to assign agents to. Use 'triggering' (default) for the triggering issue/PR, '*' to require explicit issue_number/pull_number, or a specific issue/PR number. With 'triggering', auto-resolves from github.event.issue.number or github.event.pull_request.number." }, "target-repo": { @@ -7768,10 +6810,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7818,10 +6857,7 @@ ] }, "target": { - "type": [ - "string", - "number" - ], + "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": { @@ -7847,10 +6883,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7897,10 +6930,7 @@ ] }, "target": { - "type": [ - "string", - "number" - ], + "type": ["string", "number"], "description": "Target issue to unassign users from. Use 'triggering' (default) for the triggering issue, '*' to allow any issue, or a specific issue number." }, "target-repo": { @@ -7921,10 +6951,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -7994,10 +7021,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8024,10 +7048,7 @@ "description": "Allow updating issue title - presence of key indicates field can be updated" }, "body": { - "type": [ - "boolean", - "null" - ], + "type": ["boolean", "null"], "description": "Allow updating issue body. Set to true to enable body updates, false to disable. For backward compatibility, null (body:) also enables body updates.", "default": true }, @@ -8073,10 +7094,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8113,11 +7131,7 @@ "operation": { "type": "string", "description": "Default operation for body updates: 'append' (add to end), 'prepend' (add to start), or 'replace' (overwrite completely). Defaults to 'replace' if not specified.", - "enum": [ - "append", - "prepend", - "replace" - ] + "enum": ["append", "prepend", "replace"] }, "footer": { "type": "boolean", @@ -8150,10 +7164,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8219,10 +7230,7 @@ "staged": { "type": "boolean", "description": "If true, evaluate merge gates and emit preview results without executing the merge API call.", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8287,11 +7295,7 @@ }, "if-no-changes": { "type": "string", - "enum": [ - "warn", - "error", - "ignore" - ], + "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)" }, "ignore-missing-branch-failure": { @@ -8310,10 +7314,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] }, "github-token-for-extra-empty-commit": { "type": "string", @@ -8349,11 +7350,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "blocked", - "allowed", - "fallback-to-issue" - ], + "enum": ["blocked", "allowed", "fallback-to-issue"], "description": "Controls protected-file protection. blocked (default): hard-block any patch that modifies package manifests (e.g. package.json, go.mod), engine instruction files (e.g. AGENTS.md, CLAUDE.md) or .github/ files. allowed: allow all changes. fallback-to-issue: create a review issue instead of pushing to the PR branch, so a human can review the changes before applying.", "default": "blocked" }, @@ -8369,11 +7366,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "blocked", - "allowed", - "fallback-to-issue" - ], + "enum": ["blocked", "allowed", "fallback-to-issue"], "description": "Protection policy. blocked (default): hard-block any patch that modifies protected files. allowed: allow all changes. fallback-to-issue: create a review issue instead of pushing.", "default": "blocked" }, @@ -8390,15 +7383,7 @@ "type": "string" }, "description": "List of filenames or path prefixes to remove from the default protected-file set. Items are matched by basename (e.g. \"AGENTS.md\") or path prefix (e.g. \".agents/\"). Use this to allow the agent to modify specific files that are otherwise blocked by default.", - "examples": [ - [ - "AGENTS.md" - ], - [ - "AGENTS.md", - ".agents/" - ] - ] + "examples": [["AGENTS.md"], ["AGENTS.md", ".agents/"]] } }, "additionalProperties": false, @@ -8425,10 +7410,7 @@ "oneOf": [ { "type": "string", - "enum": [ - "am", - "bundle" - ], + "enum": ["am", "bundle"], "default": "am", "description": "Transport format for packaging changes. \"am\" (default) uses git format-patch/git am. \"bundle\" uses git bundle, which preserves merge commit topology, per-commit authorship, and merge-resolution-only content." }, @@ -8444,10 +7426,7 @@ "type": "boolean", "description": "When true, adds workflows: write to the GitHub App token permissions. Required when allowed-files targets .github/workflows/ paths. Requires safe-outputs.github-app to be configured because the workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.", "default": false, - "examples": [ - true, - false - ] + "examples": [true, false] }, "check-branch-protection": { "type": "boolean", @@ -8494,14 +7473,7 @@ "description": "List of allowed reasons for hiding comments. Default: all reasons allowed (spam, abuse, off_topic, outdated, resolved, low_quality).", "items": { "type": "string", - "enum": [ - "spam", - "abuse", - "off_topic", - "outdated", - "resolved", - "low_quality" - ] + "enum": ["spam", "abuse", "off_topic", "outdated", "resolved", "low_quality"] } }, "discussions": { @@ -8511,10 +7483,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8577,10 +7546,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8635,15 +7601,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, - "required": [ - "workflows" - ], + "required": ["workflows"], "additionalProperties": false }, { @@ -8702,13 +7663,7 @@ "properties": { "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean", - "choice", - "environment" - ], + "enum": ["string", "number", "boolean", "choice", "environment"], "description": "Input type" }, "description": { @@ -8755,16 +7710,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, - "required": [ - "workflow", - "event_type" - ], + "required": ["workflow", "event_type"], "additionalProperties": false } }, @@ -8807,15 +7756,10 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, - "required": [ - "workflows" - ], + "required": ["workflows"], "additionalProperties": false }, { @@ -8876,10 +7820,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8941,10 +7882,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -8994,10 +7932,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -9062,10 +7997,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -9157,10 +8089,7 @@ "if-no-files": { "type": "string", "description": "Behaviour when no files match: 'error' (default) or 'ignore'", - "enum": [ - "error", - "ignore" - ], + "enum": ["error", "ignore"], "default": "error" } }, @@ -9173,10 +8102,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub Actions artifact uploads (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -9223,10 +8149,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -9241,10 +8164,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] }, "env": { "type": "object", @@ -9260,11 +8180,7 @@ "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 }}" - ] + "examples": ["${{ secrets.GITHUB_TOKEN }}", "${{ secrets.CUSTOM_PAT }}", "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}"] }, "github-app": { "$ref": "#/$defs/github_app", @@ -9450,13 +8366,7 @@ }, "type": { "type": "string", - "enum": [ - "string", - "boolean", - "choice", - "number", - "environment" - ], + "enum": ["string", "boolean", "choice", "number", "environment"], "description": "Input parameter type. Supports: string (default), boolean, choice (string with predefined options), number, and environment (string referencing a GitHub environment)", "default": "string" }, @@ -9552,11 +8462,7 @@ }, "type": { "type": "string", - "enum": [ - "string", - "boolean", - "number" - ], + "enum": ["string", "boolean", "number"], "description": "Input parameter type", "default": "string" } @@ -9571,9 +8477,7 @@ "description": "JavaScript handler body. Write only the code that runs inside the handler for each item \u2014 the compiler generates the full outer wrapper including config input destructuring (`const { channel, message } = config;`) and the handler function (`return async function handleX(item, resolvedTemporaryIds) { ... }`). The body has access to `item` (runtime message with input values), `resolvedTemporaryIds` (map of temporary IDs), and config-destructured local variables for each declared input." } }, - "required": [ - "script" - ], + "required": ["script"], "additionalProperties": false } }, @@ -9586,121 +8490,77 @@ "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}" - ] + "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})" - ] + "examples": ["> Install: `gh aw add {workflow_source}`", "> [Add this workflow]({workflow_source_url})"] }, "footer-workflow-recompile": { "type": "string", "description": "Custom footer message template for workflow recompile issues. Available placeholders: {workflow_name}, {run_url}, {repository}. Example: '> Workflow sync report by [{workflow_name}]({run_url}) for {repository}'", - "examples": [ - "> Workflow sync report by [{workflow_name}]({run_url}) for {repository}", - "> Maintenance report by [{workflow_name}]({run_url})" - ] + "examples": ["> Workflow sync report by [{workflow_name}]({run_url}) for {repository}", "> Maintenance report by [{workflow_name}]({run_url})"] }, "footer-workflow-recompile-comment": { "type": "string", "description": "Custom footer message template for comments on workflow recompile issues. Available placeholders: {workflow_name}, {run_url}, {repository}. Example: '> Update from [{workflow_name}]({run_url}) for {repository}'", - "examples": [ - "> Update from [{workflow_name}]({run_url}) for {repository}", - "> Maintenance update by [{workflow_name}]({run_url})" - ] + "examples": ["> Update from [{workflow_name}]({run_url}) for {repository}", "> Maintenance update by [{workflow_name}]({run_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}" - ] + "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:" - ] + "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}." - ] + "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." - ] + "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}." - ] + "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})." - ] + "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})."] }, "agent-failure-issue": { "type": "string", "description": "Custom footer template for agent failure tracking issues. Available placeholders: {workflow_name}, {run_url}. Default: '> Agent failure tracked by [{workflow_name}]({run_url})'", - "examples": [ - "> Agent failure tracked by [{workflow_name}]({run_url})", - "> Failure report from [{workflow_name}]({run_url})" - ] + "examples": ["> Agent failure tracked by [{workflow_name}]({run_url})", "> Failure report from [{workflow_name}]({run_url})"] }, "agent-failure-comment": { "type": "string", "description": "Custom footer template for comments on agent failure tracking issues. Available placeholders: {workflow_name}, {run_url}. Default: '> Agent failure update from [{workflow_name}]({run_url})'", - "examples": [ - "> Agent failure update from [{workflow_name}]({run_url})", - "> Update from [{workflow_name}]({run_url})" - ] + "examples": ["> Agent failure update from [{workflow_name}]({run_url})", "> Update from [{workflow_name}]({run_url})"] }, "pull-request-created": { "type": "string", "description": "Custom message template for pull request creation link appended to the activation comment. Available placeholders: {item_number}, {item_url}. Default: 'Pull request created: [#{item_number}]({item_url})'", - "examples": [ - "Pull request created: [#{item_number}]({item_url})", - "[#{item_number}]({item_url}) opened" - ] + "examples": ["Pull request created: [#{item_number}]({item_url})", "[#{item_number}]({item_url}) opened"] }, "issue-created": { "type": "string", "description": "Custom message template for issue creation link appended to the activation comment. Available placeholders: {item_number}, {item_url}. Default: 'Issue created: [#{item_number}]({item_url})'", - "examples": [ - "Issue created: [#{item_number}]({item_url})", - "[#{item_number}]({item_url}) filed" - ] + "examples": ["Issue created: [#{item_number}]({item_url})", "[#{item_number}]({item_url}) filed"] }, "commit-pushed": { "type": "string", "description": "Custom message template for commit push link appended to the activation comment. Available placeholders: {commit_sha}, {short_sha}, {commit_url}. Default: 'Commit pushed: [`{short_sha}`]({commit_url})'", - "examples": [ - "Commit pushed: [`{short_sha}`]({commit_url})", - "[`{short_sha}`]({commit_url}) pushed" - ] + "examples": ["Commit pushed: [`{short_sha}`]({commit_url})", "[`{short_sha}`]({commit_url}) pushed"] }, "append-only-comments": { "type": "boolean", @@ -9763,50 +8623,31 @@ "type": "boolean", "description": "Global footer control for all safe outputs. When false, omits visible AI-generated footer content from all created/updated entities (issues, PRs, discussions, releases) while still including XML markers for searchability. Individual safe-output types (create-issue, update-issue, etc.) can override this by specifying their own footer field. Defaults to true.", "default": true, - "examples": [ - false, - true - ] + "examples": [false, true] }, "activation-comments": { - "type": [ - "boolean", - "string" - ], + "type": ["boolean", "string"], "description": "When set to false or \"false\", disables all activation and fallback comments entirely (run-started, run-success, run-failure, PR/issue creation links). Supports templatable boolean values including GitHub Actions expressions (e.g. ${{ inputs.activation-comments }}). Default: true", "default": true, - "examples": [ - false, - true, - "${{ inputs.activation-comments }}" - ] + "examples": [false, true, "${{ inputs.activation-comments }}"] }, "group-reports": { "type": "boolean", "description": "When true, creates a parent '[aw] Failed runs' issue that tracks all workflow failures as sub-issues. Helps organize failure tracking but may be unnecessary in smaller repositories. Defaults to false.", "default": false, - "examples": [ - false, - true - ] + "examples": [false, true] }, "report-failure-as-issue": { "type": "boolean", "description": "When false, disables creating failure tracking issues when workflows fail. Useful for workflows where failures are expected or handled elsewhere. Defaults to true.", "default": true, - "examples": [ - false, - true - ] + "examples": [false, true] }, "failure-issue-repo": { "type": "string", "description": "Repository to create failure tracking issues in, in the format 'owner/repo'. Useful when the current repository has issues disabled. Defaults to the current repository.", "pattern": "^[^/]+/[^/]+$", - "examples": [ - "github/docs-engineering", - "myorg/infra-alerts" - ] + "examples": ["github/docs-engineering", "myorg/infra-alerts"] }, "max-bot-mentions": { "description": "Maximum number of bot trigger references (e.g. 'fixes #123', 'closes #456') allowed in output before all of them are neutralized. Default: 10. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max-bot-mentions }}').", @@ -9825,23 +8666,14 @@ }, "id-token": { "type": "string", - "enum": [ - "write", - "none" - ], + "enum": ["write", "none"], "description": "Override the id-token permission for the safe-outputs job. Use 'write' to force-enable the id-token: write permission (required for OIDC authentication with cloud providers). Use 'none' to suppress automatic detection and prevent adding id-token: write even when vault/OIDC actions are detected in steps. By default, the compiler auto-detects known OIDC/vault actions (aws-actions/configure-aws-credentials, azure/login, google-github-actions/auth, hashicorp/vault-action, cyberark/conjur-action) and adds id-token: write automatically.", - "examples": [ - "write", - "none" - ] + "examples": ["write", "none"] }, "concurrency-group": { "type": "string", "description": "Concurrency group for the safe-outputs job. When set, the safe-outputs job will use this concurrency group with cancel-in-progress: false. Supports GitHub Actions expressions.", - "examples": [ - "my-workflow-safe-outputs", - "safe-outputs-${{ github.repository }}" - ] + "examples": ["my-workflow-safe-outputs", "safe-outputs-${{ github.repository }}"] }, "needs": { "type": "array", @@ -9853,11 +8685,7 @@ "additionalItems": false, "uniqueItems": true, "default": [], - "examples": [ - [ - "secrets_fetcher" - ] - ] + "examples": [["secrets_fetcher"]] }, "environment": { "description": "Override the GitHub deployment environment for the safe-outputs job. When set, this environment is used instead of the top-level environment: field. When not set, the top-level environment: field is propagated automatically so that environment-scoped secrets are accessible in the safe-outputs job.", @@ -9879,9 +8707,7 @@ "description": "A deployment URL" } }, - "required": [ - "name" - ], + "required": ["name"], "additionalProperties": false } ] @@ -9916,11 +8742,7 @@ "uses": { "type": "string", "description": "The GitHub Action to use. Supports owner/repo@ref, owner/repo/subdir@ref, or ./local/path.", - "examples": [ - "actions-ecosystem/action-add-labels@v1", - "owner/repo@v1", - "owner/repo/subdir@v1" - ] + "examples": ["actions-ecosystem/action-add-labels@v1", "owner/repo@v1", "owner/repo/subdir@v1"] }, "description": { "type": "string", @@ -9965,9 +8787,7 @@ "additionalProperties": false } }, - "required": [ - "uses" - ], + "required": ["uses"], "additionalProperties": false } } @@ -10017,10 +8837,7 @@ "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", - "examples": [ - true, - false - ] + "examples": [true, false] } }, "additionalProperties": false @@ -10086,11 +8903,7 @@ }, "if-no-changes": { "type": "string", - "enum": [ - "warn", - "error", - "ignore" - ], + "enum": ["warn", "error", "ignore"], "default": "warn", "description": "Behavior when no changes are present in the patch: 'warn' (default, skip with warning), 'error' (fail the step), 'ignore' (skip silently)" }, @@ -10174,9 +8987,7 @@ "rate-limit": { "type": "object", "description": "Rate limiting configuration to restrict how frequently users can trigger the workflow. Helps prevent abuse and resource exhaustion from programmatically triggered events.", - "required": [ - "max" - ], + "required": ["max"], "properties": { "max": { "description": "Maximum number of workflow runs allowed per user within the time window. Required field. Supports integer or GitHub Actions expression (e.g. '${{ inputs.max }}').", @@ -10205,16 +9016,7 @@ "description": "Optional list of event types to apply rate limiting to. If not specified, rate limiting applies to all programmatically triggered events (e.g., workflow_dispatch, issue_comment, pull_request_review).", "items": { "type": "string", - "enum": [ - "workflow_dispatch", - "issue_comment", - "pull_request_review", - "pull_request_review_comment", - "issues", - "pull_request", - "discussion_comment", - "discussion" - ] + "enum": ["workflow_dispatch", "issue_comment", "pull_request_review", "pull_request_review_comment", "issues", "pull_request", "discussion_comment", "discussion"] }, "minItems": 1 }, @@ -10223,13 +9025,7 @@ "description": "Optional list of roles that are exempt from rate limiting. Defaults to ['admin', 'maintain', 'write'] if not specified. Users with any of these roles will not be subject to rate limiting checks. To apply rate limiting to all users, set to an empty array: []", "items": { "type": "string", - "enum": [ - "admin", - "maintain", - "write", - "triage", - "read" - ] + "enum": ["admin", "maintain", "write", "triage", "read"] }, "minItems": 0 } @@ -10243,18 +9039,12 @@ { "max": 10, "window": 30, - "events": [ - "workflow_dispatch", - "issue_comment" - ] + "events": ["workflow_dispatch", "issue_comment"] }, { "max": 5, "window": 60, - "ignored-roles": [ - "admin", - "maintain" - ] + "ignored-roles": ["admin", "maintain"] } ] }, @@ -10263,37 +9053,25 @@ "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://github.github.com/gh-aw/reference/frontmatter/#strict-mode-strict", - "examples": [ - true, - false - ] + "examples": [true, false] }, "private": { "type": "boolean", "default": false, "description": "Mark the workflow as private, preventing it from being added to other repositories via 'gh aw add'. A workflow with private: true is not meant to be shared outside its repository.", - "examples": [ - true, - false - ] + "examples": [true, false] }, "check-for-updates": { "type": "boolean", "default": true, "description": "Control whether the compile-agentic version update check runs in the activation job. When true (default), the activation job downloads config.json from the gh-aw repository and verifies the compiled version is not blocked and meets the minimum supported version. Set to false to disable the check (not allowed in strict mode). See: https://github.github.com/gh-aw/reference/frontmatter/#check-for-updates", - "examples": [ - true, - false - ] + "examples": [true, false] }, "run-install-scripts": { "type": "boolean", "default": false, "description": "Allow npm pre/post install scripts to execute during package installation. By default, --ignore-scripts is added to all generated npm install commands to prevent supply chain attacks via malicious install hooks. Setting run-install-scripts: true disables this protection globally (all runtimes). A supply chain security warning is emitted at compile time; in strict mode this is an error. Per-runtime control is also available via runtimes..run-install-scripts. See: https://github.github.com/gh-aw/reference/frontmatter/#run-install-scripts", - "examples": [ - false, - true - ] + "examples": [false, true] }, "mcp-scripts": { "type": "object", @@ -10302,9 +9080,7 @@ "^([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" - ], + "required": ["description"], "properties": { "description": { "type": "string", @@ -10318,13 +9094,7 @@ "properties": { "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean", - "array", - "object" - ], + "enum": ["string", "number", "boolean", "array", "object"], "default": "string", "description": "The JSON schema type of the input parameter." }, @@ -10378,108 +9148,71 @@ "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 - ] + "examples": [30, 60, 120, 300] } }, "additionalProperties": false, "oneOf": [ { - "required": [ - "script" - ], + "required": ["script"], "not": { "anyOf": [ { - "required": [ - "run" - ] + "required": ["run"] }, { - "required": [ - "py" - ] + "required": ["py"] }, { - "required": [ - "go" - ] + "required": ["go"] } ] } }, { - "required": [ - "run" - ], + "required": ["run"], "not": { "anyOf": [ { - "required": [ - "script" - ] + "required": ["script"] }, { - "required": [ - "py" - ] + "required": ["py"] }, { - "required": [ - "go" - ] + "required": ["go"] } ] } }, { - "required": [ - "py" - ], + "required": ["py"], "not": { "anyOf": [ { - "required": [ - "script" - ] + "required": ["script"] }, { - "required": [ - "run" - ] + "required": ["run"] }, { - "required": [ - "go" - ] + "required": ["go"] } ] } }, { - "required": [ - "go" - ], + "required": ["go"], "not": { "anyOf": [ { - "required": [ - "script" - ] + "required": ["script"] }, { - "required": [ - "run" - ] + "required": ["run"] }, { - "required": [ - "py" - ] + "required": ["py"] } ] } @@ -10537,18 +9270,9 @@ "description": "Runtime configuration object identified by runtime ID (e.g., 'node', 'python', 'go')", "properties": { "version": { - "type": [ - "string", - "number" - ], + "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 - ] + "examples": ["22", "3.12", "latest", 22, 3.12] }, "action-repo": { "type": "string", @@ -10561,22 +9285,13 @@ "if": { "type": "string", "description": "Optional GitHub Actions if condition to control when the runtime setup step runs. Supports standard GitHub Actions expression syntax. Useful for conditionally installing runtimes based on file presence (e.g., \"hashFiles('go.mod') != ''\" to install Go only when go.mod exists).", - "examples": [ - "hashFiles('go.mod') != ''", - "hashFiles('package.json') != ''", - "hashFiles('requirements.txt') != '' || hashFiles('pyproject.toml') != ''", - "hashFiles('uv.lock') != ''", - "github.event_name == 'workflow_dispatch'" - ] + "examples": ["hashFiles('go.mod') != ''", "hashFiles('package.json') != ''", "hashFiles('requirements.txt') != '' || hashFiles('pyproject.toml') != ''", "hashFiles('uv.lock') != ''", "github.event_name == 'workflow_dispatch'"] }, "run-install-scripts": { "type": "boolean", "default": false, "description": "Allow npm pre/post install scripts to execute for this runtime during package installation. Overrides the global run-install-scripts setting for this specific runtime. Only affects runtimes that generate npm install commands (node). A supply chain security warning is emitted at compile time; in strict mode this is an error.", - "examples": [ - false, - true - ] + "examples": [false, true] } }, "additionalProperties": false @@ -10600,9 +9315,7 @@ }, { "type": "boolean", - "enum": [ - false - ], + "enum": [false], "description": "Set to false to disable the default checkout step. The agent job will not check out any repository (dev-mode checkouts are unaffected)." } ] @@ -10610,14 +9323,9 @@ "dependencies": { "description": "APM package references to install. Supports array format (list of package slugs) or object format with packages and isolated fields.", "examples": [ - [ - "microsoft/apm-sample-package", - "acme/custom-tools" - ], + ["microsoft/apm-sample-package", "acme/custom-tools"], { - "packages": [ - "microsoft/apm-sample-package" - ], + "packages": ["microsoft/apm-sample-package"], "isolated": true } ], @@ -10662,15 +9370,10 @@ "github-token": { "type": "string", "description": "GitHub token expression to authenticate APM with private package repositories. Uses cascading fallback (GH_AW_PLUGINS_TOKEN \u2192 GH_AW_GITHUB_TOKEN \u2192 GITHUB_TOKEN) when not specified. Takes effect unless github-app is also configured (which takes precedence).", - "examples": [ - "${{ secrets.MY_TOKEN }}", - "${{ secrets.GH_AW_GITHUB_TOKEN }}" - ] + "examples": ["${{ secrets.MY_TOKEN }}", "${{ secrets.GH_AW_GITHUB_TOKEN }}"] } }, - "required": [ - "packages" - ], + "required": ["packages"], "additionalProperties": false } ] @@ -10702,13 +9405,7 @@ }, "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean", - "choice", - "array" - ], + "enum": ["string", "number", "boolean", "choice", "array"], "description": "The type of the input value." }, "options": { @@ -10724,11 +9421,7 @@ "properties": { "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean" - ], + "enum": ["string", "number", "boolean"], "description": "Type of each array item." } }, @@ -10740,9 +9433,7 @@ { "type": "object", "description": "Input parameter definition for object type (one level deep). Use 'properties' to declare the expected sub-fields.", - "required": [ - "type" - ], + "required": ["type"], "properties": { "description": { "type": "string", @@ -10755,9 +9446,7 @@ }, "type": { "type": "string", - "enum": [ - "object" - ], + "enum": ["object"], "description": "The type 'object' enables structured sub-fields accessible via 'github.aw.import-inputs..'." }, "properties": { @@ -10777,12 +9466,7 @@ "default": {}, "type": { "type": "string", - "enum": [ - "string", - "number", - "boolean", - "choice" - ], + "enum": ["string", "number", "boolean", "choice"], "description": "Type of the sub-property." }, "options": { @@ -10852,9 +9536,7 @@ } } }, - "required": [ - "slash_command" - ] + "required": ["slash_command"] }, { "properties": { @@ -10864,9 +9546,7 @@ } } }, - "required": [ - "command" - ] + "required": ["command"] } ] } @@ -10885,9 +9565,7 @@ } } }, - "required": [ - "issue_comment" - ] + "required": ["issue_comment"] }, { "properties": { @@ -10897,9 +9575,7 @@ } } }, - "required": [ - "pull_request_review_comment" - ] + "required": ["pull_request_review_comment"] }, { "properties": { @@ -10909,9 +9585,7 @@ } } }, - "required": [ - "label" - ] + "required": ["label"] } ] } @@ -11084,18 +9758,9 @@ "description": "AI engine identifier: built-in ('claude', 'codex', 'copilot', 'gemini', 'crush') or a named catalog entry" }, "version": { - "type": [ - "string", - "number" - ], + "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. GitHub Actions expressions (e.g., '${{ inputs.engine-version }}') are accepted and compiled with injection-safe env var handling.", - "examples": [ - "beta", - "stable", - 20, - 3.11, - "${{ inputs.engine-version }}" - ] + "examples": ["beta", "stable", 20, 3.11, "${{ inputs.engine-version }}"] }, "model": { "type": "string", @@ -11138,9 +9803,7 @@ "description": "Whether to cancel in-progress runs of the same concurrency group. Defaults to false for agentic workflow runs." } }, - "required": [ - "group" - ], + "required": ["group"], "additionalProperties": false } ], @@ -11177,11 +9840,7 @@ "api-target": { "type": "string", "description": "Custom API endpoint hostname for the agentic engine. Used for GitHub Enterprise Cloud (GHEC), GitHub Enterprise Server (GHES), or custom AI endpoints. Example: 'api.acme.ghe.com' for GHEC, 'api.enterprise.githubcopilot.com' for GHES, or custom endpoint hostnames.", - "examples": [ - "api.acme.ghe.com", - "api.enterprise.githubcopilot.com", - "api.custom.endpoint.com" - ] + "examples": ["api.acme.ghe.com", "api.enterprise.githubcopilot.com", "api.custom.endpoint.com"] }, "token-weights": { "type": "object", @@ -11255,21 +9914,13 @@ "session-timeout": { "type": "string", "description": "Session timeout for MCP gateway sessions as a Go duration string (e.g. \"30m\", \"4h\", \"24h\"). Must be at least 5m (no upper bound). Omitted or empty uses the effective gateway default (precedence: this field > MCP_GATEWAY_SESSION_TIMEOUT env var > built-in default 6h). Longer timeouts benefit multi-hour workflows such as large-scale migrations; shorter values free gateway resources sooner.", - "examples": [ - "30m", - "1h", - "4h", - "6h", - "12h" - ] + "examples": ["30m", "1h", "4h", "6h", "12h"] } }, "additionalProperties": false } }, - "required": [ - "id" - ], + "required": ["id"], "additionalProperties": false }, { @@ -11283,30 +9934,15 @@ "id": { "type": "string", "description": "Runtime adapter identifier (e.g. 'codex', 'claude', 'copilot', 'gemini', 'crush')", - "examples": [ - "codex", - "claude", - "copilot", - "gemini", - "crush" - ] + "examples": ["codex", "claude", "copilot", "gemini", "crush"] }, "version": { - "type": [ - "string", - "number" - ], + "type": ["string", "number"], "description": "Optional version of the runtime adapter (e.g. '0.105.0', 'beta')", - "examples": [ - "0.105.0", - "beta", - "latest" - ] + "examples": ["0.105.0", "beta", "latest"] } }, - "required": [ - "id" - ], + "required": ["id"], "additionalProperties": false }, "provider": { @@ -11316,21 +9952,12 @@ "id": { "type": "string", "description": "Provider identifier (e.g. 'openai', 'anthropic', 'github', 'google')", - "examples": [ - "openai", - "anthropic", - "github", - "google" - ] + "examples": ["openai", "anthropic", "github", "google"] }, "model": { "type": "string", "description": "Optional specific LLM model to use (e.g. 'gpt-5', 'claude-3-5-sonnet-20241022')", - "examples": [ - "gpt-5", - "claude-3-5-sonnet-20241022", - "gpt-4o" - ] + "examples": ["gpt-5", "claude-3-5-sonnet-20241022", "gpt-4o"] }, "auth": { "type": "object", @@ -11339,58 +9966,37 @@ "secret": { "type": "string", "description": "Name of the GitHub Actions secret that contains the API key for this provider", - "examples": [ - "OPENAI_API_KEY", - "ANTHROPIC_API_KEY", - "CUSTOM_API_KEY" - ] + "examples": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "CUSTOM_API_KEY"] }, "strategy": { "type": "string", - "enum": [ - "api-key", - "oauth-client-credentials", - "bearer" - ], + "enum": ["api-key", "oauth-client-credentials", "bearer"], "description": "Authentication strategy for the provider (default: api-key when secret is set)" }, "token-url": { "type": "string", "description": "OAuth 2.0 token endpoint URL. Required when strategy is 'oauth-client-credentials'.", - "examples": [ - "https://auth.example.com/oauth/token" - ] + "examples": ["https://auth.example.com/oauth/token"] }, "client-id": { "type": "string", "description": "GitHub Actions secret name that holds the OAuth client ID. Required when strategy is 'oauth-client-credentials'.", - "examples": [ - "OAUTH_CLIENT_ID" - ] + "examples": ["OAUTH_CLIENT_ID"] }, "client-secret": { "type": "string", "description": "GitHub Actions secret name that holds the OAuth client secret. Required when strategy is 'oauth-client-credentials'.", - "examples": [ - "OAUTH_CLIENT_SECRET" - ] + "examples": ["OAUTH_CLIENT_SECRET"] }, "token-field": { "type": "string", "description": "JSON field name in the token response that contains the access token. Defaults to 'access_token'.", - "examples": [ - "access_token", - "token" - ] + "examples": ["access_token", "token"] }, "header-name": { "type": "string", "description": "HTTP header name to inject the API key or token into (e.g. 'api-key', 'x-api-key'). Required when strategy is not 'bearer'.", - "examples": [ - "api-key", - "x-api-key", - "Authorization" - ] + "examples": ["api-key", "x-api-key", "Authorization"] } }, "additionalProperties": false @@ -11402,9 +10008,7 @@ "path-template": { "type": "string", "description": "URL path template with {model} and other variable placeholders (e.g. '/openai/deployments/{model}/chat/completions')", - "examples": [ - "/openai/deployments/{model}/chat/completions" - ] + "examples": ["/openai/deployments/{model}/chat/completions"] }, "query": { "type": "object", @@ -11442,9 +10046,7 @@ "default": false } }, - "required": [ - "runtime" - ], + "required": ["runtime"], "additionalProperties": false }, { @@ -11485,11 +10087,7 @@ }, "strategy": { "type": "string", - "enum": [ - "api-key", - "oauth-client-credentials", - "bearer" - ], + "enum": ["api-key", "oauth-client-credentials", "bearer"], "description": "Authentication strategy" }, "token-url": { @@ -11576,10 +10174,7 @@ "description": "Name of the GitHub Actions secret that provides credentials for this role" } }, - "required": [ - "role", - "secret" - ], + "required": ["role", "secret"], "additionalProperties": false } }, @@ -11589,10 +10184,7 @@ "additionalProperties": true } }, - "required": [ - "id", - "display-name" - ], + "required": ["id", "display-name"], "additionalProperties": false } ] @@ -11603,18 +10195,13 @@ "properties": { "type": { "type": "string", - "enum": [ - "stdio", - "local" - ], + "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", - "examples": [ - "https://api.mcp.github.com/v0/servers/microsoft/markitdown" - ] + "examples": ["https://api.mcp.github.com/v0/servers/microsoft/markitdown"] }, "command": { "type": "string", @@ -11629,17 +10216,9 @@ "description": "Container image for stdio MCP connections" }, "version": { - "type": [ - "string", - "number" - ], + "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 - ] + "examples": ["latest", "v1.0.0", 20, 3.11] }, "args": { "type": "array", @@ -11651,11 +10230,7 @@ "entrypoint": { "type": "string", "description": "Optional entrypoint override for container (equivalent to docker run --entrypoint)", - "examples": [ - "/bin/sh", - "/custom/entrypoint.sh", - "python" - ] + "examples": ["/bin/sh", "/custom/entrypoint.sh", "python"] }, "entrypointArgs": { "type": "array", @@ -11671,15 +10246,7 @@ "pattern": "^[^:]+:[^:]+:(ro|rw)$" }, "description": "Volume mounts for container in format 'source:dest:mode' where mode is 'ro' or 'rw'", - "examples": [ - [ - "/tmp/data:/data:ro" - ], - [ - "/workspace:/workspace:rw", - "/config:/config:ro" - ] - ] + "examples": [["/tmp/data:/data:ro"], ["/workspace:/workspace:rw", "/config:/config:ro"]] }, "env": { "type": "object", @@ -11725,18 +10292,7 @@ "items": { "type": "string" }, - "examples": [ - [ - "*" - ], - [ - "store_memory", - "retrieve_memory" - ], - [ - "brave_web_search" - ] - ] + "examples": [["*"], ["store_memory", "retrieve_memory"], ["brave_web_search"]] }, "proxy-args": { "type": "array", @@ -11750,32 +10306,22 @@ "$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) Type constraint: When 'type' is 'stdio' or 'local', either 'command' or 'container' is required. Note: Per-server 'network' field is deprecated and ignored.", "anyOf": [ { - "required": [ - "type" - ] + "required": ["type"] }, { - "required": [ - "command" - ] + "required": ["command"] }, { - "required": [ - "container" - ] + "required": ["container"] } ], "not": { "allOf": [ { - "required": [ - "command" - ] + "required": ["command"] }, { - "required": [ - "container" - ] + "required": ["container"] } ] }, @@ -11784,24 +10330,17 @@ "if": { "properties": { "type": { - "enum": [ - "stdio", - "local" - ] + "enum": ["stdio", "local"] } } }, "then": { "anyOf": [ { - "required": [ - "command" - ] + "required": ["command"] }, { - "required": [ - "container" - ] + "required": ["container"] } ] } @@ -11814,17 +10353,13 @@ "properties": { "type": { "type": "string", - "enum": [ - "http" - ], + "enum": ["http"], "description": "MCP connection type for HTTP" }, "registry": { "type": "string", "description": "URI to the installation location when MCP is installed from a registry", - "examples": [ - "https://api.mcp.github.com/v0/servers/microsoft/markitdown" - ] + "examples": ["https://api.mcp.github.com/v0/servers/microsoft/markitdown"] }, "url": { "type": "string", @@ -11847,26 +10382,13 @@ "items": { "type": "string" }, - "examples": [ - [ - "*" - ], - [ - "store_memory", - "retrieve_memory" - ], - [ - "brave_web_search" - ] - ] + "examples": [["*"], ["store_memory", "retrieve_memory"], ["brave_web_search"]] }, "auth": { "$ref": "#/$defs/http_mcp_auth" } }, - "required": [ - "url" - ], + "required": ["url"], "additionalProperties": false }, "http_mcp_auth": { @@ -11875,9 +10397,7 @@ "properties": { "type": { "type": "string", - "enum": [ - "github-oidc" - ], + "enum": ["github-oidc"], "description": "Authentication type. Currently only 'github-oidc' is supported, which acquires short-lived JWTs from the GitHub Actions OIDC endpoint." }, "audience": { @@ -11886,21 +10406,14 @@ "format": "uri" } }, - "required": [ - "type" - ], + "required": ["type"], "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_]*)*|needs\\.[A-Za-z_][A-Za-z0-9_]*\\.outputs\\.[A-Za-z_][A-Za-z0-9_]*)\\s*\\}\\}$", "description": "GitHub token expression. Accepts a secrets expression (e.g., `${{ secrets.NAME }}` or `${{ secrets.NAME1 || secrets.NAME2 }}`) or a job output expression (e.g., `${{ needs.auth.outputs.token }}`). Pattern details: secret names match `[A-Za-z_][A-Za-z0-9_]*`; job IDs and output names in dot notation match `[A-Za-z_][A-Za-z0-9_]*` (identifiers without hyphens).", - "examples": [ - "${{ secrets.GITHUB_TOKEN }}", - "${{ secrets.CUSTOM_PAT }}", - "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", - "${{ needs.auth.outputs.token }}" - ] + "examples": ["${{ secrets.GITHUB_TOKEN }}", "${{ secrets.CUSTOM_PAT }}", "${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", "${{ needs.auth.outputs.token }}"] }, "github_app": { "type": "object", @@ -11909,23 +10422,17 @@ "app-id": { "type": "string", "description": "Deprecated alias for client-id. GitHub App ID/client ID (e.g., '${{ vars.APP_ID }}').", - "examples": [ - "${{ vars.APP_ID }}" - ] + "examples": ["${{ vars.APP_ID }}"] }, "client-id": { "type": "string", "description": "GitHub App client ID (e.g., '${{ vars.APP_ID }}'). Required to mint a GitHub App token.", - "examples": [ - "${{ vars.APP_ID }}" - ] + "examples": ["${{ vars.APP_ID }}"] }, "private-key": { "type": "string", "description": "GitHub App private key (e.g., '${{ secrets.APP_PRIVATE_KEY }}'). Required to mint a GitHub App token.", - "examples": [ - "${{ secrets.APP_PRIVATE_KEY }}" - ] + "examples": ["${{ secrets.APP_PRIVATE_KEY }}"] }, "owner": { "type": "string", @@ -11945,16 +10452,10 @@ }, "anyOf": [ { - "required": [ - "client-id", - "private-key" - ] + "required": ["client-id", "private-key"] }, { - "required": [ - "app-id", - "private-key" - ] + "required": ["app-id", "private-key"] } ], "additionalProperties": false, @@ -12069,14 +10570,10 @@ "additionalProperties": false, "anyOf": [ { - "required": [ - "uses" - ] + "required": ["uses"] }, { - "required": [ - "run" - ] + "required": ["run"] } ] }, @@ -12088,56 +10585,34 @@ "repository": { "type": "string", "description": "Repository to checkout in owner/repo format. Defaults to the current repository.", - "examples": [ - "owner/repo", - "github/gh-aw" - ] + "examples": ["owner/repo", "github/gh-aw"] }, "ref": { "type": "string", "description": "Branch, tag, or SHA to checkout. Defaults to the ref that triggered the workflow.", - "examples": [ - "main", - "v1.0.0", - "feature/my-branch" - ] + "examples": ["main", "v1.0.0", "feature/my-branch"] }, "path": { "type": "string", "description": "Relative path within GITHUB_WORKSPACE to place the checkout. Defaults to the workspace root.", - "examples": [ - ".", - "./libs/other-repo", - "./workspace" - ] + "examples": [".", "./libs/other-repo", "./workspace"] }, "fetch-depth": { "type": "integer", "minimum": 0, "description": "Number of commits to fetch. 0 fetches all history. 1 (default) is a shallow clone. When multiple configs target the same path, the deepest value is used.", - "examples": [ - 0, - 1, - 10 - ] + "examples": [0, 1, 10] }, "sparse-checkout": { "type": "string", "description": "Enable sparse-checkout with newline-separated patterns. When multiple configs target the same path, patterns are merged.", - "examples": [ - ".github/\nsrc/", - "docs/" - ] + "examples": [".github/\nsrc/", "docs/"] }, "submodules": { "oneOf": [ { "type": "string", - "enum": [ - "recursive", - "true", - "false" - ] + "enum": ["recursive", "true", "false"] }, { "type": "boolean" @@ -12152,18 +10627,12 @@ "token": { "type": "string", "description": "Deprecated: Use github-token instead. GitHub token for authentication. Credentials are always removed after checkout (persist-credentials: false is enforced).", - "examples": [ - "${{ secrets.MY_PAT }}", - "${{ secrets.GITHUB_TOKEN }}" - ] + "examples": ["${{ secrets.MY_PAT }}", "${{ secrets.GITHUB_TOKEN }}"] }, "github-token": { "type": "string", "description": "GitHub token for authentication. Use ${{ secrets.MY_TOKEN }} to reference a secret. Mutually exclusive with github-app (and deprecated app). Credentials are always removed after checkout (persist-credentials: false is enforced).", - "examples": [ - "${{ secrets.MY_PAT }}", - "${{ secrets.CROSS_REPO_PAT }}" - ] + "examples": ["${{ secrets.MY_PAT }}", "${{ secrets.CROSS_REPO_PAT }}"] }, "github-app": { "$ref": "#/$defs/github_app", @@ -12188,29 +10657,12 @@ } ], "description": "Additional Git refs to fetch after the checkout. Supported values: \"*\" (all branches), \"refs/pulls/open/*\" (all open pull-request refs), branch names (e.g. \"main\"), or glob patterns (e.g. \"feature/*\").", - "examples": [ - [ - "*" - ], - [ - "refs/pulls/open/*" - ], - [ - "main", - "feature/my-branch" - ], - [ - "feature/*" - ] - ] + "examples": [["*"], ["refs/pulls/open/*"], ["main", "feature/my-branch"], ["feature/*"]] }, "wiki": { "type": "boolean", "description": "When true, clones the repository's wiki git instead of the regular repository. The effective repository becomes \"{repository}.wiki\" (e.g. \"owner/repo.wiki\"). Defaults to false.", - "examples": [ - true, - false - ] + "examples": [true, false] } } }, @@ -12221,169 +10673,97 @@ "properties": { "actions": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "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" - ], + "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" - ], + "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" - ], + "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" - ], + "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" - ], + "enum": ["read", "write", "none"], "description": "Permission for repository discussions (read: view discussions, write: create/update discussions, none: no access)" }, "id-token": { "type": "string", - "enum": [ - "write", - "none" - ], + "enum": ["write", "none"], "description": "Permission level for OIDC token requests (write/none only - read is not supported). Allows workflows to request JWT tokens for cloud provider authentication." }, "issues": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "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" - ], + "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" - ], + "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" - ], + "enum": ["read", "write", "none"], "description": "Permission level for GitHub Packages (read/write/none). Controls access to publish, modify, or delete packages." }, "pages": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for GitHub Pages (read/write/none). Controls access to deploy and manage GitHub Pages sites." }, "pull-requests": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for pull requests (read/write/none). Controls access to create, edit, review, and manage pull requests." }, "repository-projects": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for repository projects (read/write/none). Controls access to manage repository-level GitHub Projects boards." }, "organization-projects": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for organization projects (read/write/none). Controls access to manage organization-level GitHub Projects boards." }, "security-events": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for security events (read/write/none). Controls access to view and manage code scanning alerts and security findings." }, "statuses": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for commit statuses (read/write/none). Controls access to create and update commit status checks." }, "vulnerability-alerts": { "type": "string", - "enum": [ - "read", - "write", - "none" - ], + "enum": ["read", "write", "none"], "description": "Permission level for Dependabot vulnerability alerts (read/write/none). Allows workflows to access the Dependabot alerts API via GITHUB_TOKEN instead of requiring a PAT or GitHub App." }, "all": { "type": "string", - "enum": [ - "read" - ], + "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." } } @@ -12395,271 +10775,152 @@ "properties": { "administration": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for repository administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission for repository administration." }, "codespaces": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for Codespaces (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "codespaces-lifecycle-admin": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for Codespaces lifecycle administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "codespaces-metadata": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for Codespaces metadata (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "email-addresses": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for user email addresses (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "environments": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for repository environments (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "git-signing": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for git signing (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "members": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization members (read/none; \"write\" is rejected by the compiler). Required for org team membership API calls." }, "organization-administration": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization administration (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-announcement-banners": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization announcement banners (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-codespaces": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization Codespaces (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-copilot": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization Copilot (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-org-roles": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization custom org roles (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-properties": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization custom properties (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-custom-repository-roles": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization custom repository roles (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-events": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization events (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-hooks": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization webhooks (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-members": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization members management (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-packages": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization packages (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-personal-access-token-requests": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization personal access token requests (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-personal-access-tokens": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization personal access tokens (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-plan": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization plan (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-self-hosted-runners": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization self-hosted runners (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "organization-user-blocking": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for organization user blocking (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "repository-custom-properties": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for repository custom properties (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "repository-hooks": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for repository webhooks (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "single-file": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for single file access (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "team-discussions": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for team discussions (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." }, "vulnerability-alerts": { "type": "string", - "enum": [ - "read", - "none" - ], + "enum": ["read", "none"], "description": "Permission level for Dependabot vulnerability alerts (read/none; \"write\" is rejected by the compiler). Also available as a GITHUB_TOKEN scope. When used with a GitHub App, forwarded as permission-vulnerability-alerts input." }, "workflows": { "type": "string", - "enum": [ - "read", - "none", - "write" - ], + "enum": ["read", "none", "write"], "description": "Permission level for GitHub Actions workflow files (read/none; \"write\" is rejected by the compiler). GitHub App-only permission." } }, diff --git a/pkg/workflow/safe_outputs_permissions.go b/pkg/workflow/safe_outputs_permissions.go index 35e85a1354e..d0d8f6293a2 100644 --- a/pkg/workflow/safe_outputs_permissions.go +++ b/pkg/workflow/safe_outputs_permissions.go @@ -182,6 +182,7 @@ func ComputePermissionsForSafeOutputs(safeOutputs *SafeOutputsConfig) *Permissio permissions.Merge(NewPermissionsContentsWrite()) } if safeOutputs.UpdatePullRequests != nil && !isHandlerStaged(safeOutputs.Staged, safeOutputs.UpdatePullRequests.Staged) { + safeOutputsPermissionsLog.Print("Adding permissions for update-pull-request") if safeOutputs.UpdatePullRequests.UpdateBranch != nil && *safeOutputs.UpdatePullRequests.UpdateBranch { safeOutputsPermissionsLog.Print("update-pull-request has update-branch enabled; requiring contents: write") permissions.Merge(NewPermissionsContentsWritePRWrite()) From cb9dd49ad46dbcc955aa49e039c353822a41972e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 22:20:15 +0000 Subject: [PATCH 03/10] feat: add editWikiHandler in MCP server and smoke-codex edit-wiki test - Add editWikiHandler to safe_outputs_handlers.cjs: generates incremental patch from a wiki clone directory committed by the agent - Register edit_wiki in safe_outputs_tools_loader.cjs handler map - Add wiki_dir parameter to edit_wiki tool schema (safe_outputs_tools.json) - Fix unused createAuthenticatedGitHubClient import in edit_wiki.cjs - Fix commitTitleSuffix regex to handle [PATCH N/M] and [PATCH vN] prefixes - Fix edit_wiki.go default max from 0 to 1 (aligns with schema constraint) - Update smoke-codex.md: add edit-wiki to safe-outputs and test #10 that clones the wiki, creates a haiku page, links it from Home.md, commits, and calls the edit_wiki safe-output tool Agent-Logs-Url: https://github.com/github/gh-aw/sessions/125b6501-1921-46a1-a885-289ae2df5adc Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-codex.lock.yml | 80 +++++++------ .github/workflows/smoke-codex.md | 10 +- actions/setup/js/edit_wiki.cjs | 3 +- actions/setup/js/safe_outputs_handlers.cjs | 111 ++++++++++++++++++ .../setup/js/safe_outputs_tools_loader.cjs | 1 + pkg/workflow/edit_wiki.go | 4 +- pkg/workflow/js/safe_outputs_tools.json | 4 + 7 files changed, 172 insertions(+), 41 deletions(-) diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index c483e2fe9b5..9f0851c1211 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0305420f533fa974fcaa1c7a3277f30f833832d8c57e5542a69ddff157eb2a7a","agent_id":"codex"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29","digest":"sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29","digest":"sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29","digest":"sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"6bb55baf88fda60e6c1c5fea30f7f25c17e972ca47b455d30436d833d0b08565","agent_id":"codex"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29","digest":"sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29","digest":"sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29","digest":"sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -36,6 +36,7 @@ # # Secrets used: # - CODEX_API_KEY +# - GH_AW_CI_TRIGGER_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GH_AW_OTEL_ENDPOINT @@ -253,25 +254,25 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_be18ab6f21d42e65_EOF' + cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' - GH_AW_PROMPT_be18ab6f21d42e65_EOF + GH_AW_PROMPT_bc54081b7e3e6dfe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/playwright_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_be18ab6f21d42e65_EOF' + cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' Tools: add_comment(max:2), create_issue, add_labels, remove_labels, unassign_from_user, hide_comment(max:5), missing_tool, missing_data, noop, add_smoked_label - GH_AW_PROMPT_be18ab6f21d42e65_EOF + GH_AW_PROMPT_bc54081b7e3e6dfe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_comment_memory.md" - cat << 'GH_AW_PROMPT_be18ab6f21d42e65_EOF' + cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' - GH_AW_PROMPT_be18ab6f21d42e65_EOF + GH_AW_PROMPT_bc54081b7e3e6dfe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_be18ab6f21d42e65_EOF' + cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -303,9 +304,9 @@ jobs: - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). - GH_AW_PROMPT_be18ab6f21d42e65_EOF + GH_AW_PROMPT_bc54081b7e3e6dfe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_be18ab6f21d42e65_EOF' + cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' ## Serena Code Analysis @@ -346,7 +347,7 @@ jobs: {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/smoke-codex.md}} - GH_AW_PROMPT_be18ab6f21d42e65_EOF + GH_AW_PROMPT_bc54081b7e3e6dfe_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -585,9 +586,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a968479bc80ebf8e_EOF' - {"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-codex"]},"add_smoked_label":true,"comment_memory":{"max":1,"memory_id":"default"},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-codex","expires":2,"labels":["automation","testing"],"max":1},"create_report_incomplete_issue":{},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"remove_labels":{"allowed":["smoke"]},"report_incomplete":{},"unassign_from_user":{"allowed":["githubactionagent"],"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_a968479bc80ebf8e_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_8e7c0cf18eddaabf_EOF' + {"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-codex"]},"add_smoked_label":true,"comment_memory":{"max":1,"memory_id":"default"},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-codex","expires":2,"labels":["automation","testing"],"max":1},"create_report_incomplete_issue":{},"edit_wiki":{"if_no_changes":"warn","max_patch_size":1024},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"remove_labels":{"allowed":["smoke"]},"report_incomplete":{},"unassign_from_user":{"allowed":["githubactionagent"],"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_8e7c0cf18eddaabf_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -915,7 +916,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_78b882308c5f1ed3_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_707c316f82e50dc8_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -945,8 +946,8 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_78b882308c5f1ed3_EOF - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_068086496cc04293_EOF' + GH_AW_MCP_SCRIPTS_TOOLS_707c316f82e50dc8_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_ebe645fb25a62cc1_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); const configPath = path.join(__dirname, "tools.json"); @@ -960,12 +961,12 @@ jobs: console.error("Failed to start mcp-scripts HTTP server:", error); process.exit(1); }); - GH_AW_MCP_SCRIPTS_SERVER_068086496cc04293_EOF + GH_AW_MCP_SCRIPTS_SERVER_ebe645fb25a62cc1_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_ebb4837f5604bd27_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_90453dbdd72e029b_EOF' #!/bin/bash # Auto-generated mcp-script tool: gh # Execute any gh CLI command. This tool is accessible as 'mcpscripts-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh . Use single quotes ' for complex args to avoid shell interpretation issues. @@ -977,7 +978,7 @@ jobs: GH_TOKEN="$GH_AW_GH_TOKEN" gh $INPUT_ARGS - GH_AW_MCP_SCRIPTS_SH_GH_ebb4837f5604bd27_EOF + GH_AW_MCP_SCRIPTS_SH_GH_90453dbdd72e029b_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" - name: Generate MCP Scripts Server Config @@ -1051,7 +1052,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_MCP_SCRIPTS_PORT -e GH_AW_MCP_SCRIPTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e CODEX_HOME -e GH_AW_GH_TOKEN -e GH_DEBUG -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_cd045c4c558db8eb_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF [history] persistence = "none" @@ -1124,11 +1125,11 @@ jobs: [mcp_servers.serena."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_cd045c4c558db8eb_EOF + GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_cd045c4c558db8eb_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -1238,11 +1239,11 @@ jobs: } } } - GH_AW_MCP_CONFIG_cd045c4c558db8eb_EOF + GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_e9d7843a40c183aa_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_e9ad8250a4e103cc_EOF model_provider = "openai-proxy" @@ -1254,7 +1255,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_e9d7843a40c183aa_EOF + GH_AW_CODEX_SHELL_POLICY_e9ad8250a4e103cc_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1507,7 +1508,7 @@ jobs: needs.activation.outputs.stale_lock_file_failed == 'true') runs-on: ubuntu-slim permissions: - contents: read + contents: write discussions: write issues: write pull-requests: write @@ -1829,18 +1830,18 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_f6f6f4bba52f9546_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_522976f1ac116915_EOF [history] persistence = "none" [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_MCP_CONFIG_f6f6f4bba52f9546_EOF + GH_AW_MCP_CONFIG_522976f1ac116915_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_f74d7178b2417792_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_0a3f3b5cfc125c20_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { }, @@ -1851,11 +1852,11 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_f74d7178b2417792_EOF + GH_AW_MCP_CONFIG_0a3f3b5cfc125c20_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_ea73cb52ef946433_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_b24d9d0a4df1647d_EOF model_provider = "openai-proxy" [model_providers.openai-proxy] name = "OpenAI AWF proxy" @@ -1865,7 +1866,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_ea73cb52ef946433_EOF + GH_AW_CODEX_SHELL_POLICY_b24d9d0a4df1647d_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1989,7 +1990,7 @@ jobs: if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' runs-on: ubuntu-slim permissions: - contents: read + contents: write discussions: write issues: write pull-requests: write @@ -2046,6 +2047,12 @@ jobs: mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config shell: bash @@ -2064,7 +2071,8 @@ jobs: GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} GH_AW_SAFE_OUTPUT_ACTIONS: "{\"add_smoked_label\":\"add_smoked_label\"}" - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":2},\"add_labels\":{\"allowed\":[\"smoke-codex\"]},\"comment_memory\":{\"max\":1,\"memory_id\":\"default\"},\"create_issue\":{\"close_older_issues\":true,\"close_older_key\":\"smoke-codex\",\"expires\":2,\"labels\":[\"automation\",\"testing\"],\"max\":1},\"create_report_incomplete_issue\":{},\"hide_comment\":{\"max\":5},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"remove_labels\":{\"allowed\":[\"smoke\"]},\"report_incomplete\":{},\"unassign_from_user\":{\"allowed\":[\"githubactionagent\"],\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":2},\"add_labels\":{\"allowed\":[\"smoke-codex\"]},\"comment_memory\":{\"max\":1,\"memory_id\":\"default\"},\"create_issue\":{\"close_older_issues\":true,\"close_older_key\":\"smoke-codex\",\"expires\":2,\"labels\":[\"automation\",\"testing\"],\"max\":1},\"create_report_incomplete_issue\":{},\"edit_wiki\":{\"if_no_changes\":\"warn\",\"max_patch_size\":1024},\"hide_comment\":{\"max\":5},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"remove_labels\":{\"allowed\":[\"smoke\"]},\"report_incomplete\":{},\"unassign_from_user\":{\"allowed\":[\"githubactionagent\"],\"max\":1}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/smoke-codex.md b/.github/workflows/smoke-codex.md index 5e00824fcae..4d40e1aa65f 100644 --- a/.github/workflows/smoke-codex.md +++ b/.github/workflows/smoke-codex.md @@ -60,6 +60,7 @@ safe-outputs: allowed: [githubactionagent] max: 1 hide-comment: + edit-wiki: messages: footer: "> 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}" run-started: "🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}..." @@ -101,13 +102,20 @@ checkout: - Check if `/tmp/gh-aw/cache-memory/smoke-codex-history.json` exists; if it does, read it and note the previous run's results (run ID, timestamp, status) - Write current run results to `/tmp/gh-aw/cache-memory/smoke-codex-history.json` with content: `{"run_id": "${{ github.run_id }}", "timestamp": "", "status": "PASS or FAIL", "tests_passed": , "tests_failed": }` (create the parent directory if it doesn't exist) - Use bash to verify the file was written successfully (use `cat` to read it back) +10. **Edit Wiki Testing**: Create a new wiki page with a haiku and link it from the main wiki page using the `edit_wiki` safe-output tool: + - Clone the wiki repo to `/tmp/gh-aw/wiki` using: `git clone https://github.com/${{ github.repository }}.wiki.git /tmp/gh-aw/wiki` (if the wiki doesn't exist yet, skip this test and mark it ⚠️ Skipped) + - Configure git identity in the wiki clone: `git -C /tmp/gh-aw/wiki config user.email "github-actions[bot]@users.noreply.github.com"` and `git -C /tmp/gh-aw/wiki config user.name "github-actions[bot]"` + - Create a new wiki page `/tmp/gh-aw/wiki/Smoke-Test-Haiku.md` with content: a title "# Smoke Test Haiku", a blank line, and an original 3-line haiku about automated testing or continuous integration (write the haiku content in the file, NOT in the commit message) + - Update `/tmp/gh-aw/wiki/Home.md` (if it exists) to append a link to the new page: `- [Smoke Test Haiku](Smoke-Test-Haiku)` (if Home.md does not exist, create it with that link) + - Stage and commit the wiki changes: `git -C /tmp/gh-aw/wiki add . && git -C /tmp/gh-aw/wiki commit -m "Add smoke test haiku page [run ${{ github.run_id }}]"` + - Call the `edit_wiki` safe-output tool with `{ "message": "Add smoke test haiku page", "wiki_dir": "/tmp/gh-aw/wiki" }` ## Output **ALWAYS create an issue** with a summary of the smoke test run: - Title: "Smoke Test: Codex - ${{ github.run_id }}" - Body should include: - - Test results (✅ or ❌ for each test, including test #9 Cache Memory) + - Test results (✅ or ❌ for each test, including test #9 Cache Memory and test #10 Edit Wiki) - Overall status: PASS or FAIL - Run URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - Timestamp diff --git a/actions/setup/js/edit_wiki.cjs b/actions/setup/js/edit_wiki.cjs index 565ff7af8e8..1a2c7153aa8 100644 --- a/actions/setup/js/edit_wiki.cjs +++ b/actions/setup/js/edit_wiki.cjs @@ -9,7 +9,6 @@ const { generateStagedPreview } = require("./staged_preview.cjs"); const { isStagedMode } = require("./safe_output_helpers.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs"); -const { createAuthenticatedGitHubClient } = require("./handler_auth.cjs"); const { getGitAuthEnv } = require("./git_helpers.cjs"); /** @@ -241,7 +240,7 @@ async function main(config = {}) { if (commitTitleSuffix) { core.info(`Appending commit title suffix: "${commitTitleSuffix}"`); let patchFileContent = fs.readFileSync(patchFilePath, "utf8"); - patchFileContent = patchFileContent.replace(/^Subject: (?:\[PATCH\] )?(.*)$/gm, (match, title) => `Subject: [PATCH] ${title}${commitTitleSuffix}`); + patchFileContent = patchFileContent.replace(/^Subject: (\[PATCH[^\]]*\] )?(.*)$/gm, (match, patchPrefix, title) => `Subject: ${patchPrefix || "[PATCH] "}${title}${commitTitleSuffix}`); patchFileToApply = nodePath.join(wikiCloneDir, "..", `aw-wiki-modified-${Date.now()}.patch`); fs.writeFileSync(patchFileToApply, patchFileContent, "utf8"); core.info(`Patch modified with commit title suffix`); diff --git a/actions/setup/js/safe_outputs_handlers.cjs b/actions/setup/js/safe_outputs_handlers.cjs index 606024574e9..0f526d97f66 100644 --- a/actions/setup/js/safe_outputs_handlers.cjs +++ b/actions/setup/js/safe_outputs_handlers.cjs @@ -705,6 +705,116 @@ function createHandlers(server, appendSafeOutput, config = {}) { }; }; + /** + * Handler for edit_wiki tool + * Generates a git patch from commits made to a wiki clone directory. + * The agent must clone the wiki repo, commit changes, then call this tool. + * The patch is applied to the wiki repo by the safe_outputs job handler (edit_wiki.cjs). + */ + const editWikiHandler = async args => { + const entry = { ...(args || {}), type: "edit_wiki" }; + const wikiConfig = config.edit_wiki || {}; + + // Determine the wiki directory - from args, config, or standard default location. + // The agent is expected to clone the wiki to this directory and commit changes before + // calling this tool. + const wikiDir = (args && args.wiki_dir) || wikiConfig.wiki_dir || "/tmp/gh-aw/wiki"; + + if (!wikiDir || !fs.existsSync(wikiDir)) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + result: "error", + error: `Wiki directory '${wikiDir}' does not exist. Clone the wiki repo first (e.g. git clone https://github.com/OWNER/REPO.wiki.git /tmp/gh-aw/wiki), commit your changes, then call this tool.`, + }), + }, + ], + isError: true, + }; + } + + // Detect the current branch in the wiki clone (typically 'master' or 'main') + const wikiBranch = getCurrentBranch(wikiDir); + if (!wikiBranch) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + result: "error", + error: `Could not detect current branch in wiki directory '${wikiDir}'. Ensure the directory is a valid git repository with committed changes.`, + }), + }, + ], + isError: true, + }; + } + + server.debug(`Generating incremental patch for edit_wiki from dir=${wikiDir}, branch=${wikiBranch}`); + + // Use incremental mode: include commits since origin/. + // This captures exactly the commits the agent made on top of the cloned state. + const patchOptions = { + mode: "incremental", + cwd: wikiDir, + repoSlug: "wiki", + }; + if (wikiConfig["github-token"]) { + patchOptions.token = wikiConfig["github-token"]; + } + + const patchResult = await generateGitPatch(wikiBranch, wikiBranch, patchOptions); + + if (!patchResult.success) { + const errorMsg = patchResult.error || "Failed to generate patch for wiki changes"; + server.debug(`Wiki patch generation failed: ${errorMsg}`); + return { + content: [ + { + type: "text", + text: JSON.stringify({ + result: "error", + error: errorMsg, + details: "No commits were found in the wiki directory. Make sure you have committed your changes using git add and git commit before calling edit_wiki.", + }), + }, + ], + isError: true, + }; + } + + server.debug(`Wiki patch generated successfully: ${patchResult.patchPath} (${patchResult.patchSize} bytes, ${patchResult.patchLines} lines)`); + + entry.patch_path = patchResult.patchPath; + + if (patchResult.baseCommit) { + entry.base_commit = patchResult.baseCommit; + } + + if (typeof patchResult.diffSize === "number" && patchResult.diffSize >= 0) { + entry.diff_size = patchResult.diffSize; + } + + appendSafeOutput(entry); + return { + content: [ + { + type: "text", + text: JSON.stringify({ + result: "success", + patch: { + path: patchResult.patchPath, + size: patchResult.patchSize, + lines: patchResult.patchLines, + }, + }), + }, + ], + }; + }; + /** * Handler for push_repo_memory tool * Validates that memory files in the configured memory directory are within size limits. @@ -1084,6 +1194,7 @@ function createHandlers(server, appendSafeOutput, config = {}) { uploadArtifactHandler, createPullRequestHandler, pushToPullRequestBranchHandler, + editWikiHandler, pushRepoMemoryHandler, createProjectHandler, addCommentHandler, diff --git a/actions/setup/js/safe_outputs_tools_loader.cjs b/actions/setup/js/safe_outputs_tools_loader.cjs index b13e940cec9..e888622819b 100644 --- a/actions/setup/js/safe_outputs_tools_loader.cjs +++ b/actions/setup/js/safe_outputs_tools_loader.cjs @@ -74,6 +74,7 @@ function attachHandlers(tools, handlers) { const handlerMap = { create_pull_request: handlers.createPullRequestHandler, push_to_pull_request_branch: handlers.pushToPullRequestBranchHandler, + edit_wiki: handlers.editWikiHandler, push_repo_memory: handlers.pushRepoMemoryHandler, upload_asset: handlers.uploadAssetHandler, upload_artifact: handlers.uploadArtifactHandler, diff --git a/pkg/workflow/edit_wiki.go b/pkg/workflow/edit_wiki.go index 3b0a8bb77a3..67319708f6b 100644 --- a/pkg/workflow/edit_wiki.go +++ b/pkg/workflow/edit_wiki.go @@ -64,8 +64,8 @@ func (c *Compiler) parseEditWikiConfig(outputMap map[string]any) *EditWikiConfig } } - // Parse common base fields with default max of 0 (no limit) - c.parseBaseSafeOutputConfig(configMap, &editWikiConfig.BaseSafeOutputConfig, 0) + // Parse common base fields with default max of 1 + c.parseBaseSafeOutputConfig(configMap, &editWikiConfig.BaseSafeOutputConfig, 1) } return editWikiConfig diff --git a/pkg/workflow/js/safe_outputs_tools.json b/pkg/workflow/js/safe_outputs_tools.json index 8714c3fd22e..55d98a08bb3 100644 --- a/pkg/workflow/js/safe_outputs_tools.json +++ b/pkg/workflow/js/safe_outputs_tools.json @@ -1052,6 +1052,10 @@ "integrity": { "type": "string", "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\")." + }, + "wiki_dir": { + "type": "string", + "description": "Path to the local wiki repo clone (e.g., /tmp/gh-aw/wiki). Defaults to /tmp/gh-aw/wiki. Clone the wiki repo with git clone before calling this tool." } }, "additionalProperties": false From 064932ed77820269a05facff5b0cd9f3d65d03e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 23:02:42 +0000 Subject: [PATCH 04/10] Add changeset --- .changeset/patch-add-edit-wiki-safe-output.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/patch-add-edit-wiki-safe-output.md diff --git a/.changeset/patch-add-edit-wiki-safe-output.md b/.changeset/patch-add-edit-wiki-safe-output.md new file mode 100644 index 00000000000..c64f23829bc --- /dev/null +++ b/.changeset/patch-add-edit-wiki-safe-output.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Added the `edit-wiki` safe-output for pushing committed agent changes to repository wikis. From 92de41863725a7708489a93402b18236cc7562df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 23:55:17 +0000 Subject: [PATCH 05/10] fix: add edit_wiki to runtime safe_outputs_tools.json so it is exposed to agents Agent-Logs-Url: https://github.com/github/gh-aw/sessions/2d7b3803-b78a-4521-b3a5-8674bb0a6d1a Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_tools.json | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/actions/setup/js/safe_outputs_tools.json b/actions/setup/js/safe_outputs_tools.json index d333fbcd9a7..76c0708c516 100644 --- a/actions/setup/js/safe_outputs_tools.json +++ b/actions/setup/js/safe_outputs_tools.json @@ -883,6 +883,33 @@ "additionalProperties": false } }, + { + "name": "edit_wiki", + "description": "Push committed changes to a repository wiki. Use this to add or update wiki pages by committing changes locally and then calling this tool. The changes are applied to the main branch of the wiki.", + "inputSchema": { + "type": "object", + "required": ["message"], + "properties": { + "message": { + "type": "string", + "description": "Commit message describing the wiki changes. Follow repository commit message conventions." + }, + "secrecy": { + "type": "string", + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\")." + }, + "integrity": { + "type": "string", + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\")." + }, + "wiki_dir": { + "type": "string", + "description": "Path to the local wiki repo clone (e.g., /tmp/gh-aw/wiki). Defaults to /tmp/gh-aw/wiki. Clone the wiki repo with git clone before calling this tool." + } + }, + "additionalProperties": false + } + }, { "name": "upload_asset", "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content.", From c834f6aefcfdb1662697db8ee2ccd643fd9cbc7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 02:55:22 +0000 Subject: [PATCH 06/10] fix: reuse pushSignedCommits helper for wiki push with auth token in remote URL Agent-Logs-Url: https://github.com/github/gh-aw/sessions/89095bae-c532-4f24-8638-e66af0e5cea1 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/edit_wiki.cjs | 76 +++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/actions/setup/js/edit_wiki.cjs b/actions/setup/js/edit_wiki.cjs index 1a2c7153aa8..1158da3ffbf 100644 --- a/actions/setup/js/edit_wiki.cjs +++ b/actions/setup/js/edit_wiki.cjs @@ -10,6 +10,8 @@ const { isStagedMode } = require("./safe_output_helpers.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs"); const { getGitAuthEnv } = require("./git_helpers.cjs"); +const { createAuthenticatedGitHubClient } = require("./handler_auth.cjs"); +const { pushSignedCommits } = require("./push_signed_commits.cjs"); /** * @typedef {import('./types/handler-factory').HandlerFactoryFunction} HandlerFactoryFunction @@ -35,6 +37,10 @@ async function main(config = {}) { // Build git auth env once for all network operations in this handler. const gitAuthEnv = getGitAuthEnv(config["github-token"]); + // Create authenticated GitHub client (same pattern as push_to_pull_request_branch). + // Used by pushSignedCommits for the signed-commit GraphQL path and fallback git push. + const githubClient = await createAuthenticatedGitHubClient(config); + // Check if we're in staged mode const isStaged = isStagedMode(config); @@ -286,29 +292,61 @@ async function main(config = {}) { core.info("Patch applied to wiki successfully"); - // Push to the wiki branch - core.info(`Pushing wiki changes to: ${wikiBranch}`); - const pushResult = await exec.getExecOutput("git", ["push", "origin", `HEAD:refs/heads/${wikiBranch}`], { - cwd: wikiCloneDir, - env: { ...process.env, ...gitAuthEnv }, - ignoreReturnCode: true, - }); - - if (pushResult.exitCode !== 0) { - const pushError = (pushResult.stderr || pushResult.stdout || "").trim(); - core.error(`Failed to push wiki changes: ${pushError}`); - return { success: false, error: `Failed to push wiki changes: ${pushError || "git push failed"}` }; + // Configure an authenticated remote URL before pushing so that git push + // works reliably from a fresh clone. This mirrors what actions/checkout does + // internally (https://x-access-token:TOKEN@...) and ensures the push succeeds + // even when GIT_CONFIG_* environment variables are not propagated correctly to + // child processes in the github-script execution environment. + const authToken = config["github-token"] || process.env.GITHUB_TOKEN; + if (authToken) { + core.setSecret(authToken); + const serverUrlHost = serverUrl.replace(/^https?:\/\//, "").replace(/\/$/, ""); + const authWikiUrl = `https://x-access-token:${authToken}@${serverUrlHost}/${repoParts.owner}/${repoParts.repo}.wiki.git`; + // Use silent: true to suppress any command logging that could expose the token + // (core.setSecret also masks the value, but defense-in-depth) + const setUrlResult = await exec.getExecOutput("git", ["remote", "set-url", "origin", authWikiUrl], { + cwd: wikiCloneDir, + silent: true, + ignoreReturnCode: true, + }); + if (setUrlResult.exitCode !== 0) { + core.warning(`Failed to set authenticated remote URL: ${(setUrlResult.stderr || "").trim()}`); + } } - core.info("Wiki changes pushed successfully"); - - // Get the commit SHA for the activation comment update + // Push commits using pushSignedCommits (the same helper used by push_to_pull_request_branch). + // Wiki repos are not accessible via the GitHub GraphQL createCommitOnBranch mutation, + // so the GraphQL path will fail gracefully and the fallback git push will be used. + core.info(`Pushing wiki changes to: ${wikiBranch}`); let commitSha = ""; try { - const shaResult = await exec.getExecOutput("git", ["rev-parse", "HEAD"], { cwd: wikiCloneDir }); - commitSha = shaResult.stdout.trim(); - } catch { - // Non-fatal + const pushedSha = await pushSignedCommits({ + githubClient, + owner: repoParts.owner, + repo: `${repoParts.repo}.wiki`, + branch: wikiBranch, + baseRef: `origin/${wikiBranch}`, + cwd: wikiCloneDir, + gitAuthEnv, + }); + if (pushedSha) { + commitSha = pushedSha; + } + core.info("Wiki changes pushed successfully"); + } catch (pushError) { + const pushErrorMessage = getErrorMessage(pushError); + core.error(`Failed to push wiki changes: ${pushErrorMessage}`); + return { success: false, error: `Failed to push wiki changes: ${pushErrorMessage}` }; + } + + // Get the commit SHA for the activation comment update if not set by pushSignedCommits + if (!commitSha) { + try { + const shaResult = await exec.getExecOutput("git", ["rev-parse", "HEAD"], { cwd: wikiCloneDir }); + commitSha = shaResult.stdout.trim(); + } catch { + // Non-fatal + } } const wikiUrl = `${serverUrl}/${repoParts.owner}/${repoParts.repo}/wiki`; From 19dfeb9fd71e47ab625e869bd2999cac5dd490a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 10:43:12 +0000 Subject: [PATCH 07/10] chore: merge main and recompile workflows Agent-Logs-Url: https://github.com/github/gh-aw/sessions/9038c874-9fd3-4d95-975a-73b43a525d93 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-codex.lock.yml | 79 +++++++++++++------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index 9f0851c1211..aac23ed104a 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -1,5 +1,5 @@ # gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"6bb55baf88fda60e6c1c5fea30f7f25c17e972ca47b455d30436d833d0b08565","agent_id":"codex"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29","digest":"sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29","digest":"sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29","digest":"sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29","digest":"sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29","digest":"sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29","digest":"sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -51,7 +51,8 @@ # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 # - actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -154,7 +155,7 @@ jobs: GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "false" - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -164,7 +165,7 @@ jobs: - name: Add hooray reaction for immediate feedback id: react if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REACTION: "hooray" with: @@ -203,7 +204,7 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_FILE: "smoke-codex.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -215,7 +216,7 @@ jobs: await main(); - name: Compute current body text id: sanitized - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,127.0.0.1,172.30.0.1,::1,api.openai.com,api.snapcraft.io,app.renovatebot.com,appveyor.com,archive.ubuntu.com,azure.archive.ubuntu.com,badgen.net,cdn.playwright.dev,circleci.com,codacy.com,codeclimate.com,codecov.io,codeload.github.com,coveralls.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deepsource.io,docs.github.com,drone.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,img.shields.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,localhost,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,readthedocs.io,readthedocs.org,renovatebot.com,s.symcb.com,s.symcd.com,security.ubuntu.com,semaphoreci.com,shields.io,snyk.io,sonarcloud.io,sonarqube.com,storage.googleapis.com,sum.golang.org,travis-ci.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: @@ -227,7 +228,7 @@ jobs: - name: Add comment with workflow run link id: add-comment if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_NAME: "Smoke Codex" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" @@ -350,7 +351,7 @@ jobs: GH_AW_PROMPT_bc54081b7e3e6dfe_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} @@ -365,7 +366,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_ALLOWED_EXTENSIONS: '' @@ -530,7 +531,7 @@ jobs: id: checkout-pr if: | github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} with: @@ -551,7 +552,7 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.29 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -565,7 +566,7 @@ jobs: name: activation path: /tmp/gh-aw - name: Prepare comment memory files - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -866,7 +867,7 @@ jobs: } } } - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1274,7 +1275,7 @@ jobs: MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1337,7 +1338,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1364,7 +1365,7 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,127.0.0.1,172.30.0.1,::1,api.openai.com,api.snapcraft.io,app.renovatebot.com,appveyor.com,archive.ubuntu.com,azure.archive.ubuntu.com,badgen.net,cdn.playwright.dev,circleci.com,codacy.com,codeclimate.com,codecov.io,codeload.github.com,coveralls.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deepsource.io,docs.github.com,drone.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,img.shields.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,localhost,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,readthedocs.io,readthedocs.org,renovatebot.com,s.symcb.com,s.symcd.com,security.ubuntu.com,semaphoreci.com,shields.io,snyk.io,sonarcloud.io,sonarqube.com,storage.googleapis.com,sum.golang.org,travis-ci.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" @@ -1378,7 +1379,7 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log with: @@ -1389,7 +1390,7 @@ jobs: await main(); - name: Parse MCP Scripts logs for step summary if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1399,7 +1400,7 @@ jobs: - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1424,7 +1425,7 @@ jobs: - name: Parse token usage for step summary if: always() continue-on-error: true - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1434,7 +1435,7 @@ jobs: - name: Print AWF reflect summary if: always() continue-on-error: true - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1443,7 +1444,7 @@ jobs: await main(); - name: Generate observability summary if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1537,7 +1538,7 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Report TruffleHog secret scan failure if: always() && needs.trufflehog_scan.result == 'failure' && needs.trufflehog_scan.outputs.secrets_found == 'true' - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_TRUFFLEHOG_SECRETS_LOCATIONS: ${{ needs.trufflehog_scan.outputs.secrets_locations }} @@ -1581,7 +1582,7 @@ jobs: echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - name: Process no-op messages id: noop - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" @@ -1598,7 +1599,7 @@ jobs: await main(); - name: Log detection run id: detection_runs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "Smoke Codex" @@ -1614,7 +1615,7 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" @@ -1628,7 +1629,7 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" @@ -1643,7 +1644,7 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "Smoke Codex" @@ -1671,7 +1672,7 @@ jobs: await main(); - name: Update reaction comment with completion status id: conclusion - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} @@ -1778,7 +1779,7 @@ jobs: ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - name: Setup threat detection if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Smoke Codex" WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Codex engine functionality by reviewing recent PRs twice daily" @@ -1830,18 +1831,18 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_522976f1ac116915_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_f65e75752cff5494_EOF [history] persistence = "none" [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_MCP_CONFIG_522976f1ac116915_EOF + GH_AW_MCP_CONFIG_f65e75752cff5494_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_0a3f3b5cfc125c20_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ebf53c1e8421b544_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { }, @@ -1852,11 +1853,11 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_0a3f3b5cfc125c20_EOF + GH_AW_MCP_CONFIG_ebf53c1e8421b544_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_b24d9d0a4df1647d_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_08930c825fdc3afb_EOF model_provider = "openai-proxy" [model_providers.openai-proxy] name = "OpenAI AWF proxy" @@ -1866,7 +1867,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_b24d9d0a4df1647d_EOF + GH_AW_CODEX_SHELL_POLICY_08930c825fdc3afb_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1917,7 +1918,7 @@ jobs: id: detection_conclusion if: always() continue-on-error: true - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" @@ -1971,7 +1972,7 @@ jobs: job-name: ${{ github.job }} - name: Check team membership for workflow id: check_membership - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" with: @@ -2064,7 +2065,7 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,127.0.0.1,172.30.0.1,::1,api.openai.com,api.snapcraft.io,app.renovatebot.com,appveyor.com,archive.ubuntu.com,azure.archive.ubuntu.com,badgen.net,cdn.playwright.dev,circleci.com,codacy.com,codeclimate.com,codecov.io,codeload.github.com,coveralls.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deepsource.io,docs.github.com,drone.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,img.shields.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,localhost,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,readthedocs.io,readthedocs.org,renovatebot.com,s.symcb.com,s.symcd.com,security.ubuntu.com,semaphoreci.com,shields.io,snyk.io,sonarcloud.io,sonarqube.com,storage.googleapis.com,sum.golang.org,travis-ci.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" From 5e6f65e4aabd71d713a7c2fe079a99bb93446d8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 3 May 2026 15:33:28 +0000 Subject: [PATCH 08/10] chore: merge main and recompile workflows Agent-Logs-Url: https://github.com/github/gh-aw/sessions/ad634f1c-5c55-4f62-bd25-917f3de41bfe Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-codex.lock.yml | 150 +++++++++---------------- 1 file changed, 56 insertions(+), 94 deletions(-) diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index aac23ed104a..f8873d39f8c 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"6bb55baf88fda60e6c1c5fea30f7f25c17e972ca47b455d30436d833d0b08565","agent_id":"codex"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29","digest":"sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29","digest":"sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29","digest":"sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8617bc4f8a38bf55b6cce2fba58f2dafc8eedf642fbcd6f67517eee4380c1cc4","agent_id":"codex"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions-ecosystem/action-add-labels","sha":"c96b68fec76a0987cd93957189e9abd0b9a72ff1","version":"v1.1.3"},{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.35"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.35"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -58,13 +58,12 @@ # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53 +# - ghcr.io/github/gh-aw-firewall/agent:0.25.35 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.35 # - ghcr.io/github/gh-aw-mcpg:v0.3.3 # - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 # - ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 -# - mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2 # - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f name: "Smoke Codex" @@ -151,7 +150,7 @@ jobs: GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","playwright"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.29" + GH_AW_INFO_AWF_VERSION: "v0.25.35" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "false" @@ -194,12 +193,13 @@ jobs: .crush .gemini .opencode + .pi sparse-checkout-cone-mode: true fetch-depth: 1 - name: Save agent config folders for base branch restoration env: - GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" - GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" # poutine:ignore untrusted_checkout_exec run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file @@ -255,25 +255,25 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' + cat << 'GH_AW_PROMPT_7e886d939ae96a38_EOF' - GH_AW_PROMPT_bc54081b7e3e6dfe_EOF + GH_AW_PROMPT_7e886d939ae96a38_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/playwright_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' + cat << 'GH_AW_PROMPT_7e886d939ae96a38_EOF' Tools: add_comment(max:2), create_issue, add_labels, remove_labels, unassign_from_user, hide_comment(max:5), missing_tool, missing_data, noop, add_smoked_label - GH_AW_PROMPT_bc54081b7e3e6dfe_EOF + GH_AW_PROMPT_7e886d939ae96a38_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_comment_memory.md" - cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' + cat << 'GH_AW_PROMPT_7e886d939ae96a38_EOF' - GH_AW_PROMPT_bc54081b7e3e6dfe_EOF + GH_AW_PROMPT_7e886d939ae96a38_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' + cat << 'GH_AW_PROMPT_7e886d939ae96a38_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -305,9 +305,9 @@ jobs: - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). - GH_AW_PROMPT_bc54081b7e3e6dfe_EOF + GH_AW_PROMPT_7e886d939ae96a38_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_bc54081b7e3e6dfe_EOF' + cat << 'GH_AW_PROMPT_7e886d939ae96a38_EOF' ## Serena Code Analysis @@ -348,12 +348,13 @@ jobs: {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/smoke-codex.md}} - GH_AW_PROMPT_bc54081b7e3e6dfe_EOF + GH_AW_PROMPT_7e886d939ae96a38_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "codex" GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} @@ -549,7 +550,11 @@ jobs: - name: Install Codex CLI run: npm install --ignore-scripts -g @openai/codex@0.128.0 - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.29 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.35 + - name: Install Playwright CLI + run: npm install -g @playwright/cli@0.1.11 + - name: Install Playwright CLI skills + run: playwright-cli install --skills - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 @@ -577,19 +582,19 @@ jobs: - name: Restore agent config folders from base branch if: steps.checkout-pr.outcome == 'success' env: - GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" - GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6 ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53 ghcr.io/github/gh-aw-mcpg:v0.3.3 ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.35 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35 ghcr.io/github/gh-aw-firewall/squid:0.25.35 ghcr.io/github/gh-aw-mcpg:v0.3.3 ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - name: Write Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_8e7c0cf18eddaabf_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a3651798fc7a531f_EOF' {"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-codex"]},"add_smoked_label":true,"comment_memory":{"max":1,"memory_id":"default"},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-codex","expires":2,"labels":["automation","testing"],"max":1},"create_report_incomplete_issue":{},"edit_wiki":{"if_no_changes":"warn","max_patch_size":1024},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"remove_labels":{"allowed":["smoke"]},"report_incomplete":{},"unassign_from_user":{"allowed":["githubactionagent"],"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_8e7c0cf18eddaabf_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_a3651798fc7a531f_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -917,7 +922,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_707c316f82e50dc8_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_6836ba84d60d1463_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -947,8 +952,8 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_707c316f82e50dc8_EOF - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_ebe645fb25a62cc1_EOF' + GH_AW_MCP_SCRIPTS_TOOLS_6836ba84d60d1463_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_62c64cf425021ce4_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); const configPath = path.join(__dirname, "tools.json"); @@ -962,12 +967,12 @@ jobs: console.error("Failed to start mcp-scripts HTTP server:", error); process.exit(1); }); - GH_AW_MCP_SCRIPTS_SERVER_ebe645fb25a62cc1_EOF + GH_AW_MCP_SCRIPTS_SERVER_62c64cf425021ce4_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_90453dbdd72e029b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" << 'GH_AW_MCP_SCRIPTS_SH_GH_c49b15be455bb31a_EOF' #!/bin/bash # Auto-generated mcp-script tool: gh # Execute any gh CLI command. This tool is accessible as 'mcpscripts-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh . Use single quotes ' for complex args to avoid shell interpretation issues. @@ -979,7 +984,7 @@ jobs: GH_TOKEN="$GH_AW_GH_TOKEN" gh $INPUT_ARGS - GH_AW_MCP_SCRIPTS_SH_GH_90453dbdd72e029b_EOF + GH_AW_MCP_SCRIPTS_SH_GH_c49b15be455bb31a_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh" - name: Generate MCP Scripts Server Config @@ -1033,12 +1038,11 @@ jobs: run: | set -eo pipefail mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" - mkdir -p /tmp/gh-aw/mcp-logs/playwright - chmod 777 /tmp/gh-aw/mcp-logs/playwright # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -1053,7 +1057,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_MCP_SCRIPTS_PORT -e GH_AW_MCP_SCRIPTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e CODEX_HOME -e GH_AW_GH_TOKEN -e GH_DEBUG -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_dc0f5c421375b6db_EOF [history] persistence = "none" @@ -1079,27 +1083,6 @@ jobs: [mcp_servers.mcpscripts."guard-policies".write-sink] accept = ["*"] - [mcp_servers.playwright] - container = "mcr.microsoft.com/playwright/mcp" - args = [ - "--init", - "--network", - "host", - "--security-opt", - "seccomp=unconfined", - "--ipc=host", - ] - entrypointArgs = [ - "--output-dir", - "/tmp/gh-aw/mcp-logs/playwright" - ] - mounts = ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"] - - [mcp_servers.playwright."guard-policies"] - - [mcp_servers.playwright."guard-policies".write-sink] - accept = ["*"] - [mcp_servers.safeoutputs] type = "http" url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" @@ -1126,11 +1109,11 @@ jobs: [mcp_servers.serena."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF + GH_AW_MCP_CONFIG_dc0f5c421375b6db_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_dc0f5c421375b6db_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -1162,30 +1145,6 @@ jobs: } } }, - "playwright": { - "container": "mcr.microsoft.com/playwright/mcp", - "args": [ - "--init", - "--network", - "host", - "--security-opt", - "seccomp=unconfined", - "--ipc=host" - ], - "entrypointArgs": [ - "--output-dir", - "/tmp/gh-aw/mcp-logs/playwright", - "--no-sandbox" - ], - "mounts": ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"], - "guard-policies": { - "write-sink": { - "accept": [ - "*" - ] - } - } - }, "safeoutputs": { "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", @@ -1240,11 +1199,11 @@ jobs: } } } - GH_AW_MCP_CONFIG_538a08690c8d9f40_EOF + GH_AW_MCP_CONFIG_dc0f5c421375b6db_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_e9ad8250a4e103cc_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_a27ff31dd57422aa_EOF model_provider = "openai-proxy" @@ -1256,7 +1215,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_e9ad8250a4e103cc_EOF + GH_AW_CODEX_SHELL_POLICY_a27ff31dd57422aa_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1291,7 +1250,7 @@ jobs: set -o pipefail mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/schemas/awf-config.v1.json","network":{"allowDomains":["*.githubusercontent.com","172.30.0.1","api.openai.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","docs.github.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","go.dev","golang.org","goproxy.io","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","openai.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","pkg.go.dev","playwright.download.prss.microsoft.com","ppa.launchpad.net","proxy.golang.org","raw.githubusercontent.com","s.symcb.com","s.symcd.com","security.ubuntu.com","storage.googleapis.com","sum.golang.org","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.29,squid=sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53,agent=sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4,agent-act=sha256:97b4cc14dc2123a45b9d5b9927489f66882dec5857de6afc0e5bab257be92ef1,api-proxy=sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6,cli-proxy=sha256:29917488eb90a01ff9544ffeeb5cc26434a8ea16d69ae8972f5f6be0e567e276"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","172.30.0.1","api.openai.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","cdn.playwright.dev","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","docs.github.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","go.dev","golang.org","goproxy.io","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","openai.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","pkg.go.dev","playwright.download.prss.microsoft.com","ppa.launchpad.net","proxy.golang.org","raw.githubusercontent.com","s.symcb.com","s.symcd.com","security.ubuntu.com","storage.googleapis.com","sum.golang.org","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GH_AW_GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log @@ -1661,6 +1620,8 @@ jobs: GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}" GH_AW_GROUP_REPORTS: "false" GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "15" GH_AW_CACHE_MEMORY_ENABLED: "true" with: @@ -1803,9 +1764,9 @@ jobs: - name: Install Codex CLI run: npm install --ignore-scripts -g @openai/codex@0.128.0 - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.29 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.35 - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.29@sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.29@sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6 ghcr.io/github/gh-aw-firewall/squid:0.25.29@sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53 ghcr.io/github/gh-aw-mcpg:v0.3.3 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.35 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35 ghcr.io/github/gh-aw-firewall/squid:0.25.35 ghcr.io/github/gh-aw-mcpg:v0.3.3 - name: Start MCP Gateway id: start-mcp-gateway env: @@ -1817,6 +1778,7 @@ jobs: # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -1831,18 +1793,18 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_f65e75752cff5494_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_c6d506ebc961eaa5_EOF [history] persistence = "none" [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_MCP_CONFIG_f65e75752cff5494_EOF + GH_AW_MCP_CONFIG_c6d506ebc961eaa5_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ebf53c1e8421b544_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_84673a4dcbb2a351_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { }, @@ -1853,11 +1815,11 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_ebf53c1e8421b544_EOF + GH_AW_MCP_CONFIG_84673a4dcbb2a351_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_08930c825fdc3afb_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_023b046afde839aa_EOF model_provider = "openai-proxy" [model_providers.openai-proxy] name = "OpenAI AWF proxy" @@ -1867,7 +1829,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_08930c825fdc3afb_EOF + GH_AW_CODEX_SHELL_POLICY_023b046afde839aa_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1887,7 +1849,7 @@ jobs: set -o pipefail mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/schemas/awf-config.v1.json","network":{"allowDomains":["172.30.0.1","api.openai.com","host.docker.internal","openai.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.29,squid=sha256:8a71ad9e40454051672312917e51567abfb8251d7c294d086c48f63d84e4cb53,agent=sha256:e68f37e36962dcb3f3d1de680a49bc2302cefd001b941a7dc377155ec7ce42f4,agent-act=sha256:97b4cc14dc2123a45b9d5b9927489f66882dec5857de6afc0e5bab257be92ef1,api-proxy=sha256:d1219e4110684402aabbeb5a43858f26790c9d0be210581cf3f7a521bd2c87b6,cli-proxy=sha256:29917488eb90a01ff9544ffeeb5cc26434a8ea16d69ae8972f5f6be0e567e276"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["172.30.0.1","api.openai.com","host.docker.internal","openai.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log From 7a31cf0ae7645d381a4c2b9afe9098c8cb743e48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 3 May 2026 21:37:51 +0000 Subject: [PATCH 09/10] docs: add edit-wiki to scratchpad/dev.md; merge main and recompile Agent-Logs-Url: https://github.com/github/gh-aw/sessions/68909dbe-445b-4ac4-9d3e-6c3aac9389dd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-codex.lock.yml | 42 +++++++++++++++++----- scratchpad/dev.md | 48 +++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index f8873d39f8c..f6853857359 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -134,6 +134,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info @@ -472,6 +475,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Set runtime paths id: set-runtime-paths run: | @@ -587,7 +593,7 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.35 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35 ghcr.io/github/gh-aw-firewall/squid:0.25.35 ghcr.io/github/gh-aw-mcpg:v0.3.3 ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - - name: Write Safe Outputs Config + - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs @@ -595,7 +601,7 @@ jobs: cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a3651798fc7a531f_EOF' {"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-codex"]},"add_smoked_label":true,"comment_memory":{"max":1,"memory_id":"default"},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-codex","expires":2,"labels":["automation","testing"],"max":1},"create_report_incomplete_issue":{},"edit_wiki":{"if_no_changes":"warn","max_patch_size":1024},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"remove_labels":{"allowed":["smoke"]},"report_incomplete":{},"unassign_from_user":{"allowed":["githubactionagent"],"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_a3651798fc7a531f_EOF - - name: Write Safe Outputs Tools + - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { @@ -1244,6 +1250,10 @@ jobs: - name: Clean credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - name: Execute Codex CLI id: agentic_execution run: | @@ -1441,6 +1451,7 @@ jobs: /tmp/gh-aw/mcp-scripts/logs/ /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/otel.jsonl @@ -1495,6 +1506,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Report TruffleHog secret scan failure if: always() && needs.trufflehog_scan.result == 'failure' && needs.trufflehog_scan.outputs.secrets_found == 'true' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 @@ -1680,6 +1694,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1793,18 +1810,18 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_c6d506ebc961eaa5_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_9a805a75a952a510_EOF [history] persistence = "none" [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_MCP_CONFIG_c6d506ebc961eaa5_EOF + GH_AW_MCP_CONFIG_9a805a75a952a510_EOF # Generate JSON config for MCP gateway GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_84673a4dcbb2a351_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_e19470f042069fdb_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { }, @@ -1815,11 +1832,11 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_84673a4dcbb2a351_EOF + GH_AW_MCP_CONFIG_e19470f042069fdb_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_023b046afde839aa_EOF + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_355e0852a9942342_EOF model_provider = "openai-proxy" [model_providers.openai-proxy] name = "OpenAI AWF proxy" @@ -1829,7 +1846,7 @@ jobs: [shell_environment_policy] inherit = "core" include_only = ["CODEX_API_KEY", "HOME", "OPENAI_API_KEY", "PATH"] - GH_AW_CODEX_SHELL_POLICY_023b046afde839aa_EOF + GH_AW_CODEX_SHELL_POLICY_355e0852a9942342_EOF awk ' BEGIN { skip_openai_proxy = 0 } /^[[:space:]]*model_provider[[:space:]]*=/ { next } @@ -1932,6 +1949,9 @@ jobs: with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1994,6 +2014,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact @@ -2238,6 +2261,9 @@ jobs: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Smoke Codex" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-codex.lock.yml@${{ github.ref }} - name: Download cache-memory artifact (default) id: download_cache_default uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/scratchpad/dev.md b/scratchpad/dev.md index f158f364fc5..bf7b4533be6 100644 --- a/scratchpad/dev.md +++ b/scratchpad/dev.md @@ -727,6 +727,9 @@ sequenceDiagram - `create-project-status-update` - `update-release`, `upload-asset` +**Wiki**: +- `edit-wiki` + **Security & Agent Tasks**: - `create-code-scanning-alert` - `create-agent-session` @@ -805,7 +808,49 @@ safe-outputs: The `blocked` field accepts a list of usernames or glob patterns. If the AI agent attempts to assign/unassign a blocked user, the operation is rejected. The `allowed` field restricts which users can be operated on; if omitted, all non-blocked users are permitted. -### Attribution Footers +**Edit Wiki** (`edit-wiki`): +```yaml +safe-outputs: + edit-wiki: # minimal — targets the current repo's wiki + + # or with options: + edit-wiki: + repo: "org/other-repo" # optional, defaults to current repo + allowed-repos: # restricts which repos can be targeted + - "org/other-repo" + if-no-changes: warn # warn | error | ignore (default: warn) + commit-title-suffix: " [bot]" # appended to each commit subject line + github-token: ${{ secrets.MY_TOKEN }} + staged: false +``` + +The agent clones the wiki repo (`OWNER/REPO.wiki.git`) to a local directory, creates or edits wiki page files, commits the changes, then calls the `edit_wiki` tool. The safe-output job applies the patch via `git am --3way` and pushes to the wiki's default branch (`master`). + +Agent usage pattern: +```bash +# 1. Clone the wiki +git clone https://github.com/OWNER/REPO.wiki.git /tmp/gh-aw/wiki +git -C /tmp/gh-aw/wiki config user.email "github-actions[bot]@users.noreply.github.com" +git -C /tmp/gh-aw/wiki config user.name "github-actions[bot]" + +# 2. Create or edit wiki pages +echo "# My Page\nContent here" > /tmp/gh-aw/wiki/My-Page.md + +# 3. Commit the changes +git -C /tmp/gh-aw/wiki add . +git -C /tmp/gh-aw/wiki commit -m "Add My-Page" + +# 4. Call the edit_wiki tool +# { "message": "Add My-Page", "wiki_dir": "/tmp/gh-aw/wiki" } +``` + +Testing `edit-wiki` locally with `smoke-codex.md`: +1. Add `edit-wiki:` under `safe-outputs:` in your workflow +2. Run the workflow: `gh aw run .github/workflows/smoke-codex.md` +3. The smoke test (#10) clones the wiki, creates `Smoke-Test-Haiku.md`, appends a link to `Home.md`, commits, and calls the tool +4. Check the wiki at `https://github.com/OWNER/REPO/wiki` to confirm the new page and link appear + + All GitHub content created by safe outputs includes attribution: @@ -2590,6 +2635,7 @@ type Everything interface { | `add-comment` | 1 | ✅ | `issues: write` or `pull-requests: write` | | `assign-to-user` | 1 | ✅ | `issues: write` | | `unassign-from-user` | 1 | ✅ | `issues: write` | +| `edit-wiki` | 1 | ✅ | `contents: write` | | `missing-tool` | 0 (unlimited) | N/A | Optional `issues: write` | | `noop` | 1 | N/A | None | From d3660095ad135ccda9ddbb69040a0677b9ce38fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 3 May 2026 22:02:27 +0000 Subject: [PATCH 10/10] feat: update dev.md to use copilot engine Agent-Logs-Url: https://github.com/github/gh-aw/sessions/48d1a57e-07de-47c2-accf-ff40bcf95b62 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/dev.lock.yml | 166 +++++++++++++++++++++++---------- .github/workflows/dev.md | 4 +- 2 files changed, 120 insertions(+), 50 deletions(-) diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 60e2c19224e..2f555e9a38c 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"cc975ed0d58d799d184035327af359c4a3225a02a95981b5d20c04fae0f857bf","agent_id":"pi","agent_model":"copilot/claude-sonnet-4-20250514"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d658597134da0d7e2e082417a6c4801759d1d3083432b2b4f75a31fe7982dc10","agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.35"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.35"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.35"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.35"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.3"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -126,18 +126,18 @@ jobs: - name: Generate agentic run info id: generate_aw_info env: - GH_AW_INFO_ENGINE_ID: "pi" - GH_AW_INFO_ENGINE_NAME: "Pi" - GH_AW_INFO_MODEL: "copilot/claude-sonnet-4-20250514" - GH_AW_INFO_VERSION: "0.72.1" - GH_AW_INFO_AGENT_VERSION: "0.72.1" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_AGENT_VERSION: "1.0.40" GH_AW_INFO_WORKFLOW_NAME: "Dev" - GH_AW_INFO_EXPERIMENTAL: "true" + GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' - GH_AW_INFO_FIREWALL_ENABLED: "false" - GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.25.35" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "false" @@ -163,7 +163,7 @@ jobs: await main(); - name: Validate COPILOT_GITHUB_TOKEN secret id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN Pi https://github.github.com/gh-aw/reference/engines/#pi + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Checkout .github and .agents folders @@ -239,20 +239,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_820d0bab622491f3_EOF' + cat << 'GH_AW_PROMPT_c21ca251edb62f3c_EOF' - GH_AW_PROMPT_820d0bab622491f3_EOF + GH_AW_PROMPT_c21ca251edb62f3c_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_820d0bab622491f3_EOF' + cat << 'GH_AW_PROMPT_c21ca251edb62f3c_EOF' Tools: create_issue, missing_tool, missing_data, noop - GH_AW_PROMPT_820d0bab622491f3_EOF + GH_AW_PROMPT_c21ca251edb62f3c_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_820d0bab622491f3_EOF' + cat << 'GH_AW_PROMPT_c21ca251edb62f3c_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -281,19 +281,19 @@ jobs: {{/if}} - GH_AW_PROMPT_820d0bab622491f3_EOF + GH_AW_PROMPT_c21ca251edb62f3c_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_820d0bab622491f3_EOF' + cat << 'GH_AW_PROMPT_c21ca251edb62f3c_EOF' {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/dev.md}} - GH_AW_PROMPT_820d0bab622491f3_EOF + GH_AW_PROMPT_c21ca251edb62f3c_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "pi" + GH_AW_ENGINE_ID: "copilot" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -376,10 +376,14 @@ jobs: GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_WORKFLOW_ID_SANITIZED: dev outputs: + agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} @@ -446,15 +450,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: '24' - package-manager-cache: false + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + env: + GH_HOST: github.com - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.35 - - name: Install Pi CLI - run: npm install --ignore-scripts -g @mariozechner/pi-coding-agent@0.72.1 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 @@ -483,9 +484,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_96fe11ece7634061_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_7b7dd3869d383420_EOF' {"create_issue":{"expires":168,"max":1,"title_prefix":"[Daily Report] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_96fe11ece7634061_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_7b7dd3869d383420_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -674,7 +675,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="pi" + export GH_AW_ENGINE="copilot" export GH_AW_MCP_CLI_SERVERS='["safeoutputs"]' echo 'GH_AW_MCP_CLI_SERVERS=["safeoutputs"]' >> "$GITHUB_ENV" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') @@ -682,6 +683,34 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.3' + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_5a4f9817a0b4b4d0_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_5a4f9817a0b4b4d0_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -711,35 +740,54 @@ jobs: CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.3.3' run: | bash "${RUNNER_TEMP}/gh-aw/actions/start_cli_proxy.sh" - - name: Execute Pi CLI + - name: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 30 run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["api.githubcopilot.com","api.pi.ai","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ - -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && mkdir -p /tmp/gh-aw/pi-agent-dir && echo eyJwcm92aWRlcnMiOnsiYXctZ2F0ZXdheSI6eyJhcGkiOiJvcGVuYWktY29tcGxldGlvbnMiLCJhcGlLZXkiOiJDT1BJTE9UX0dJVEhVQl9UT0tFTiIsImJhc2VVcmwiOiJodHRwOi8vaG9zdC5kb2NrZXIuaW50ZXJuYWw6MTAwMDIiLCJtb2RlbHMiOlt7ImlkIjoiY2xhdWRlLXNvbm5ldC00LTIwMjUwNTE0In1dfX19 | base64 -d > /tmp/gh-aw/pi-agent-dir/models.json && cat /tmp/gh-aw/aw-prompts/prompt.txt | pi --print --mode json --no-session --model aw-gateway/claude-sonnet-4-20250514 --extension "${RUNNER_TEMP}/gh-aw/actions/pi_provider.cjs" --extension "${RUNNER_TEMP}/gh-aw/actions/pi_steering_extension.cjs" 2>&1 | tee /tmp/gh-aw/pi-streaming.jsonl' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_VERSION: dev GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md GITHUB_WORKSPACE: ${{ github.workspace }} GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com GIT_AUTHOR_NAME: github-actions[bot] GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com GIT_COMMITTER_NAME: github-actions[bot] - PI_CODING_AGENT_DIR: /tmp/gh-aw/pi-agent-dir + XDG_CONFIG_HOME: /home/runner - name: Stop CLI Proxy if: always() continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/stop_cli_proxy.sh" + - name: Detect Copilot errors + id: detect-copilot-errors + if: always() + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_copilot_errors.cjs" - name: Configure Git credentials env: REPO_NAME: ${{ github.repository }} @@ -753,6 +801,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -793,7 +845,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "api.githubcopilot.com,api.pi.ai,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -806,12 +858,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/pi-streaming.jsonl + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_pi_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -872,7 +924,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/pi-streaming.jsonl + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/agent_usage.json @@ -1015,9 +1067,14 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "dev" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "12" - GH_AW_ENGINE_ID: "pi" + GH_AW_ENGINE_ID: "copilot" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_GROUP_REPORTS: "false" @@ -1166,35 +1223,49 @@ jobs: with: node-version: '24' package-manager-cache: false + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + env: + GH_HOST: github.com - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.35 - - name: Install Pi CLI - run: npm install --ignore-scripts -g @mariozechner/pi-coding-agent@0.72.1 - - name: Execute Pi CLI + - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["api.githubcopilot.com","api.pi.ai","github.com","host.docker.internal","raw.githubusercontent.com","registry.npmjs.org"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.35/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.35"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && mkdir -p /tmp/gh-aw/pi-agent-dir && echo eyJwcm92aWRlcnMiOnsiYXctZ2F0ZXdheSI6eyJhcGkiOiJvcGVuYWktY29tcGxldGlvbnMiLCJhcGlLZXkiOiJDT1BJTE9UX0dJVEhVQl9UT0tFTiIsImJhc2VVcmwiOiJodHRwOi8vaG9zdC5kb2NrZXIuaW50ZXJuYWw6MTAwMDIiLCJtb2RlbHMiOlt7ImlkIjoiY2xhdWRlLXNvbm5ldC00LTIwMjUwNTE0In1dfX19 | base64 -d > /tmp/gh-aw/pi-agent-dir/models.json && cat /tmp/gh-aw/aw-prompts/prompt.txt | pi --print --mode json --no-session --model aw-gateway/claude-sonnet-4-20250514 --extension "${RUNNER_TEMP}/gh-aw/actions/pi_provider.cjs" --extension "${RUNNER_TEMP}/gh-aw/actions/pi_steering_extension.cjs" 2>&1 | tee /tmp/gh-aw/pi-streaming.jsonl' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.6' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_VERSION: dev + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md GITHUB_WORKSPACE: ${{ github.workspace }} GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com GIT_AUTHOR_NAME: github-actions[bot] GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com GIT_COMMITTER_NAME: github-actions[bot] - PI_CODING_AGENT_DIR: /tmp/gh-aw/pi-agent-dir + XDG_CONFIG_HOME: /home/runner - name: Upload threat detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -1291,8 +1362,9 @@ jobs: GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "pi" - GH_AW_ENGINE_MODEL: "copilot/claude-sonnet-4-20250514" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.40" GH_AW_WORKFLOW_ID: "dev" GH_AW_WORKFLOW_NAME: "Dev" outputs: @@ -1350,7 +1422,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_ALLOWED_DOMAINS: "api.githubcopilot.com,api.pi.ai,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"expires\":168,\"max\":1,\"title_prefix\":\"[Daily Report] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/dev.md b/.github/workflows/dev.md index 1d080fbaa09..61b37dce1e1 100644 --- a/.github/workflows/dev.md +++ b/.github/workflows/dev.md @@ -8,9 +8,7 @@ name: Dev description: Daily status report for gh-aw project timeout-minutes: 30 strict: false -engine: - id: pi - model: copilot/claude-sonnet-4-20250514 +engine: copilot permissions: contents: read