feat: add claude_args passthrough and structured_output (closes #1)
Bring the upstream v1 `claude_args` input and `structured_output` output
into this Gitea fork so downstream workflows can run the agent with
arbitrary Claude CLI flags (notably `--json-schema`) and read the
schema-validated verdict back as an action output, without an
agent-written file.
Approach (issue Option B, ported rather than bumped): the production
"Run Claude Code" step previously delegated to the external
anthropics/claude-code-base-action@v0.0.63, which has neither input.
Upstream base-action main has them but has migrated to the Claude Agent
SDK — a wholesale divergence that would change v0.0.63 behavior every
downstream step relies on. Instead this invokes the vendored base-action
directly via `bun run ${github.action_path}/base-action/src/index.ts`
(the same github.action_path pattern prepare.ts already uses, reliable
on Gitea), and ports only the two features onto the v0.0.63 process-spawn
engine.
- base-action/src/run-claude.ts: tokenize claude_args with shell-quote
(comment-line stripping; quoted/file-path schemas survive intact) and
append after the byte-identical BASE_ARGS, so empty claude_args yields
an unchanged arg list; extract structured_output from the stream-json
result event when --json-schema is present, failing loudly if absent.
- base-action/src/index.ts: forward INPUT_CLAUDE_ARGS.
- base-action/action.yml: add claude_args input + structured_output output.
- action.yml: add claude_args input + structured_output output; replace
the external base-action delegation with a direct bun-run of the
vendored copy (full INPUT_*/provider env contract derived from the
vendored validate-env/index); bump the default Claude CLI install to
2.1.160 (--json-schema requires a newer CLI than 1.0.117).
- shell-quote added to both package.json files; root bun.lock reconciled
(it was stale vs package.json — non-frozen installs already resolved
the newer tree).
- Tests for tokenizer, hasJsonSchema, and structured-output extraction.
- README: inputs/outputs tables, "Structured output" + "Version pins".
- examples/gitea-structured-output.yml.
Follow-up (cannot be done from this repo): consumers using a pre-baked
runner image (path_to_claude_code_executable) must rebuild that image
with a --json-schema-capable Claude CLI and restart the runner.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+40
-40
@@ -81,6 +81,10 @@ inputs:
|
||||
description: "Enable automatic fallback to specified model when default model is overloaded"
|
||||
required: false
|
||||
default: ""
|
||||
claude_args:
|
||||
description: "Additional arguments to pass directly to the Claude CLI, forwarded verbatim (e.g. '--json-schema /path/to/schema.json' to get schema-validated output via the structured_output output). Requires a Claude CLI new enough to support the flags used (see README)."
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
# Auth configuration
|
||||
anthropic_api_key:
|
||||
@@ -131,6 +135,9 @@ outputs:
|
||||
execution_file:
|
||||
description: "Path to the Claude Code execution output file"
|
||||
value: ${{ steps.claude-code.outputs.execution_file }}
|
||||
structured_output:
|
||||
description: "JSON string of the schema-validated result when --json-schema is provided in claude_args (parse with fromJSON() or jq)"
|
||||
value: ${{ steps.claude-code.outputs.structured_output }}
|
||||
branch_name:
|
||||
description: "The branch created by Claude Code for this execution"
|
||||
value: ${{ steps.prepare.outputs.CLAUDE_BRANCH }}
|
||||
@@ -177,10 +184,13 @@ runs:
|
||||
if: steps.prepare.outputs.contains_trigger == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
# Install Claude Code if no custom executable is provided
|
||||
# Install Claude Code if no custom executable is provided.
|
||||
# Version must be new enough to support any flags passed via claude_args
|
||||
# (e.g. --json-schema). Runner images that bake their own CLI via
|
||||
# path_to_claude_code_executable must bump their pin independently.
|
||||
if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then
|
||||
echo "Installing Claude Code..."
|
||||
curl -fsSL https://claude.ai/install.sh | bash -s 1.0.117
|
||||
curl -fsSL https://claude.ai/install.sh | bash -s 2.1.160
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
else
|
||||
echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}"
|
||||
@@ -189,50 +199,40 @@ runs:
|
||||
echo "$CLAUDE_DIR" >> "$GITHUB_PATH"
|
||||
fi
|
||||
# TODO pass claude_code_executable as input and use it here
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude-code
|
||||
if: steps.prepare.outputs.contains_trigger == 'true'
|
||||
uses: anthropics/claude-code-base-action@v0.0.63
|
||||
with:
|
||||
prompt_file: /tmp/claude-prompts/claude-prompt.txt
|
||||
allowed_tools: ${{ env.ALLOWED_TOOLS }}
|
||||
disallowed_tools: ${{ env.DISALLOWED_TOOLS }}
|
||||
max_turns: ${{ inputs.max_turns }}
|
||||
timeout_minutes: ${{ inputs.timeout_minutes }}
|
||||
model: ${{ inputs.model || inputs.anthropic_model }}
|
||||
mcp_config: ${{ steps.prepare.outputs.mcp_config }}
|
||||
use_bedrock: ${{ inputs.use_bedrock }}
|
||||
use_vertex: ${{ inputs.use_vertex }}
|
||||
anthropic_api_key: ${{ inputs.anthropic_api_key }}
|
||||
claude_code_oauth_token: ${{ inputs.claude_code_oauth_token }}
|
||||
settings: ${{ inputs.settings }}
|
||||
system_prompt: ${{ inputs.system_prompt }}
|
||||
append_system_prompt: ${{ inputs.append_system_prompt }}
|
||||
claude_env: ${{ inputs.claude_env }}
|
||||
fallback_model: ${{ inputs.fallback_model }}
|
||||
use_node_cache: ${{ inputs.use_node_cache }}
|
||||
shell: bash
|
||||
run: |
|
||||
bun run ${{ github.action_path }}/base-action/src/index.ts
|
||||
env:
|
||||
# Core configuration
|
||||
PROMPT_FILE: /tmp/claude-prompts/claude-prompt.txt
|
||||
ALLOWED_TOOLS: ${{ env.ALLOWED_TOOLS }}
|
||||
DISALLOWED_TOOLS: ${{ env.DISALLOWED_TOOLS }}
|
||||
TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
|
||||
MODEL: ${{ inputs.model || inputs.anthropic_model }}
|
||||
# Core configuration. The vendored base-action reads these INPUT_* env
|
||||
# vars directly (see base-action/src/index.ts), so we map them here
|
||||
# instead of delegating to the external claude-code-base-action. This
|
||||
# lets us forward claude_args and surface structured_output while
|
||||
# keeping the Gitea adaptations this fork relies on.
|
||||
CLAUDE_CODE_ACTION: "1"
|
||||
INPUT_PROMPT_FILE: /tmp/claude-prompts/claude-prompt.txt
|
||||
INPUT_ALLOWED_TOOLS: ${{ env.ALLOWED_TOOLS }}
|
||||
INPUT_DISALLOWED_TOOLS: ${{ env.DISALLOWED_TOOLS }}
|
||||
INPUT_MAX_TURNS: ${{ inputs.max_turns }}
|
||||
INPUT_TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
|
||||
INPUT_MCP_CONFIG: ${{ steps.prepare.outputs.mcp_config }}
|
||||
INPUT_SETTINGS: ${{ inputs.settings }}
|
||||
INPUT_SYSTEM_PROMPT: ${{ inputs.system_prompt }}
|
||||
INPUT_APPEND_SYSTEM_PROMPT: ${{ inputs.append_system_prompt }}
|
||||
INPUT_CLAUDE_ENV: ${{ inputs.claude_env }}
|
||||
INPUT_FALLBACK_MODEL: ${{ inputs.fallback_model }}
|
||||
INPUT_CLAUDE_ARGS: ${{ inputs.claude_args }}
|
||||
ANTHROPIC_MODEL: ${{ inputs.model || inputs.anthropic_model }}
|
||||
MCP_CONFIG: ${{ steps.prepare.outputs.mcp_config }}
|
||||
USE_BEDROCK: ${{ inputs.use_bedrock }}
|
||||
USE_VERTEX: ${{ inputs.use_vertex }}
|
||||
|
||||
# Provider selection (base-action validate-env reads the '1'/'' form).
|
||||
CLAUDE_CODE_USE_BEDROCK: ${{ inputs.use_bedrock == 'true' && '1' || '' }}
|
||||
CLAUDE_CODE_USE_VERTEX: ${{ inputs.use_vertex == 'true' && '1' || '' }}
|
||||
|
||||
# Auth configuration
|
||||
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
|
||||
CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.claude_code_oauth_token }}
|
||||
|
||||
# New settings support
|
||||
SETTINGS: ${{ inputs.settings }}
|
||||
SYSTEM_PROMPT: ${{ inputs.system_prompt }}
|
||||
APPEND_SYSTEM_PROMPT: ${{ inputs.append_system_prompt }}
|
||||
CLAUDE_ENV: ${{ inputs.claude_env }}
|
||||
FALLBACK_MODEL: ${{ inputs.fallback_model }}
|
||||
USE_NODE_CACHE: ${{ inputs.use_node_cache }}
|
||||
|
||||
# GitHub token for repository access
|
||||
GITHUB_TOKEN: ${{ steps.prepare.outputs.GITHUB_TOKEN }}
|
||||
@@ -242,7 +242,7 @@ runs:
|
||||
CLAUDE_GIT_NAME: ${{ inputs.claude_git_name }}
|
||||
CLAUDE_GIT_EMAIL: ${{ inputs.claude_git_email }}
|
||||
|
||||
# Provider configuration (for future cloud provider support)
|
||||
# Provider configuration (for cloud provider support)
|
||||
ANTHROPIC_BASE_URL: ${{ env.ANTHROPIC_BASE_URL }}
|
||||
AWS_REGION: ${{ env.AWS_REGION }}
|
||||
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||
|
||||
Reference in New Issue
Block a user