Skip to content

Harden GitHub Action#3542

Merged
koxudaxi merged 1 commit into
mainfrom
harden-github-action
Jul 2, 2026
Merged

Harden GitHub Action#3542
koxudaxi merged 1 commit into
mainfrom
harden-github-action

Conversation

@koxudaxi

@koxudaxi koxudaxi commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added automated smoke testing for the action on pull requests, main-branch pushes, and manual runs.
  • Bug Fixes

    • Improved handling of additional command-line inputs to preserve spacing and special characters.
    • Strengthened action install/version selection and caching for more reliable setup across supported Python environments.
    • Enhanced workflow robustness with safer shell execution and consistent generation verification.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e61a5e9a-9f6c-45c1-8ad1-24f831743d4d

📥 Commits

Reviewing files that changed from the base of the PR and between e7057f5 and 4ae5b77.

📒 Files selected for processing (2)
  • .github/workflows/action-smoke.yaml
  • action.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/action-smoke.yaml
  • action.yml

📝 Walkthrough

Walkthrough

The composite action updates its install and argument handling, and a new smoke workflow exercises generation twice against a prepared schema fixture and validates the output plus sentinel handling.

Changes

Composite action hardening and smoke test

Layer / File(s) Summary
Action.yml dependency install and version resolution
action.yml
Pins actions/setup-python and actions/cache to SHAs, updates the pip cache key to include Python 3.14, and rewrites EXTRAS/VERSION handling with conditional package pinning and shell-safe install settings.
Action.yml extra-args parsing and generator invocation
action.yml
Parses inputs.extra-args into an ARGS array with shlex.split and runs datamodel-codegen with \"${ARGS[@]}\" instead of raw interpolation.
Smoke workflow triggers and job setup
.github/workflows/action-smoke.yaml
Adds a new workflow for pull requests, pushes to main, and manual dispatch, with concurrency cancellation, read-only permissions, and job checkout setup.
Smoke test fixture prep and validation
.github/workflows/action-smoke.yaml
Creates a temp schema fixture with a sentinel filename, runs the local action twice to generate a pydantic_v2.BaseModel, and checks the sentinel plus generated model content.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Workflow
  participant TempFixture
  participant CompositeAction
  participant GeneratedModel
  Workflow->>TempFixture: copy schema and touch sentinel filename
  Workflow->>CompositeAction: run generate step
  CompositeAction->>GeneratedModel: write generated/model.py
  Workflow->>CompositeAction: run generate step again
  CompositeAction->>GeneratedModel: re-write generated/model.py
  Workflow->>GeneratedModel: grep expected class and field
  Workflow->>TempFixture: assert sentinel is absent
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: hardening the GitHub Action workflow and composite action.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch harden-github-action

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

📚 Docs Preview: https://pr-3542.datamodel-code-generator.pages.dev

@codspeed-hq

codspeed-hq Bot commented Jul 2, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 11%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 9 regressed benchmarks
✅ 2 untouched benchmarks
⏩ 98 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime test_perf_all_options_enabled 4.6 s 5.2 s -12.34%
WallTime test_perf_complex_refs 1.7 s 1.9 s -11.55%
WallTime test_perf_kubernetes_style_pydantic_v2 2.2 s 2.5 s -11.22%
WallTime test_perf_stripe_style_pydantic_v2 1.7 s 1.9 s -10.89%
WallTime test_perf_openapi_large 2.6 s 2.9 s -10.72%
WallTime test_perf_large_models_pydantic_v2 3 s 3.4 s -10.71%
WallTime test_perf_aws_style_openapi_pydantic_v2 1.7 s 1.9 s -10.7%
WallTime test_perf_deep_nested 4.5 s 5 s -10.59%
WallTime test_perf_graphql_style_pydantic_v2 689.4 ms 768.2 ms -10.25%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing harden-github-action (4ae5b77) with main (958c5b6)

Open in CodSpeed

Footnotes

  1. 98 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@koxudaxi

koxudaxi commented Jul 2, 2026

Copy link
Copy Markdown
Owner Author

CodSpeed is not actionable for this PR: the diff only touches action.yml and .github/workflows/action-smoke.yaml, with no Python runtime or generation-path changes. Treating the walltime regression report as runner noise.

@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (958c5b6) to head (4ae5b77).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #3542   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          161       161           
  Lines        34363     34363           
  Branches      4011      4011           
=========================================
  Hits         34363     34363           
Flag Coverage Δ
unittests 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/action-smoke.yaml (1)

37-42: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Unused fixture file.

injection.json (line 42) is created but never referenced by any subsequent step — only the injection$(touch action-injection-ran).json fixture is used as input. Consider removing the unused copy.

♻️ Proposed cleanup
           mkdir -p "$RUNNER_TEMP/action-smoke/schemas" "$RUNNER_TEMP/action-smoke/generated"
           cp tests/data/jsonschema/simple_string.json "$RUNNER_TEMP/action-smoke/schemas/injection\$(touch action-injection-ran).json"
-          cp tests/data/jsonschema/simple_string.json "$RUNNER_TEMP/action-smoke/schemas/injection.json"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/action-smoke.yaml around lines 37 - 42, The smoke fixture
setup in the Prepare smoke fixtures step creates an extra copy that is never
used. Remove the redundant cp for the unused injection.json fixture and keep
only the fixture actually referenced later by the action-smoke workflow, using
the existing Prepare smoke fixtures block as the location to update.
action.yml (1)

65-68: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Validate extras against the documented allowlist.

Line 67 embeds raw inputs.extras into the pip requirement. Reject anything outside graphql, http, validation, ruff, and all before building PACKAGE.

Proposed hardening
         EXTRAS=""
         if [ -n "$INPUT_EXTRAS" ]; then
-          EXTRAS="[$INPUT_EXTRAS]"
+          IFS=',' read -r -a REQUESTED_EXTRAS <<< "$INPUT_EXTRAS"
+          NORMALIZED_EXTRAS=()
+          for EXTRA in "${REQUESTED_EXTRAS[@]}"; do
+            EXTRA="${EXTRA//[[:space:]]/}"
+            case "$EXTRA" in
+              graphql|http|validation|ruff|all)
+                NORMALIZED_EXTRAS+=("$EXTRA")
+                ;;
+              *)
+                echo "::error::Unsupported extras value: $EXTRA"
+                exit 1
+                ;;
+            esac
+          done
+          EXTRAS="[$(IFS=,; echo "${NORMALIZED_EXTRAS[*]}")]"
         fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@action.yml` around lines 65 - 68, The `EXTRAS` handling in the action script
is using raw `INPUT_EXTRAS` directly, so `PACKAGE` can be built with unsupported
or unsafe extras. Add validation in the same shell block that sets `EXTRAS` to
reject any value outside the documented allowlist (`graphql`, `http`,
`validation`, `ruff`, `all`) before constructing `PACKAGE`, and keep the change
localized around the `INPUT_EXTRAS`/`EXTRAS` logic so the allowed values are
enforced consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@action.yml`:
- Around line 110-117: The extra-args parsing in the action’s shell script
currently runs `shlex.split` inside process substitution, which can hide parser
failures and let `datamodel-codegen` continue with incomplete arguments.
Refactor the `INPUT_EXTRA_ARGS` handling so the `python3` parser is executed as
a normal command with its exit status checked explicitly before appending to
`ARGS`, and keep the logic localized around the existing `EXTRA_ARG`/`ARGS`
block.

---

Nitpick comments:
In @.github/workflows/action-smoke.yaml:
- Around line 37-42: The smoke fixture setup in the Prepare smoke fixtures step
creates an extra copy that is never used. Remove the redundant cp for the unused
injection.json fixture and keep only the fixture actually referenced later by
the action-smoke workflow, using the existing Prepare smoke fixtures block as
the location to update.

In `@action.yml`:
- Around line 65-68: The `EXTRAS` handling in the action script is using raw
`INPUT_EXTRAS` directly, so `PACKAGE` can be built with unsupported or unsafe
extras. Add validation in the same shell block that sets `EXTRAS` to reject any
value outside the documented allowlist (`graphql`, `http`, `validation`, `ruff`,
`all`) before constructing `PACKAGE`, and keep the change localized around the
`INPUT_EXTRAS`/`EXTRAS` logic so the allowed values are enforced consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0ac8f210-b007-43cb-a92c-5680c7225bf6

📥 Commits

Reviewing files that changed from the base of the PR and between 958c5b6 and e7057f5.

📒 Files selected for processing (2)
  • .github/workflows/action-smoke.yaml
  • action.yml

Comment thread action.yml Outdated
@koxudaxi koxudaxi force-pushed the harden-github-action branch from e7057f5 to 4ae5b77 Compare July 2, 2026 08:48
@koxudaxi koxudaxi merged commit a437c7d into main Jul 2, 2026
59 of 60 checks passed
@koxudaxi koxudaxi deleted the harden-github-action branch July 2, 2026 09:40
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: The PR only modifies action.yml and adds a smoke-test workflow — no Python library, CLI code, generated-output, or template changes. However, action.yml changes alter the behavior of the published GitHub Action for existing users: (1) extra-args is now parsed with shlex.split instead of being injected raw into the shell, so users relying on shell expansion (globs, $VAR, $(...), word-splitting) in extra-args will see different behavior; (2) the extras input is now validated against a fixed whitelist (graphql|http|validation|ruff|all) and any other value now fails the step with an error, whereas before any value was accepted. Both are behavior changes to a documented interface (the GitHub Action), even though they are security hardening. Version SHA pinning, cache-key change, and the expanded version regex are non-breaking.

Content for Release Notes

Default Behavior Changes

  • GitHub Action extra-args no longer undergoes shell expansion - The Action previously appended extra-args directly into the shell command (datamodel-codegen "${ARGS[@]}" ${{ inputs.extra-args }}), so the value was subject to word-splitting, glob expansion, variable expansion, and command substitution. It is now tokenized with Python's shlex.split. Workflows that relied on shell features inside extra-args (globs like *.json, variables like $HOME, or command substitution $(...)) will no longer have them expanded and must pass literal, individually-quoted arguments instead. (Harden GitHub Action #3542)
  • GitHub Action extras input is now validated against a whitelist - Previously any value passed to the extras input was accepted and injected into the pip install spec. It is now validated against the fixed set graphql, http, validation, ruff, all; any other value now fails the install step with ::error::Unsupported extras value: <value> instead of being passed through. Workflows passing extras values outside this set will now error. (Harden GitHub Action #3542)

This analysis was performed by Claude Code Action

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🎉 Released in 0.67.0

This PR is now available in the latest release. See the release notes for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant