diff --git a/.github/workflows/artifacts-summary.lock.yml b/.github/workflows/artifacts-summary.lock.yml index d50852028e6..18f70c957e0 100644 --- a/.github/workflows/artifacts-summary.lock.yml +++ b/.github/workflows/artifacts-summary.lock.yml @@ -138,7 +138,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -259,39 +258,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1023,7 +1009,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1060,7 +1045,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1466,7 +1450,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1601,7 +1584,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2033,7 +2015,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2052,8 +2043,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index 25671d7d476..3d199bf8793 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -156,7 +156,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -443,39 +442,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1207,7 +1193,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1243,7 +1228,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2640,7 +2624,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -3072,7 +3055,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3091,8 +3083,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/blog-auditor.lock.yml b/.github/workflows/blog-auditor.lock.yml index af3b880d8c4..5b80322df13 100644 --- a/.github/workflows/blog-auditor.lock.yml +++ b/.github/workflows/blog-auditor.lock.yml @@ -140,7 +140,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -365,39 +364,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1129,7 +1115,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1171,7 +1156,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1990,7 +1974,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,githubnext.com,www.githubnext.com" with: script: | @@ -2422,7 +2405,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2441,8 +2433,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index cd3a08e59b2..f1a72bb6508 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -1086,7 +1086,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1198,39 +1197,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1962,7 +1948,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2017,7 +2002,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2392,7 +2376,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2528,7 +2511,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: brave with: @@ -2961,7 +2943,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2980,8 +2971,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index c12813c9469..96ded769fc1 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -696,7 +696,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -825,39 +824,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1589,7 +1575,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1626,7 +1611,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2072,7 +2056,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2207,7 +2190,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2639,7 +2621,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2658,8 +2649,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml index 06dd06731bd..3eb5f870be3 100644 --- a/.github/workflows/ci-doctor.lock.yml +++ b/.github/workflows/ci-doctor.lock.yml @@ -547,7 +547,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -679,39 +678,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1443,7 +1429,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1480,7 +1465,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1925,7 +1909,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2060,7 +2043,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2492,7 +2474,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2511,8 +2502,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml index 22271560afb..9b81240726c 100644 --- a/.github/workflows/cli-version-checker.lock.yml +++ b/.github/workflows/cli-version-checker.lock.yml @@ -142,7 +142,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -287,39 +286,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1051,7 +1037,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1088,7 +1073,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1588,7 +1572,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1723,7 +1706,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,bun.sh,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,deb.nodesource.com,deno.land,get.pnpm.io,ghcr.io,github.com,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" with: script: | @@ -2155,7 +2137,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2174,8 +2165,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/commit-changes-analyzer.lock.yml b/.github/workflows/commit-changes-analyzer.lock.yml index fe134bb7447..ea9459405f4 100644 --- a/.github/workflows/commit-changes-analyzer.lock.yml +++ b/.github/workflows/commit-changes-analyzer.lock.yml @@ -143,7 +143,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -368,39 +367,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1132,7 +1118,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1164,7 +1149,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1921,7 +1905,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2353,7 +2336,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2372,8 +2364,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index e2f61ee5357..81b081f4980 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -145,7 +145,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -398,39 +397,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1162,7 +1148,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1194,7 +1179,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2273,7 +2257,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com" with: script: | @@ -2705,7 +2688,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2724,8 +2716,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 084232ea276..d793a182912 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -145,7 +145,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -294,39 +293,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1058,7 +1044,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1095,7 +1080,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1808,7 +1792,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1943,7 +1926,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2375,7 +2357,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2394,8 +2385,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index a422f28ddce..ecabce2cc07 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -153,7 +153,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -432,39 +431,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1196,7 +1182,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1228,7 +1213,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -3181,7 +3165,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com,pypi.python.org,pypi.org,pip.pypa.io,*.pythonhosted.org,files.pythonhosted.org,bootstrap.pypa.io,conda.binstar.org,conda.anaconda.org,binstar.org,anaconda.org,repo.continuum.io,repo.anaconda.com" with: script: | @@ -3613,7 +3596,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3632,8 +3624,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml index 4edc1732ea0..a533254a52a 100644 --- a/.github/workflows/craft.lock.yml +++ b/.github/workflows/craft.lock.yml @@ -1086,7 +1086,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1202,39 +1201,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1966,7 +1952,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2003,7 +1988,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2545,7 +2529,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2680,7 +2663,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: craft with: @@ -3113,7 +3095,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3132,8 +3123,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml index b94193e2949..bf6cad259a7 100644 --- a/.github/workflows/daily-doc-updater.lock.yml +++ b/.github/workflows/daily-doc-updater.lock.yml @@ -138,7 +138,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -383,39 +382,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1147,7 +1133,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1179,7 +1164,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1856,7 +1840,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com" with: script: | @@ -2288,7 +2271,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2307,8 +2299,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml index 31bf4127804..88f278cc32c 100644 --- a/.github/workflows/daily-firewall-report.lock.yml +++ b/.github/workflows/daily-firewall-report.lock.yml @@ -152,7 +152,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -323,39 +322,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1087,7 +1073,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1134,7 +1119,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2205,7 +2189,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2340,7 +2323,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.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,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" with: script: | @@ -2772,7 +2754,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2791,8 +2782,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 8f4c5caea4d..feb180b4cf3 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -156,7 +156,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -323,39 +322,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1087,7 +1073,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1124,7 +1109,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2179,7 +2163,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2316,7 +2299,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.enterprise.githubcopilot.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,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,files.pythonhosted.org,github.com,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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" with: script: | @@ -2748,7 +2730,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2767,8 +2758,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-perf-improver.lock.yml b/.github/workflows/daily-perf-improver.lock.yml index 238887d9ce7..a4a91ed76b4 100644 --- a/.github/workflows/daily-perf-improver.lock.yml +++ b/.github/workflows/daily-perf-improver.lock.yml @@ -569,7 +569,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":5},\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -696,39 +695,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1460,7 +1446,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1497,7 +1482,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1973,7 +1957,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":5},\"create_pull_request\":{},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2108,7 +2091,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":5},\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2540,7 +2522,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2559,8 +2550,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-repo-chronicle.lock.yml b/.github/workflows/daily-repo-chronicle.lock.yml index b63f5f1df41..659f7cbcaf0 100644 --- a/.github/workflows/daily-repo-chronicle.lock.yml +++ b/.github/workflows/daily-repo-chronicle.lock.yml @@ -152,7 +152,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -316,39 +315,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1080,7 +1066,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1117,7 +1102,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2072,7 +2056,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2207,7 +2190,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.enterprise.githubcopilot.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,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,files.pythonhosted.org,github.com,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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" with: script: | @@ -2639,7 +2621,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2658,8 +2649,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/daily-test-improver.lock.yml b/.github/workflows/daily-test-improver.lock.yml index daf4b30ccba..b3ed0bf3019 100644 --- a/.github/workflows/daily-test-improver.lock.yml +++ b/.github/workflows/daily-test-improver.lock.yml @@ -569,7 +569,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -696,39 +695,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1460,7 +1446,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1497,7 +1482,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1947,7 +1931,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2082,7 +2065,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_discussion\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2514,7 +2496,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2533,8 +2524,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml index 5812f8c4835..3581513f8c8 100644 --- a/.github/workflows/dev-hawk.lock.yml +++ b/.github/workflows/dev-hawk.lock.yml @@ -531,7 +531,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -649,39 +648,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1413,7 +1399,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1460,7 +1445,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1819,7 +1803,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1954,7 +1937,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2386,7 +2368,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2405,8 +2396,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 084f71c39f3..f4ee7e8e733 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -135,7 +135,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -246,39 +245,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1010,7 +996,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1047,7 +1032,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1366,7 +1350,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1501,7 +1484,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1933,7 +1915,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1952,8 +1943,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml index ab5fd140c22..2d21206af31 100644 --- a/.github/workflows/dictation-prompt.lock.yml +++ b/.github/workflows/dictation-prompt.lock.yml @@ -140,7 +140,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -251,39 +250,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1015,7 +1001,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1052,7 +1037,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1456,7 +1440,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1591,7 +1574,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2023,7 +2005,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2042,8 +2033,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml index 06801895847..048ef114b75 100644 --- a/.github/workflows/duplicate-code-detector.lock.yml +++ b/.github/workflows/duplicate-code-detector.lock.yml @@ -146,7 +146,6 @@ jobs: group: "gh-aw-codex-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":3},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -280,39 +279,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1044,7 +1030,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1080,7 +1065,7 @@ jobs: args = [ "/tmp/gh-aw/safeoutputs/mcp-server.cjs", ] - env = { "GH_AW_SAFE_OUTPUTS" = "${{ env.GH_AW_SAFE_OUTPUTS }}", "GH_AW_SAFE_OUTPUTS_CONFIG" = ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}, "GH_AW_ASSETS_BRANCH" = "${{ env.GH_AW_ASSETS_BRANCH }}", "GH_AW_ASSETS_MAX_SIZE_KB" = "${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}", "GH_AW_ASSETS_ALLOWED_EXTS" = "${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}", "GITHUB_REPOSITORY" = "${{ github.repository }}", "GITHUB_SERVER_URL" = "${{ github.server_url }}" } + env = { "GH_AW_SAFE_OUTPUTS" = "${{ env.GH_AW_SAFE_OUTPUTS }}", "GH_AW_ASSETS_BRANCH" = "${{ env.GH_AW_ASSETS_BRANCH }}", "GH_AW_ASSETS_MAX_SIZE_KB" = "${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}", "GH_AW_ASSETS_ALLOWED_EXTS" = "${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}", "GITHUB_REPOSITORY" = "${{ github.repository }}", "GITHUB_SERVER_URL" = "${{ github.server_url }}" } [mcp_servers.serena] command = "uvx" @@ -1545,7 +1530,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":3},\"missing_tool\":{}}" GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug - name: Redact secrets in logs @@ -1676,7 +1660,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":3},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2108,7 +2091,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2127,8 +2119,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml index c56763ddee5..866b75d07a9 100644 --- a/.github/workflows/example-workflow-analyzer.lock.yml +++ b/.github/workflows/example-workflow-analyzer.lock.yml @@ -142,7 +142,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -374,39 +373,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1138,7 +1124,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1178,7 +1163,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1704,7 +1688,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2136,7 +2119,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2155,8 +2147,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index d597cdf7d29..576a0fb81e2 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -153,7 +153,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -394,39 +393,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1158,7 +1144,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1181,7 +1166,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2220,7 +2204,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2652,7 +2635,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2671,8 +2663,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index b1edd3dbebc..d80c1ce7041 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -140,7 +140,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -400,39 +399,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1164,7 +1150,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1196,7 +1181,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1975,7 +1959,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2407,7 +2390,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2426,8 +2418,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml index 7144cbd426e..7d617c0d180 100644 --- a/.github/workflows/go-pattern-detector.lock.yml +++ b/.github/workflows/go-pattern-detector.lock.yml @@ -145,7 +145,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -371,39 +370,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1135,7 +1121,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1177,7 +1162,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1752,7 +1736,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2184,7 +2167,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2203,8 +2195,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml index 2122e59d87b..0b6e4149648 100644 --- a/.github/workflows/instructions-janitor.lock.yml +++ b/.github/workflows/instructions-janitor.lock.yml @@ -138,7 +138,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -383,39 +382,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1147,7 +1133,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1179,7 +1164,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1854,7 +1838,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com" with: script: | @@ -2286,7 +2269,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2305,8 +2297,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index ea6b6d60e90..9083a820ffd 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -930,7 +930,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\"],\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1023,39 +1022,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1787,7 +1773,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1817,7 +1802,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2082,7 +2066,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"add_labels\\\":{\\\"allowed\\\":[\\\"bug\\\",\\\"feature\\\",\\\"enhancement\\\",\\\"documentation\\\"],\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" with: enable-github-mcp: ${{ secrets.GH_AW_GITHUB_TOKEN != '' }} github-mcp-token: ${{ secrets.GH_AW_GITHUB_TOKEN }} @@ -2218,7 +2201,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\"],\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2650,7 +2632,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2669,8 +2660,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml index 8228340f78a..07b7b5f4bdd 100644 --- a/.github/workflows/lockfile-stats.lock.yml +++ b/.github/workflows/lockfile-stats.lock.yml @@ -142,7 +142,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -387,39 +386,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1151,7 +1137,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1183,7 +1168,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2058,7 +2042,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2490,7 +2473,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2509,8 +2501,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index 2c7d71d1cec..ea3716bf20e 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -172,7 +172,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"},\"post-to-slack-channel\":{\"description\":\"Post a message to a Slack channel. Message must be 200 characters or less. Supports basic Slack markdown: *bold*, _italic_, ~strike~, `code`, ```code block```, \\u003equote, and links \\u003curl|text\\u003e. Requires GH_AW_SLACK_CHANNEL_ID environment variable to be set.\",\"inputs\":{\"message\":{\"description\":\"The message to post (max 200 characters, supports Slack markdown)\",\"required\":true,\"type\":\"string\"}},\"output\":\"Message posted to Slack successfully!\"}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -351,39 +350,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1115,7 +1101,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1333,7 +1318,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2025,7 +2009,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"},\"post-to-slack-channel\":{\"description\":\"Post a message to a Slack channel. Message must be 200 characters or less. Supports basic Slack markdown: *bold*, _italic_, ~strike~, `code`, ```code block```, \\u003equote, and links \\u003curl|text\\u003e. Requires GH_AW_SLACK_CHANNEL_ID environment variable to be set.\",\"inputs\":{\"message\":{\"description\":\"The message to post (max 200 characters, supports Slack markdown)\",\"required\":true,\"type\":\"string\"}},\"output\":\"Message posted to Slack successfully!\"}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2173,7 +2156,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"},\"post-to-slack-channel\":{\"description\":\"Post a message to a Slack channel. Message must be 200 characters or less. Supports basic Slack markdown: *bold*, _italic_, ~strike~, `code`, ```code block```, \\u003equote, and links \\u003curl|text\\u003e. Requires GH_AW_SLACK_CHANNEL_ID environment variable to be set.\",\"inputs\":{\"message\":{\"description\":\"The message to post (max 200 characters, supports Slack markdown)\",\"required\":true,\"type\":\"string\"}},\"output\":\"Message posted to Slack successfully!\"}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2605,7 +2587,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2624,8 +2615,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml index 41a3836115e..eb4e3fc092d 100644 --- a/.github/workflows/mergefest.lock.yml +++ b/.github/workflows/mergefest.lock.yml @@ -486,7 +486,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -600,39 +599,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1364,7 +1350,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1401,7 +1386,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2022,7 +2006,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2157,7 +2140,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: mergefest with: @@ -2590,7 +2572,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2609,8 +2600,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/notion-issue-summary.lock.yml b/.github/workflows/notion-issue-summary.lock.yml index 90aefda7d72..504bddaa3dd 100644 --- a/.github/workflows/notion-issue-summary.lock.yml +++ b/.github/workflows/notion-issue-summary.lock.yml @@ -137,7 +137,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -249,39 +248,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1013,7 +999,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1071,7 +1056,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1324,7 +1308,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1460,7 +1443,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"notion-add-comment\":{\"description\":\"Add a comment to a Notion page\",\"inputs\":{\"comment\":{\"description\":\"The comment text to add\",\"required\":true,\"type\":\"string\"}},\"output\":\"Comment added to Notion successfully!\"}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1892,7 +1874,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1911,8 +1902,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index c09954c3cef..cf547d8ac3d 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -1108,7 +1108,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1246,39 +1245,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -2010,7 +1996,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2054,7 +2039,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2498,7 +2482,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2633,7 +2616,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: summarize with: @@ -3066,7 +3048,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3085,8 +3076,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index 034121c0806..7d79b3b60b2 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -699,7 +699,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":5},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -810,39 +809,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1574,7 +1560,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1611,7 +1596,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1994,7 +1978,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":5},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2129,7 +2112,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":5},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: plan with: @@ -2562,7 +2544,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2581,8 +2572,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 3fd70c9daf8..21c3bb9bca8 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -1373,7 +1373,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"poetry\",\"creative\",\"automation\",\"ai-generated\",\"epic\",\"haiku\",\"sonnet\",\"limerick\"],\"max\":5},\"create_issue\":{\"max\":2},\"create_pull_request\":{},\"create_pull_request_review_comment\":{\"max\":2},\"missing_tool\":{},\"push_to_pull_request_branch\":{},\"update_issue\":{\"max\":2},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1506,39 +1505,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -2270,7 +2256,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2307,7 +2292,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2732,7 +2716,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"poetry\",\"creative\",\"automation\",\"ai-generated\",\"epic\",\"haiku\",\"sonnet\",\"limerick\"],\"max\":5},\"create_issue\":{\"max\":2},\"create_pull_request\":{},\"create_pull_request_review_comment\":{\"max\":2},\"missing_tool\":{},\"push_to_pull_request_branch\":{},\"update_issue\":{\"max\":2},\"upload_asset\":{}}" GH_AW_SAFE_OUTPUTS_STAGED: true GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -2868,7 +2851,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"poetry\",\"creative\",\"automation\",\"ai-generated\",\"epic\",\"haiku\",\"sonnet\",\"limerick\"],\"max\":5},\"create_issue\":{\"max\":2},\"create_pull_request\":{},\"create_pull_request_review_comment\":{\"max\":2},\"missing_tool\":{},\"push_to_pull_request_branch\":{},\"update_issue\":{\"max\":2},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: poem-bot with: @@ -3301,7 +3283,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3320,8 +3311,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml index 358c4fb78e6..e55138de834 100644 --- a/.github/workflows/prompt-clustering-analysis.lock.yml +++ b/.github/workflows/prompt-clustering-analysis.lock.yml @@ -150,7 +150,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -436,39 +435,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1200,7 +1186,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1236,7 +1221,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2393,7 +2377,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com,pypi.python.org,pypi.org,pip.pypa.io,*.pythonhosted.org,files.pythonhosted.org,bootstrap.pypa.io,conda.binstar.org,conda.anaconda.org,binstar.org,anaconda.org,repo.continuum.io,repo.anaconda.com" with: script: | @@ -2825,7 +2808,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2844,8 +2836,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml index 80b205d45b8..03f5b65da75 100644 --- a/.github/workflows/python-data-charts.lock.yml +++ b/.github/workflows/python-data-charts.lock.yml @@ -144,7 +144,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -308,39 +307,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1072,7 +1058,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1109,7 +1094,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1782,7 +1766,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1917,7 +1900,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.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,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" with: script: | @@ -2349,7 +2331,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2368,8 +2359,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index fef71645608..1cc590c015c 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -1134,7 +1134,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1291,39 +1290,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -2055,7 +2041,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2099,7 +2084,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2846,7 +2830,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2983,7 +2966,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: q with: @@ -3416,7 +3398,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3435,8 +3426,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/repo-tree-map.lock.yml b/.github/workflows/repo-tree-map.lock.yml index 9b1896ea836..f199c85c987 100644 --- a/.github/workflows/repo-tree-map.lock.yml +++ b/.github/workflows/repo-tree-map.lock.yml @@ -138,7 +138,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -249,39 +248,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1013,7 +999,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1050,7 +1035,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1490,7 +1474,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1625,7 +1608,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2057,7 +2039,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2076,8 +2067,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/research.lock.yml b/.github/workflows/research.lock.yml index 2861e0d1b99..125a66ba380 100644 --- a/.github/workflows/research.lock.yml +++ b/.github/workflows/research.lock.yml @@ -144,7 +144,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -265,39 +264,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1029,7 +1015,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1066,7 +1051,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1429,7 +1413,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1566,7 +1549,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1998,7 +1980,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2017,8 +2008,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml index 5e9e7507882..5a17d622e3d 100644 --- a/.github/workflows/safe-output-health.lock.yml +++ b/.github/workflows/safe-output-health.lock.yml @@ -148,7 +148,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -413,39 +412,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1177,7 +1163,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1213,7 +1198,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2190,7 +2174,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2622,7 +2605,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2641,8 +2633,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml index e7698d5e074..915b29c9f8f 100644 --- a/.github/workflows/schema-consistency-checker.lock.yml +++ b/.github/workflows/schema-consistency-checker.lock.yml @@ -144,7 +144,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -387,39 +386,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1151,7 +1137,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1174,7 +1159,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2060,7 +2044,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2492,7 +2475,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2511,8 +2503,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index a2d0b66c286..72685d9ad97 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -1133,7 +1133,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1389,39 +1388,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -2153,7 +2139,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -2222,7 +2207,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -3014,7 +2998,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" GH_AW_COMMAND: scout with: @@ -3447,7 +3430,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3466,8 +3458,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/security-fix-pr.lock.yml b/.github/workflows/security-fix-pr.lock.yml index 1f292a23587..e1e8df38d4a 100644 --- a/.github/workflows/security-fix-pr.lock.yml +++ b/.github/workflows/security-fix-pr.lock.yml @@ -136,7 +136,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -381,39 +380,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1145,7 +1131,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1177,7 +1162,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1802,7 +1786,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2234,7 +2217,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2253,8 +2245,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/semantic-function-refactor.lock.yml b/.github/workflows/semantic-function-refactor.lock.yml index d934177dd4d..eda87ed3516 100644 --- a/.github/workflows/semantic-function-refactor.lock.yml +++ b/.github/workflows/semantic-function-refactor.lock.yml @@ -147,7 +147,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -390,39 +389,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1154,7 +1140,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1186,7 +1171,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2152,7 +2136,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2584,7 +2567,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2603,8 +2595,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 67a5714a661..7147aaa586b 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -146,7 +146,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -371,39 +370,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1135,7 +1121,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1167,7 +1152,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1603,7 +1587,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2035,7 +2018,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2054,8 +2046,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index 22b3df6790e..d879b06801c 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -146,7 +146,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -262,39 +261,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1026,7 +1012,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1062,7 +1047,7 @@ jobs: args = [ "/tmp/gh-aw/safeoutputs/mcp-server.cjs", ] - env = { "GH_AW_SAFE_OUTPUTS" = "${{ env.GH_AW_SAFE_OUTPUTS }}", "GH_AW_SAFE_OUTPUTS_CONFIG" = ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}, "GH_AW_ASSETS_BRANCH" = "${{ env.GH_AW_ASSETS_BRANCH }}", "GH_AW_ASSETS_MAX_SIZE_KB" = "${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}", "GH_AW_ASSETS_ALLOWED_EXTS" = "${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}", "GITHUB_REPOSITORY" = "${{ github.repository }}", "GITHUB_SERVER_URL" = "${{ github.server_url }}" } + env = { "GH_AW_SAFE_OUTPUTS" = "${{ env.GH_AW_SAFE_OUTPUTS }}", "GH_AW_ASSETS_BRANCH" = "${{ env.GH_AW_ASSETS_BRANCH }}", "GH_AW_ASSETS_MAX_SIZE_KB" = "${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}", "GH_AW_ASSETS_ALLOWED_EXTS" = "${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}", "GITHUB_REPOSITORY" = "${{ github.repository }}", "GITHUB_SERVER_URL" = "${{ github.server_url }}" } EOF - name: Create prompt env: @@ -1285,7 +1270,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_SAFE_OUTPUTS_STAGED: true GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug @@ -1417,7 +1401,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -1849,7 +1832,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1868,8 +1860,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-copilot.firewall.lock.yml b/.github/workflows/smoke-copilot.firewall.lock.yml index dfd8fdb68f5..4883cd882ec 100644 --- a/.github/workflows/smoke-copilot.firewall.lock.yml +++ b/.github/workflows/smoke-copilot.firewall.lock.yml @@ -146,7 +146,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -267,39 +266,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1031,7 +1017,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1068,7 +1053,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1353,7 +1337,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_SAFE_OUTPUTS_STAGED: true GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1489,7 +1472,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1921,7 +1903,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1940,8 +1931,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml index 1b8eb4e0c04..01d0cbafdbe 100644 --- a/.github/workflows/smoke-copilot.lock.yml +++ b/.github/workflows/smoke-copilot.lock.yml @@ -146,7 +146,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -267,39 +266,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1031,7 +1017,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1068,7 +1053,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1353,7 +1337,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_SAFE_OUTPUTS_STAGED: true GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1489,7 +1472,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1921,7 +1903,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1940,8 +1931,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-detector.lock.yml b/.github/workflows/smoke-detector.lock.yml index 6754fe2d270..14b0ca88b2b 100644 --- a/.github/workflows/smoke-detector.lock.yml +++ b/.github/workflows/smoke-detector.lock.yml @@ -897,7 +897,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1156,39 +1155,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1920,7 +1906,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1956,7 +1941,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2743,7 +2727,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"*\"},\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -3175,7 +3158,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3194,8 +3186,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/smoke-opencode.lock.yml b/.github/workflows/smoke-opencode.lock.yml index 3507949170e..3a08fa150cf 100644 --- a/.github/workflows/smoke-opencode.lock.yml +++ b/.github/workflows/smoke-opencode.lock.yml @@ -150,7 +150,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -247,39 +246,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1011,7 +997,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1041,7 +1026,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -1240,7 +1224,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" - name: Configure OpenCode MCP servers run: | @@ -1304,7 +1287,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" - name: Run OpenCode id: opencode @@ -1317,7 +1299,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} @@ -1453,7 +1434,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -1885,7 +1865,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1904,8 +1893,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); @@ -2759,7 +2747,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" - name: Configure OpenCode MCP servers run: | @@ -2823,7 +2810,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" - name: Run OpenCode id: opencode @@ -2836,7 +2822,6 @@ jobs: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "\"{\\\"create_issue\\\":{\\\"max\\\":1},\\\"missing_tool\\\":{}}\"" GH_AW_SAFE_OUTPUTS_STAGED: "true" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} diff --git a/.github/workflows/static-analysis-report.lock.yml b/.github/workflows/static-analysis-report.lock.yml index a8643915d5f..7f17829d525 100644 --- a/.github/workflows/static-analysis-report.lock.yml +++ b/.github/workflows/static-analysis-report.lock.yml @@ -147,7 +147,6 @@ jobs: group: "gh-aw-claude-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -406,39 +405,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1170,7 +1156,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1206,7 +1191,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2079,7 +2063,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com" with: script: | @@ -2511,7 +2494,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2530,8 +2522,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index ceb73b1f899..4c64f09b2cf 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -550,7 +550,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -706,39 +705,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1470,7 +1456,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1507,7 +1492,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -2223,7 +2207,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2358,7 +2341,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.enterprise.githubcopilot.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,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,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" with: script: | @@ -2790,7 +2772,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2809,8 +2800,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/test-ollama-threat-detection.lock.yml b/.github/workflows/test-ollama-threat-detection.lock.yml index 3f29a42185e..7812f0f6eec 100644 --- a/.github/workflows/test-ollama-threat-detection.lock.yml +++ b/.github/workflows/test-ollama-threat-detection.lock.yml @@ -136,7 +136,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -247,39 +246,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1011,7 +997,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1048,7 +1033,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1297,7 +1281,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1432,7 +1415,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -1864,7 +1846,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -1883,8 +1874,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 55ade636287..a0a392312f8 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -502,7 +502,6 @@ jobs: pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -627,39 +626,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1391,7 +1377,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1428,7 +1413,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1824,7 +1808,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1959,7 +1942,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" GH_AW_COMMAND: tidy with: @@ -2392,7 +2374,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2411,8 +2402,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index a9437a372b9..3897329d4c6 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -896,7 +896,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -1156,39 +1155,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1920,7 +1906,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1964,7 +1949,6 @@ jobs: "args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"], "env": { "GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS", - "GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG, "GH_AW_ASSETS_BRANCH": "$GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB": "$GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS": "$GH_AW_ASSETS_ALLOWED_EXTS", @@ -2766,7 +2750,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "crl3.digicert.com,crl4.digicert.com,ocsp.digicert.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,crl.geotrust.com,ocsp.geotrust.com,crl.thawte.com,ocsp.thawte.com,crl.verisign.com,ocsp.verisign.com,crl.globalsign.com,ocsp.globalsign.com,crls.ssl.com,ocsp.ssl.com,crl.identrust.com,ocsp.identrust.com,crl.sectigo.com,ocsp.sectigo.com,crl.usertrust.com,ocsp.usertrust.com,s.symcb.com,s.symcd.com,json-schema.org,json.schemastore.org,archive.ubuntu.com,security.ubuntu.com,ppa.launchpad.net,keyserver.ubuntu.com,azure.archive.ubuntu.com,api.snapcraft.io,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,*.githubusercontent.com,raw.githubusercontent.com,objects.githubusercontent.com,lfs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,codeload.github.com" GH_AW_COMMAND: unbloat with: @@ -3199,7 +3182,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -3218,8 +3210,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml index fb98fddafdd..d37d304c570 100644 --- a/.github/workflows/video-analyzer.lock.yml +++ b/.github/workflows/video-analyzer.lock.yml @@ -143,7 +143,6 @@ jobs: group: "gh-aw-copilot-${{ github.workflow }}" env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -262,39 +261,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1026,7 +1012,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1063,7 +1048,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1588,7 +1572,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1723,7 +1706,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" GH_AW_ALLOWED_DOMAINS: "api.enterprise.githubcopilot.com,api.github.com,github.com,raw.githubusercontent.com,registry.npmjs.org" with: script: | @@ -2155,7 +2137,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2174,8 +2165,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index 835dc352ecd..32935a7f125 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -146,7 +146,6 @@ jobs: GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" GH_AW_ASSETS_MAX_SIZE_KB: 10240 GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" outputs: output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -269,39 +268,26 @@ jobs: normalized = normalized.toLowerCase(); return normalized; } - const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; - if (!configEnv) { - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); + debug(`Reading config from file: ${configPath}`); + try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } - } else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } + } catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); debug(`Final processed config: ${JSON.stringify(safeOutputsConfig)}`); @@ -1033,7 +1019,6 @@ jobs: env: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }} GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }} GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }} GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }} @@ -1073,7 +1058,6 @@ jobs: "tools": ["*"], "env": { "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}", "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", @@ -1983,7 +1967,6 @@ jobs: GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -2118,7 +2101,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_discussion\":{\"max\":1},\"missing_tool\":{},\"upload_asset\":{}}" GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.enterprise.githubcopilot.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,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,files.pythonhosted.org,github.com,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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" with: script: | @@ -2550,7 +2532,16 @@ jobs: } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -2569,8 +2560,7 @@ jobs: let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/pkg/workflow/compile_config_test.go b/pkg/workflow/compile_config_test.go index 854e148397e..c387a861bde 100644 --- a/pkg/workflow/compile_config_test.go +++ b/pkg/workflow/compile_config_test.go @@ -194,48 +194,21 @@ func TestSafeOutputsConfigGeneration(t *testing.T) { SafeOutputs: config, } - // Use the compiler's generateOutputCollectionStep to test the GH_AW_SAFE_OUTPUTS_CONFIG generation + // Use the compiler's generateOutputCollectionStep to verify config is not in env vars var yamlBuilder strings.Builder compiler.generateOutputCollectionStep(&yamlBuilder, workflowData) generatedYAML := yamlBuilder.String() - // Look specifically for the GH_AW_SAFE_OUTPUTS_CONFIG environment variable line + // Config should NOT be in environment variables anymore - it's in a file configLinePresent := strings.Contains(generatedYAML, "GH_AW_SAFE_OUTPUTS_CONFIG:") if len(tt.expectedInConfig) > 0 { - // If we expect items in config, the config line should be present - if !configLinePresent { - t.Errorf("Expected GH_AW_SAFE_OUTPUTS_CONFIG environment variable to be present, but it was not found") + // Even if we expect items in config, they should be written to file, not env var + if configLinePresent { + t.Errorf("GH_AW_SAFE_OUTPUTS_CONFIG should NOT be in environment variables - config is now in file") return } - - // Extract the config line to check its contents - configLine := "" - lines := strings.Split(generatedYAML, "\n") - for _, line := range lines { - if strings.Contains(line, "GH_AW_SAFE_OUTPUTS_CONFIG:") { - configLine = line - break - } - } - - // Check expected items are present in the config line - for _, expected := range tt.expectedInConfig { - if !strings.Contains(configLine, expected) { - t.Errorf("Expected %q to be in GH_AW_SAFE_OUTPUTS_CONFIG, but it was not found in config line: %s", expected, configLine) - } - } - - // Check unexpected items are not present in the config line - for _, unexpected := range tt.unexpectedInConfig { - if strings.Contains(configLine, unexpected) { - t.Errorf("Did not expect %q to be in GH_AW_SAFE_OUTPUTS_CONFIG, but it was found in config line: %s", unexpected, configLine) - } - } } - // If we don't expect any items and no unexpected items specified, - // the config line may or may not be present (depending on whether SafeOutputs is nil) - // This is acceptable behavior }) } } diff --git a/pkg/workflow/compiler_jobs.go b/pkg/workflow/compiler_jobs.go index 4808928641c..245fb01f33e 100644 --- a/pkg/workflow/compiler_jobs.go +++ b/pkg/workflow/compiler_jobs.go @@ -675,12 +675,7 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) ( // Set GH_AW_SAFE_OUTPUTS to fixed path env["GH_AW_SAFE_OUTPUTS"] = "/tmp/gh-aw/safeoutputs/outputs.jsonl" - // Set GH_AW_SAFE_OUTPUTS_CONFIG with the safe outputs configuration - safeOutputConfig := generateSafeOutputsConfig(data) - if safeOutputConfig != "" { - // The JSON string needs to be properly quoted for YAML - env["GH_AW_SAFE_OUTPUTS_CONFIG"] = fmt.Sprintf("%q", safeOutputConfig) - } + // Config is written to /tmp/gh-aw/safeoutputs/config.json file, not passed as env var // Add asset-related environment variables if upload-assets is configured if data.SafeOutputs.UploadAssets != nil { diff --git a/pkg/workflow/compiler_yaml.go b/pkg/workflow/compiler_yaml.go index 54aa40633f5..04deae12491 100644 --- a/pkg/workflow/compiler_yaml.go +++ b/pkg/workflow/compiler_yaml.go @@ -880,11 +880,7 @@ func (c *Compiler) generateOutputCollectionStep(yaml *strings.Builder, data *Wor yaml.WriteString(" env:\n") yaml.WriteString(" GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}\n") - // Pass the safe-outputs configuration for validation - safeOutputConfig := generateSafeOutputsConfig(data) - if safeOutputConfig != "" { - fmt.Fprintf(yaml, " GH_AW_SAFE_OUTPUTS_CONFIG: %q\n", safeOutputConfig) - } + // Config is written to file, not passed as env var // Add allowed domains configuration for sanitization // Use manually configured domains if available, otherwise compute from network configuration diff --git a/pkg/workflow/js/collect_ndjson_output.cjs b/pkg/workflow/js/collect_ndjson_output.cjs index 994039ddf5f..898f171dcfb 100644 --- a/pkg/workflow/js/collect_ndjson_output.cjs +++ b/pkg/workflow/js/collect_ndjson_output.cjs @@ -302,7 +302,18 @@ async function main() { } } const outputFile = process.env.GH_AW_SAFE_OUTPUTS; - const safeOutputsConfig = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + // Read config from file instead of environment variable + const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; + let safeOutputsConfig; + try { + if (fs.existsSync(configPath)) { + const configFileContent = fs.readFileSync(configPath, "utf8"); + safeOutputsConfig = JSON.parse(configFileContent); + } + } catch (error) { + core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`); + } + if (!outputFile) { core.info("GH_AW_SAFE_OUTPUTS not set, no output to collect"); core.setOutput("output", ""); @@ -321,9 +332,9 @@ async function main() { let expectedOutputTypes = {}; if (safeOutputsConfig) { try { - const rawConfig = JSON.parse(safeOutputsConfig); + // safeOutputsConfig is already a parsed object from the file // Normalize all config keys to use underscores instead of dashes - expectedOutputTypes = Object.fromEntries(Object.entries(rawConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); + expectedOutputTypes = Object.fromEntries(Object.entries(safeOutputsConfig).map(([key, value]) => [key.replace(/-/g, "_"), value])); core.info(`Expected output types: ${JSON.stringify(Object.keys(expectedOutputTypes))}`); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); diff --git a/pkg/workflow/js/collect_ndjson_output.test.cjs b/pkg/workflow/js/collect_ndjson_output.test.cjs index 829c2c469ab..a0351d6dde9 100644 --- a/pkg/workflow/js/collect_ndjson_output.test.cjs +++ b/pkg/workflow/js/collect_ndjson_output.test.cjs @@ -135,7 +135,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true, "add_comment": true}'; + const __config = '{"create_issue": true, "add_comment": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -157,7 +160,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -179,7 +185,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -203,7 +212,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -226,7 +238,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_pull_request": true}'; + const __config = '{"create_pull_request": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -253,7 +268,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true, "add_comment": true}'; + const __config = '{"create_issue": true, "add_comment": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -273,7 +291,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -296,7 +317,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set max to 2 for create_issue - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"max": 2}}'; + const __config = '{"create_issue": {"max": 2}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -320,7 +344,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_discussion": true}'; + const __config = '{"create_discussion": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -346,7 +373,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true, "add_comment": true}'; + const __config = '{"create_issue": true, "add_comment": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -369,7 +399,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_pull_request_review_comment": {"max": 10}}'; + const __config = '{"create_pull_request_review_comment": {"max": 10}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -396,7 +429,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_pull_request_review_comment": {"max": 10}}'; + const __config = '{"create_pull_request_review_comment": {"max": 10}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -423,7 +459,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set max to 5 for create-pull-request-review-comment - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_pull_request_review_comment": {"max": 5}}'; + const __config = '{"create_pull_request_review_comment": {"max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -446,7 +485,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -466,7 +508,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -486,7 +531,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -506,7 +554,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -526,7 +577,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -546,7 +600,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -567,7 +624,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -587,7 +647,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -607,7 +670,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -628,7 +694,10 @@ describe("collect_ndjson_output.cjs", () => { fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -654,7 +723,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true, "add_comment": true}'; + const __config = '{"create_issue": true, "add_comment": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -676,7 +748,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -697,7 +772,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -718,7 +796,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -739,7 +820,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -759,7 +843,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -787,7 +874,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -808,7 +898,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -830,7 +923,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -854,7 +950,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -879,7 +978,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -903,7 +1005,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -927,7 +1032,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -951,7 +1059,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -978,7 +1089,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1003,7 +1117,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1026,7 +1143,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1049,7 +1169,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1072,7 +1195,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1093,7 +1219,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1116,7 +1245,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1145,7 +1277,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1165,7 +1300,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1186,7 +1324,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1207,7 +1348,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1228,7 +1372,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1256,7 +1403,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_labels": true}'; + const __config = '{"add_labels": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1277,7 +1427,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1301,7 +1454,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true, "add_comment": true}'; + const __config = '{"create_issue": true, "add_comment": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1336,7 +1492,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); // Mock fs.writeFileSync to throw an error for the agent_output.json file const originalWriteFileSync = fs.writeFileSync; @@ -1377,7 +1536,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1430,7 +1592,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1457,7 +1622,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1482,7 +1650,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1505,7 +1676,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1532,7 +1706,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1559,7 +1736,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_code_scanning_alert": true}'; + const __config = '{"create_code_scanning_alert": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1586,7 +1766,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1605,7 +1788,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1623,7 +1809,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1641,7 +1830,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1659,7 +1851,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1677,7 +1872,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1693,7 +1891,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1715,7 +1916,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1734,7 +1938,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1755,7 +1962,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1775,7 +1985,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1797,7 +2010,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1816,7 +2032,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1834,7 +2053,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_pull_request": true}'; + const __config = '{"create_pull_request": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1853,7 +2075,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": true}'; + const __config = '{"create_issue": true}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1874,7 +2099,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min to 2 for create_issue - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"min": 2, "max": 5}}'; + const __config = '{"create_issue": {"min": 2, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1894,7 +2122,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min to 3 for create_issue, but we only have 1 item - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"min": 3, "max": 5}}'; + const __config = '{"create_issue": {"min": 3, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1917,7 +2148,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min to 1 for create_issue (satisfied) and min to 2 for add-comment (not satisfied) - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"min": 1, "max": 5}, "add_comment": {"min": 2, "max": 5}}'; + const __config = '{"create_issue": {"min": 1, "max": 5}, "add_comment": {"min": 2, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1938,7 +2172,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min to 0 for create_issue (should be ignored) - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"min": 0, "max": 5}}'; + const __config = '{"create_issue": {"min": 0, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1958,7 +2195,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // No min specified, should default to 0 - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"max": 5}}'; + const __config = '{"create_issue": {"max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -1978,7 +2218,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min to 1 for create_issue, but no items present - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"create_issue": {"min": 1, "max": 5}}'; + const __config = '{"create_issue": {"min": 1, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); @@ -2001,7 +2244,10 @@ Line 3"} fs.writeFileSync(testFile, ndjsonContent); process.env.GH_AW_SAFE_OUTPUTS = testFile; // Set min requirements for different types - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = '{"add_comment": {"min": 2, "max": 5}, "create_discussion": {"min": 1, "max": 5}}'; + const __config = '{"add_comment": {"min": 2, "max": 5}, "create_discussion": {"min": 1, "max": 5}}'; + const configPath = "/tmp/gh-aw/safeoutputs/config.json"; + fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: true }); + fs.writeFileSync(configPath, __config); await eval(`(async () => { ${collectScript} })()`); diff --git a/pkg/workflow/js/safe_outputs_mcp_large_content.test.cjs b/pkg/workflow/js/safe_outputs_mcp_large_content.test.cjs index 02690469f9e..dea1b1ed814 100644 --- a/pkg/workflow/js/safe_outputs_mcp_large_content.test.cjs +++ b/pkg/workflow/js/safe_outputs_mcp_large_content.test.cjs @@ -39,7 +39,7 @@ describe("safe_outputs_mcp_server.cjs large content handling", () => { it("should write large content to file when exceeding 16000 tokens", async () => { // Set up environment process.env.GH_AW_SAFE_OUTPUTS = tempOutputFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = fs.readFileSync(tempConfigFile, "utf8"); + process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH = tempConfigFile; const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); @@ -171,7 +171,7 @@ describe("safe_outputs_mcp_server.cjs large content handling", () => { it("should handle normal content without writing to file", async () => { // Set up environment process.env.GH_AW_SAFE_OUTPUTS = tempOutputFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = fs.readFileSync(tempConfigFile, "utf8"); + process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH = tempConfigFile; const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); @@ -281,7 +281,7 @@ describe("safe_outputs_mcp_server.cjs large content handling", () => { it("should detect JSON content and use .json extension", async () => { // Set up environment process.env.GH_AW_SAFE_OUTPUTS = tempOutputFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = fs.readFileSync(tempConfigFile, "utf8"); + process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH = tempConfigFile; const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); @@ -403,7 +403,7 @@ describe("safe_outputs_mcp_server.cjs large content handling", () => { it("should always use .json extension even for non-JSON content", async () => { // Set up environment process.env.GH_AW_SAFE_OUTPUTS = tempOutputFile; - process.env.GH_AW_SAFE_OUTPUTS_CONFIG = fs.readFileSync(tempConfigFile, "utf8"); + process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH = tempConfigFile; const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); diff --git a/pkg/workflow/js/safe_outputs_mcp_server.cjs b/pkg/workflow/js/safe_outputs_mcp_server.cjs index 08b7da7bf0c..c9e5f69055b 100644 --- a/pkg/workflow/js/safe_outputs_mcp_server.cjs +++ b/pkg/workflow/js/safe_outputs_mcp_server.cjs @@ -58,44 +58,30 @@ function normalizeBranchName(branchName) { return normalized; } -// Handle GH_AW_SAFE_OUTPUTS_CONFIG with default fallback -const configEnv = process.env.GH_AW_SAFE_OUTPUTS_CONFIG; +// Read configuration from file +const configPath = process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH || "/tmp/gh-aw/safeoutputs/config.json"; let safeOutputsConfigRaw; -if (!configEnv) { - // Default config file path - const defaultConfigPath = "/tmp/gh-aw/safeoutputs/config.json"; - debug(`GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: ${defaultConfigPath}`); - - try { - if (fs.existsSync(defaultConfigPath)) { - debug(`Reading config from file: ${defaultConfigPath}`); - const configFileContent = fs.readFileSync(defaultConfigPath, "utf8"); - debug(`Config file content length: ${configFileContent.length} characters`); - // Don't log raw content to avoid exposing sensitive configuration data - debug(`Config file read successfully, attempting to parse JSON`); - safeOutputsConfigRaw = JSON.parse(configFileContent); - debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); - } else { - debug(`Config file does not exist at: ${defaultConfigPath}`); - debug(`Using minimal default configuration`); - safeOutputsConfigRaw = {}; - } - } catch (error) { - debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); - debug(`Falling back to empty configuration`); +debug(`Reading config from file: ${configPath}`); + +try { + if (fs.existsSync(configPath)) { + debug(`Config file exists at: ${configPath}`); + const configFileContent = fs.readFileSync(configPath, "utf8"); + debug(`Config file content length: ${configFileContent.length} characters`); + // Don't log raw content to avoid exposing sensitive configuration data + debug(`Config file read successfully, attempting to parse JSON`); + safeOutputsConfigRaw = JSON.parse(configFileContent); + debug(`Successfully parsed config from file with ${Object.keys(safeOutputsConfigRaw).length} configuration keys`); + } else { + debug(`Config file does not exist at: ${configPath}`); + debug(`Using minimal default configuration`); safeOutputsConfigRaw = {}; } -} else { - debug(`Using GH_AW_SAFE_OUTPUTS_CONFIG from environment variable`); - debug(`Config environment variable length: ${configEnv.length} characters`); - try { - safeOutputsConfigRaw = JSON.parse(configEnv); // uses dashes for keys - debug(`Successfully parsed config from environment: ${JSON.stringify(safeOutputsConfigRaw)}`); - } catch (error) { - debug(`Error parsing config from environment: ${error instanceof Error ? error.message : String(error)}`); - throw new Error(`Failed to parse GH_AW_SAFE_OUTPUTS_CONFIG: ${error instanceof Error ? error.message : String(error)}`); - } +} catch (error) { + debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`); + debug(`Falling back to empty configuration`); + safeOutputsConfigRaw = {}; } const safeOutputsConfig = Object.fromEntries(Object.entries(safeOutputsConfigRaw).map(([k, v]) => [k.replace(/-/g, "_"), v])); diff --git a/pkg/workflow/js/safe_outputs_mcp_server_defaults.test.cjs b/pkg/workflow/js/safe_outputs_mcp_server_defaults.test.cjs index 2e7e38af88a..01bcbee0470 100644 --- a/pkg/workflow/js/safe_outputs_mcp_server_defaults.test.cjs +++ b/pkg/workflow/js/safe_outputs_mcp_server_defaults.test.cjs @@ -17,6 +17,15 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { fs.mkdirSync(tempOutputDir, { recursive: true }); tempConfigFile = path.join(tempOutputDir, "config.json"); + + // Create default config directory and file for all tests + const defaultConfigDir = "/tmp/gh-aw/safeoutputs"; + if (!fs.existsSync(defaultConfigDir)) { + fs.mkdirSync(defaultConfigDir, { recursive: true }); + } + const defaultConfigPath = path.join(defaultConfigDir, "config.json"); + // Create a minimal default config + fs.writeFileSync(defaultConfigPath, JSON.stringify({ create_issue: true, missing_tool: true })); }); afterEach(() => { @@ -34,14 +43,18 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { it("should use default output file when GH_AW_SAFE_OUTPUTS is not set", async () => { // Remove environment variables delete process.env.GH_AW_SAFE_OUTPUTS; - delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH; - // Create default directories + // Create default directories and default config file const defaultOutputDir = "/tmp/gh-aw/safeoutputs"; if (!fs.existsSync(defaultOutputDir)) { fs.mkdirSync(defaultOutputDir, { recursive: true }); } + // Write a default config file so the server can start + const defaultConfigPath = path.join(defaultOutputDir, "config.json"); + fs.writeFileSync(defaultConfigPath, JSON.stringify({ create_issue: true, missing_tool: true })); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -94,7 +107,7 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { // Check that default paths are mentioned in debug output expect(stderr).toContain("GH_AW_SAFE_OUTPUTS not set, using default: /tmp/gh-aw/safeoutputs/outputs.jsonl"); expect(stderr).toContain( - "GH_AW_SAFE_OUTPUTS_CONFIG not set, attempting to read from default path: /tmp/gh-aw/safeoutputs/config.json" + "Reading config from file: /tmp/gh-aw/safeoutputs/config.json" ); resolve(); @@ -105,7 +118,7 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { it("should read config from default file when config file exists", async () => { // Remove environment variables delete process.env.GH_AW_SAFE_OUTPUTS; - delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH; // Create default config file const defaultConfigDir = "/tmp/gh-aw/safeoutputs"; @@ -185,7 +198,7 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { it("should use empty config when default file does not exist", async () => { // Remove environment variables delete process.env.GH_AW_SAFE_OUTPUTS; - delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH; // Ensure default config file does not exist const defaultConfigFile = "/tmp/gh-aw/safeoutputs/config.json"; @@ -254,13 +267,21 @@ describe("safe_outputs_mcp_server.cjs defaults handling", () => { // Set GH_AW_SAFE_OUTPUTS to a path that doesn't exist yet process.env.GH_AW_SAFE_OUTPUTS = testOutputFile; - delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG; + delete process.env.GH_AW_SAFE_OUTPUTS_CONFIG_PATH; // Ensure the directory does NOT exist before starting if (fs.existsSync(testOutputDir)) { fs.rmSync(testOutputDir, { recursive: true, force: true }); } + // Create default config file so the server can start + const defaultConfigDir = "/tmp/gh-aw/safeoutputs"; + if (!fs.existsSync(defaultConfigDir)) { + fs.mkdirSync(defaultConfigDir, { recursive: true }); + } + const defaultConfigPath = path.join(defaultConfigDir, "config.json"); + fs.writeFileSync(defaultConfigPath, JSON.stringify({ create_issue: true, missing_tool: true })); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -333,6 +354,11 @@ describe("safe_outputs_mcp_server.cjs add_labels tool patching", () => { }, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -345,7 +371,7 @@ describe("safe_outputs_mcp_server.cjs add_labels tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -438,6 +464,11 @@ describe("safe_outputs_mcp_server.cjs add_labels tool patching", () => { }, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -450,7 +481,7 @@ describe("safe_outputs_mcp_server.cjs add_labels tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -546,6 +577,11 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { }, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -558,7 +594,7 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -648,6 +684,11 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { }, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -660,7 +701,7 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -746,6 +787,11 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { }, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -758,7 +804,7 @@ describe("safe_outputs_mcp_server.cjs update_issue tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -845,6 +891,11 @@ describe("safe_outputs_mcp_server.cjs upload_asset tool patching", () => { upload_asset: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -857,7 +908,7 @@ describe("safe_outputs_mcp_server.cjs upload_asset tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", GH_AW_ASSETS_MAX_SIZE_KB: "5120", GH_AW_ASSETS_ALLOWED_EXTS: ".pdf,.txt,.md", @@ -947,6 +998,11 @@ describe("safe_outputs_mcp_server.cjs upload_asset tool patching", () => { upload_asset: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -964,7 +1020,7 @@ describe("safe_outputs_mcp_server.cjs upload_asset tool patching", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...envWithoutAssetVars, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -1055,6 +1111,11 @@ describe("safe_outputs_mcp_server.cjs branch parameter handling", () => { create_pull_request: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -1067,7 +1128,7 @@ describe("safe_outputs_mcp_server.cjs branch parameter handling", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -1156,6 +1217,11 @@ describe("safe_outputs_mcp_server.cjs branch parameter handling", () => { push_to_pull_request_branch: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -1168,7 +1234,7 @@ describe("safe_outputs_mcp_server.cjs branch parameter handling", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs.jsonl", }, }); @@ -1260,6 +1326,11 @@ describe("safe_outputs_mcp_server.cjs tool call response format", () => { create_issue: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -1272,7 +1343,7 @@ describe("safe_outputs_mcp_server.cjs tool call response format", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs-iserror.jsonl", }, }); @@ -1361,6 +1432,11 @@ describe("safe_outputs_mcp_server.cjs tool call response format", () => { create_issue: {}, }; + + // Write config to temporary file + const tempConfigPath = path.join("/tmp", `test-config-${Date.now()}-${Math.random().toString(36).substring(7)}.json`); + fs.writeFileSync(tempConfigPath, JSON.stringify(config)); + const serverPath = path.join(__dirname, "safe_outputs_mcp_server.cjs"); return new Promise((resolve, reject) => { @@ -1373,7 +1449,7 @@ describe("safe_outputs_mcp_server.cjs tool call response format", () => { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env, - GH_AW_SAFE_OUTPUTS_CONFIG: JSON.stringify(config), + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: tempConfigPath, GH_AW_SAFE_OUTPUTS: "/tmp/gh-aw/test-outputs-json-response.jsonl", }, }); diff --git a/pkg/workflow/main_job_env_test.go b/pkg/workflow/main_job_env_test.go index 359421ec80b..72e048cae1a 100644 --- a/pkg/workflow/main_job_env_test.go +++ b/pkg/workflow/main_job_env_test.go @@ -32,7 +32,7 @@ func TestMainJobEnvironmentVariables(t *testing.T) { }, }, expectedEnvVars: []string{ - "GH_AW_SAFE_OUTPUTS_CONFIG:", + // Config is now in file, not env var }, shouldHaveEnv: true, }, @@ -50,7 +50,7 @@ func TestMainJobEnvironmentVariables(t *testing.T) { }, }, expectedEnvVars: []string{ - "GH_AW_SAFE_OUTPUTS_CONFIG:", + // Config is now in file, not env var }, shouldHaveEnv: true, }, @@ -185,15 +185,9 @@ This workflow tests that job-level environment variables are properly set for sa t.Error("Expected job-level 'env:' section in agent job") } - // Check for required environment variables - expectedEnvVars := []string{ - " GH_AW_SAFE_OUTPUTS_CONFIG:", - } - - for _, expectedEnvVar := range expectedEnvVars { - if !strings.Contains(agentJobSection, expectedEnvVar) { - t.Errorf("Expected environment variable %q not found in agent job section", expectedEnvVar) - } + // Check that GH_AW_SAFE_OUTPUTS_CONFIG is NOT in environment variables + if strings.Contains(agentJobSection, "GH_AW_SAFE_OUTPUTS_CONFIG:") { + t.Error("GH_AW_SAFE_OUTPUTS_CONFIG should NOT be in environment variables - config is now in file") } // Clean up diff --git a/pkg/workflow/mcp-config.go b/pkg/workflow/mcp-config.go index 6266b67f13f..2442c03c3c2 100644 --- a/pkg/workflow/mcp-config.go +++ b/pkg/workflow/mcp-config.go @@ -120,9 +120,9 @@ func renderSafeOutputsMCPConfigWithOptions(yaml *strings.Builder, isLast bool, i // Use shell environment variables instead of GitHub Actions expressions to prevent template injection // For both Copilot and Claude/Custom engines, reference shell env vars // The actual GitHub expressions are set in the step's env: block + // Config is now read from file, so we don't pass GH_AW_SAFE_OUTPUTS_CONFIG if includeCopilotFields { yaml.WriteString(" \"GH_AW_SAFE_OUTPUTS\": \"\\${GH_AW_SAFE_OUTPUTS}\",\n") - yaml.WriteString(" \"GH_AW_SAFE_OUTPUTS_CONFIG\": \"\\${GH_AW_SAFE_OUTPUTS_CONFIG}\",\n") yaml.WriteString(" \"GH_AW_ASSETS_BRANCH\": \"\\${GH_AW_ASSETS_BRANCH}\",\n") yaml.WriteString(" \"GH_AW_ASSETS_MAX_SIZE_KB\": \"\\${GH_AW_ASSETS_MAX_SIZE_KB}\",\n") yaml.WriteString(" \"GH_AW_ASSETS_ALLOWED_EXTS\": \"\\${GH_AW_ASSETS_ALLOWED_EXTS}\",\n") @@ -130,7 +130,6 @@ func renderSafeOutputsMCPConfigWithOptions(yaml *strings.Builder, isLast bool, i yaml.WriteString(" \"GITHUB_SERVER_URL\": \"\\${GITHUB_SERVER_URL}\"\n") } else { yaml.WriteString(" \"GH_AW_SAFE_OUTPUTS\": \"$GH_AW_SAFE_OUTPUTS\",\n") - yaml.WriteString(" \"GH_AW_SAFE_OUTPUTS_CONFIG\": $GH_AW_SAFE_OUTPUTS_CONFIG,\n") yaml.WriteString(" \"GH_AW_ASSETS_BRANCH\": \"$GH_AW_ASSETS_BRANCH\",\n") yaml.WriteString(" \"GH_AW_ASSETS_MAX_SIZE_KB\": \"$GH_AW_ASSETS_MAX_SIZE_KB\",\n") yaml.WriteString(" \"GH_AW_ASSETS_ALLOWED_EXTS\": \"$GH_AW_ASSETS_ALLOWED_EXTS\",\n") @@ -223,7 +222,7 @@ func renderSafeOutputsMCPConfigTOML(yaml *strings.Builder) { yaml.WriteString(" args = [\n") yaml.WriteString(" \"/tmp/gh-aw/safeoutputs/mcp-server.cjs\",\n") yaml.WriteString(" ]\n") - yaml.WriteString(" env = { \"GH_AW_SAFE_OUTPUTS\" = \"${{ env.GH_AW_SAFE_OUTPUTS }}\", \"GH_AW_SAFE_OUTPUTS_CONFIG\" = ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}, \"GH_AW_ASSETS_BRANCH\" = \"${{ env.GH_AW_ASSETS_BRANCH }}\", \"GH_AW_ASSETS_MAX_SIZE_KB\" = \"${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}\", \"GH_AW_ASSETS_ALLOWED_EXTS\" = \"${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}\", \"GITHUB_REPOSITORY\" = \"${{ github.repository }}\", \"GITHUB_SERVER_URL\" = \"${{ github.server_url }}\" }\n") + yaml.WriteString(" env = { \"GH_AW_SAFE_OUTPUTS\" = \"${{ env.GH_AW_SAFE_OUTPUTS }}\", \"GH_AW_ASSETS_BRANCH\" = \"${{ env.GH_AW_ASSETS_BRANCH }}\", \"GH_AW_ASSETS_MAX_SIZE_KB\" = \"${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}\", \"GH_AW_ASSETS_ALLOWED_EXTS\" = \"${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}\", \"GITHUB_REPOSITORY\" = \"${{ github.repository }}\", \"GITHUB_SERVER_URL\" = \"${{ github.server_url }}\" }\n") } // renderAgenticWorkflowsMCPConfigTOML generates the Agentic Workflows MCP server configuration in TOML format for Codex diff --git a/pkg/workflow/mcp_config_refactor_test.go b/pkg/workflow/mcp_config_refactor_test.go index d78fd4a496f..be2647fa649 100644 --- a/pkg/workflow/mcp_config_refactor_test.go +++ b/pkg/workflow/mcp_config_refactor_test.go @@ -123,11 +123,11 @@ func TestRenderSafeOutputsMCPConfigWithOptions(t *testing.T) { `"tools": ["*"]`, `"env": {`, `"GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}"`, - `"GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}"`, ` }`, }, unexpectedContent: []string{ `${{ env.`, + `GH_AW_SAFE_OUTPUTS_CONFIG`, // Config is now in file, not env var }, }, { @@ -140,7 +140,6 @@ func TestRenderSafeOutputsMCPConfigWithOptions(t *testing.T) { `"args": ["/tmp/gh-aw/safeoutputs/mcp-server.cjs"]`, // Security fix: Now uses shell variables instead of GitHub expressions `"GH_AW_SAFE_OUTPUTS": "$GH_AW_SAFE_OUTPUTS"`, - `"GH_AW_SAFE_OUTPUTS_CONFIG": $GH_AW_SAFE_OUTPUTS_CONFIG`, ` },`, }, unexpectedContent: []string{ @@ -150,6 +149,7 @@ func TestRenderSafeOutputsMCPConfigWithOptions(t *testing.T) { // Verify GitHub expressions are NOT in the output (security fix) `${{ env.`, `${{ toJSON(`, + `GH_AW_SAFE_OUTPUTS_CONFIG`, // Config is now in file, not env var }, }, } @@ -321,7 +321,11 @@ func TestRenderSafeOutputsMCPConfigTOML(t *testing.T) { `"/tmp/gh-aw/safeoutputs/mcp-server.cjs"`, `env = {`, `"GH_AW_SAFE_OUTPUTS" = "${{ env.GH_AW_SAFE_OUTPUTS }}"`, - `${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}`, + } + + unexpectedContent := []string{ + `GH_AW_SAFE_OUTPUTS_CONFIG`, // Config is now in file, not env var + `${{ toJSON(`, } for _, expected := range expectedContent { @@ -329,6 +333,12 @@ func TestRenderSafeOutputsMCPConfigTOML(t *testing.T) { t.Errorf("Expected content not found: %q\nActual output:\n%s", expected, result) } } + + for _, unexpected := range unexpectedContent { + if strings.Contains(result, unexpected) { + t.Errorf("Unexpected content found: %q\nActual output:\n%s", unexpected, result) + } + } } // TestRenderAgenticWorkflowsMCPConfigTOML verifies the Agentic Workflows TOML format helper diff --git a/pkg/workflow/mcp_config_shared_test.go b/pkg/workflow/mcp_config_shared_test.go index d7801e6066d..495f3335096 100644 --- a/pkg/workflow/mcp_config_shared_test.go +++ b/pkg/workflow/mcp_config_shared_test.go @@ -99,7 +99,6 @@ func TestRenderSafeOutputsMCPConfigShared(t *testing.T) { `"command": "node"`, `"/tmp/gh-aw/safeoutputs/mcp-server.cjs"`, `"GH_AW_SAFE_OUTPUTS"`, - `"GH_AW_SAFE_OUTPUTS_CONFIG"`, `"GH_AW_ASSETS_BRANCH"`, `"GH_AW_ASSETS_MAX_SIZE_KB"`, `"GH_AW_ASSETS_ALLOWED_EXTS"`, diff --git a/pkg/workflow/mcp_servers.go b/pkg/workflow/mcp_servers.go index 899f6ffd148..8a18f097084 100644 --- a/pkg/workflow/mcp_servers.go +++ b/pkg/workflow/mcp_servers.go @@ -179,7 +179,7 @@ func (c *Compiler) generateMCPSetup(yaml *strings.Builder, tools map[string]any, // Add safe-outputs env vars if present if hasSafeOutputs { yaml.WriteString(" GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}\n") - yaml.WriteString(" GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}\n") + // Config is now read from file, not passed as env var yaml.WriteString(" GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }}\n") yaml.WriteString(" GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}\n") yaml.WriteString(" GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}\n") diff --git a/pkg/workflow/safe_output_helpers_test.go b/pkg/workflow/safe_output_helpers_test.go index b3417a8d744..392c3f8e716 100644 --- a/pkg/workflow/safe_output_helpers_test.go +++ b/pkg/workflow/safe_output_helpers_test.go @@ -224,8 +224,7 @@ func TestApplySafeOutputEnvToMap(t *testing.T) { SafeOutputs: &SafeOutputsConfig{}, }, expected: map[string]string{ - "GH_AW_SAFE_OUTPUTS": "${{ env.GH_AW_SAFE_OUTPUTS }}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\"{}\"", + "GH_AW_SAFE_OUTPUTS": "${{ env.GH_AW_SAFE_OUTPUTS }}", }, }, { @@ -237,7 +236,6 @@ func TestApplySafeOutputEnvToMap(t *testing.T) { }, expected: map[string]string{ "GH_AW_SAFE_OUTPUTS": "${{ env.GH_AW_SAFE_OUTPUTS }}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\"{}\"", "GH_AW_SAFE_OUTPUTS_STAGED": "true", }, }, @@ -250,7 +248,6 @@ func TestApplySafeOutputEnvToMap(t *testing.T) { }, expected: map[string]string{ "GH_AW_SAFE_OUTPUTS": "${{ env.GH_AW_SAFE_OUTPUTS }}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\"{}\"", "GH_AW_SAFE_OUTPUTS_STAGED": "true", "GH_AW_TARGET_REPO_SLUG": "owner/repo", }, @@ -268,7 +265,6 @@ func TestApplySafeOutputEnvToMap(t *testing.T) { }, expected: map[string]string{ "GH_AW_SAFE_OUTPUTS": "${{ env.GH_AW_SAFE_OUTPUTS }}", - "GH_AW_SAFE_OUTPUTS_CONFIG": "\"{\\\"upload_asset\\\":{}}\"", "GH_AW_ASSETS_BRANCH": "\"gh-aw-assets\"", "GH_AW_ASSETS_MAX_SIZE_KB": "10240", "GH_AW_ASSETS_ALLOWED_EXTS": "\".png,.jpg,.jpeg\"", diff --git a/pkg/workflow/safe_outputs.go b/pkg/workflow/safe_outputs.go index 891a4a8da7c..7d671e10e86 100644 --- a/pkg/workflow/safe_outputs.go +++ b/pkg/workflow/safe_outputs.go @@ -746,9 +746,6 @@ func applySafeOutputEnvToMap(env map[string]string, data *WorkflowData) { env["GH_AW_SAFE_OUTPUTS"] = "${{ env.GH_AW_SAFE_OUTPUTS }}" - safeOutputConfig := generateSafeOutputsConfig(data) - env["GH_AW_SAFE_OUTPUTS_CONFIG"] = fmt.Sprintf("%q", safeOutputConfig) - // Add staged flag if specified if data.TrialMode || data.SafeOutputs.Staged { env["GH_AW_SAFE_OUTPUTS_STAGED"] = "true" diff --git a/pkg/workflow/safe_outputs_mcp_integration_test.go b/pkg/workflow/safe_outputs_mcp_integration_test.go index e4cf2209194..21284c73414 100644 --- a/pkg/workflow/safe_outputs_mcp_integration_test.go +++ b/pkg/workflow/safe_outputs_mcp_integration_test.go @@ -73,9 +73,14 @@ Test safe outputs workflow with MCP server integration. t.Error("Expected safeoutputs MCP server to be configured with node command") } - // Check that safe outputs config is properly set - if !strings.Contains(yamlStr, "GH_AW_SAFE_OUTPUTS_CONFIG") { - t.Error("Expected GH_AW_SAFE_OUTPUTS_CONFIG environment variable to be set") + // Check that safe outputs config is written to file, not as environment variable + if strings.Contains(yamlStr, "GH_AW_SAFE_OUTPUTS_CONFIG:") { + t.Error("GH_AW_SAFE_OUTPUTS_CONFIG should NOT be in environment variables - config is now in file") + } + + // Check that config file is created + if !strings.Contains(yamlStr, "cat > /tmp/gh-aw/safeoutputs/config.json") { + t.Error("Expected config file to be created") } t.Log("Safe outputs MCP server integration test passed") diff --git a/pkg/workflow/safe_outputs_mcp_server_test.go b/pkg/workflow/safe_outputs_mcp_server_test.go index bd4c39fc8cb..7249be46e78 100644 --- a/pkg/workflow/safe_outputs_mcp_server_test.go +++ b/pkg/workflow/safe_outputs_mcp_server_test.go @@ -37,12 +37,22 @@ func NewMCPTestClient(t *testing.T, outputFile string, config map[string]any) *M env = append(env, "GITHUB_SERVER_URL=https://github.com") env = append(env, "GITHUB_REPOSITORY=test/repo") + // Write config to file in the same directory as the output file if config != nil { + configFile := filepath.Join(filepath.Dir(outputFile), "config.json") configJSON, err := json.Marshal(config) if err != nil { t.Fatalf("Failed to marshal config: %v", err) } - env = append(env, fmt.Sprintf("GH_AW_SAFE_OUTPUTS_CONFIG=%s", string(configJSON))) + if err := os.WriteFile(configFile, configJSON, 0644); err != nil { + t.Fatalf("Failed to write config file: %v", err) + } + // Set config path environment variable to point to the test config file + env = append(env, fmt.Sprintf("GH_AW_SAFE_OUTPUTS_CONFIG_PATH=%s", configFile)) + // Clean up config file after test + t.Cleanup(func() { + os.Remove(configFile) + }) } // Create command for the MCP server