Gate base-action settingSources default on event type

Defaults to user-only under pull_request_target/workflow_run; otherwise
keeps user,project,local. Wrapper's runtime default unchanged.

🏠 Remote-Dev: homespace
This commit is contained in:
Octavian Guzu 2026-04-23 17:21:02 +00:00
parent 12f457aad8
commit a551ae4682
No known key found for this signature in database
5 changed files with 49 additions and 16 deletions

View File

@ -27,7 +27,7 @@ jobs:
with: with:
prompt: "List all available tools" prompt: "List all available tools"
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# base-action defaults setting_sources to "user"; opt in to project so .mcp.json is discovered # Explicitly include project so .mcp.json is discovered regardless of the event-gated default
setting_sources: "user,project" setting_sources: "user,project"
env: env:
# Change to test directory so it finds .mcp.json # Change to test directory so it finds .mcp.json
@ -110,8 +110,9 @@ jobs:
with: with:
prompt: "List all available tools" prompt: "List all available tools"
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# mcp_config input was removed; pass via claude_args. setting_sources stays at the # mcp_config input was removed; pass via claude_args. Pin setting_sources to "user"
# default ("user") so .mcp.json is NOT auto-discovered — this proves the flag works. # so .mcp.json is NOT auto-discovered — this proves the flag itself works.
setting_sources: "user"
claude_args: >- claude_args: >-
--mcp-config '{"mcpServers":{"test-server":{"type":"stdio","command":"bun","args":["simple-mcp-server.ts"],"env":{}}}}' --mcp-config '{"mcpServers":{"test-server":{"type":"stdio","command":"bun","args":["simple-mcp-server.ts"],"env":{}}}}'
env: env:

View File

@ -94,7 +94,7 @@ Add the following to your workflow file:
| `max_turns` | Maximum number of conversation turns (default: no limit) | No | '' | | `max_turns` | Maximum number of conversation turns (default: no limit) | No | '' |
| `mcp_config` | Path to the MCP configuration JSON file, or MCP configuration JSON string | No | '' | | `mcp_config` | Path to the MCP configuration JSON file, or MCP configuration JSON string | No | '' |
| `settings` | Path to Claude Code settings JSON file, or settings JSON string | No | '' | | `settings` | Path to Claude Code settings JSON file, or settings JSON string | No | '' |
| `setting_sources` | Comma-separated setting sources to load (`user`, `project`, `local`). Project/local merge permissions additively. | No | 'user' | | `setting_sources` | Comma-separated setting sources to load (`user`, `project`, `local`). Project/local merge permissions additively. | No | event-dependent (see below) |
| `system_prompt` | Override system prompt | No | '' | | `system_prompt` | Override system prompt | No | '' |
| `append_system_prompt` | Append to system prompt | No | '' | | `append_system_prompt` | Append to system prompt | No | '' |
| `claude_env` | Custom environment variables to pass to Claude Code execution (YAML multiline format) | No | '' | | `claude_env` | Custom environment variables to pass to Claude Code execution (YAML multiline format) | No | '' |

View File

@ -19,7 +19,7 @@ inputs:
required: false required: false
default: "" default: ""
setting_sources: setting_sources:
description: "Comma-separated list of setting sources to load (user, project, local). Defaults to 'user' only. Project/local settings additively merge permissions with allowed_tools — set to 'user,project,local' to opt in." description: "Comma-separated list of setting sources to load (user, project, local). Defaults to 'user,project,local'; under pull_request_target/workflow_run, defaults to 'user' only. Project/local settings additively merge permissions with allowed_tools — set explicitly to control which sources load."
required: false required: false
default: "" default: ""

View File

@ -272,16 +272,20 @@ export function parseSdkOptions(options: ClaudeOptions): ParsedSdkOptions {
env, env,
// Setting sources precedence: direct input > --setting-sources in claude_args > default. // Setting sources precedence: direct input > --setting-sources in claude_args > default.
// The default is supplied by the caller (base-action uses ["user"]; the wrapper action // The default is supplied by the caller (the wrapper action passes
// uses ["user","project","local"]). Both action.yml files leave the YAML default empty // ["user","project","local"]); base-action applies an event-gated default of ["user"]
// so that --setting-sources in claude_args is reachable when the input is not set. // under pull_request_target/workflow_run and ["user","project","local"] otherwise.
// Both action.yml files leave the YAML default empty so that --setting-sources in
// claude_args is reachable when the input is not set.
settingSources: (options.settingSources settingSources: (options.settingSources
? options.settingSources.split(",").map((s) => s.trim()) ? options.settingSources.split(",").map((s) => s.trim())
: extraArgs["setting-sources"] : extraArgs["setting-sources"]
? extraArgs["setting-sources"].split(",").map((s) => s.trim()) ? extraArgs["setting-sources"].split(",").map((s) => s.trim())
: (options.defaultSettingSources ?? [ : (options.defaultSettingSources ??
"user", (process.env.GITHUB_EVENT_NAME === "pull_request_target" ||
])) as SdkOptions["settingSources"], process.env.GITHUB_EVENT_NAME === "workflow_run"
? ["user"]
: ["user", "project", "local"]))) as SdkOptions["settingSources"],
}; };
// Remove setting-sources from extraArgs to avoid passing it twice // Remove setting-sources from extraArgs to avoid passing it twice

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bun #!/usr/bin/env bun
import { describe, test, expect } from "bun:test"; import { describe, test, expect, afterEach } from "bun:test";
import { parseSdkOptions } from "../src/parse-sdk-options"; import { parseSdkOptions } from "../src/parse-sdk-options";
import type { ClaudeOptions } from "../src/run-claude"; import type { ClaudeOptions } from "../src/run-claude";
@ -424,9 +424,36 @@ describe("parseSdkOptions", () => {
}); });
describe("settingSources", () => { describe("settingSources", () => {
test("should default to ['user'] when not specified", () => { const originalEventName = process.env.GITHUB_EVENT_NAME;
const options: ClaudeOptions = {}; afterEach(() => {
const result = parseSdkOptions(options); if (originalEventName === undefined) {
delete process.env.GITHUB_EVENT_NAME;
} else {
process.env.GITHUB_EVENT_NAME = originalEventName;
}
});
test("should default to ['user','project','local'] for non-gated events", () => {
process.env.GITHUB_EVENT_NAME = "push";
const result = parseSdkOptions({});
expect(result.sdkOptions.settingSources).toEqual([
"user",
"project",
"local",
]);
});
test("should default to ['user'] under pull_request_target", () => {
process.env.GITHUB_EVENT_NAME = "pull_request_target";
const result = parseSdkOptions({});
expect(result.sdkOptions.settingSources).toEqual(["user"]);
});
test("should default to ['user'] under workflow_run", () => {
process.env.GITHUB_EVENT_NAME = "workflow_run";
const result = parseSdkOptions({});
expect(result.sdkOptions.settingSources).toEqual(["user"]); expect(result.sdkOptions.settingSources).toEqual(["user"]);
}); });
@ -477,7 +504,8 @@ describe("parseSdkOptions", () => {
]); ]);
}); });
test("should use defaultSettingSources when nothing else is set", () => { test("explicit defaultSettingSources overrides the event-gated default", () => {
process.env.GITHUB_EVENT_NAME = "pull_request_target";
const options: ClaudeOptions = { const options: ClaudeOptions = {
defaultSettingSources: ["user", "project", "local"], defaultSettingSources: ["user", "project", "local"],
}; };