Skip to content

fix: restore version outputs from CLI builds - #854

Closed
davidmfinol wants to merge 2 commits into
game-ci:mainfrom
davidmfinol:codex/fix-cli-version-outputs
Closed

davidmfinol wants to merge 2 commits into
game-ci:mainfrom
davidmfinol:codex/fix-cli-version-outputs

Conversation

@davidmfinol

@davidmfinol davidmfinol commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

What's Changed

  • Restore build and Android version outputs when the CLI only prints them, fixing missing-version package uploads like this failure.
  • Handle Windows and Unix line endings and preserve failed-build reporting.
  • Add regression coverage; all 52 tests, type checks, lint, formatting, and the bundled action build pass locally.

Summary by CodeRabbit

  • New Features
    • Successful CLI runs now publish recognized build version and Android version code outputs, including values written without a trailing line break.
  • Bug Fixes
    • Existing CLI outputs are preserved, and malformed or unrelated output lines are ignored.
    • Failed CLI runs do not publish captured version outputs. Nonzero exits publish only the exit code and mark the action as failed; launch errors mark the action as failed without publishing outputs.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Cat Gif

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3ae44212-4adf-4c07-9067-6bd9b6f9d924
📥 Commits

Reviewing files that changed from the base of the PR and between 6737734 and cb3f62e.

⛔ Files ignored due to path filters (2)
  • dist/index.js is excluded by !**/dist/**
  • dist/index.js.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (3)
  • src/cli-outputs.ts
  • src/index.test.ts
  • src/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/index.test.ts
  • src/index.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The action parses buildVersion and androidVersionCode records from CLI stdout. It publishes collected records only after a successful CLI exit. Tests cover parsing, exit handling, and output line endings.

Changes

CLI Output Flow

Layer / File(s) Summary
Collect and parse CLI output
src/cli-outputs.ts, src/index.test.ts
collectCliOutputs() incrementally decodes stdout and records recognized version lines. Tests cover recognized and ignored records, repeated values, and empty or malformed records.
Publish records after successful execution
src/index.ts, src/index.test.ts
run connects the collector to CLI stdout and forwards collected records after a successful exit. Tests cover nonzero exits, launch errors, and LF, CRLF, and unterminated final lines.

Priority: ➖ Normal

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant run
  participant CLI
  participant versionOutputs as collectCliOutputs
  participant core as core.setOutput
  run->>versionOutputs: Create stdout collector
  run->>CLI: Execute with stdout listener
  CLI-->>versionOutputs: Send stdout chunks
  run->>CLI: Receive exit code
  alt Exit code is zero
    run->>versionOutputs: Call finish()
    versionOutputs-->>run: Return parsed records
    run->>core: Publish each record
  else Exit code is nonzero
    run->>run: Return without forwarding collected outputs
  end
Loading

Merge Risk: ⚪ Minimal · up to cb3f6

The default CLI’s version outputs match the action’s collector, and no actionable merge risk was identified.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 67377

Strict parsing and success-only forwarding limit the new output path. No security vulnerability was established, but the origin of matching log records and their interaction with direct CLI output writes remain uncertain.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The new bridge directly affects two build-metadata outputs for the current action invocation. Broader release, asset, or environment consequences depend on external consumers that were not supplied. The CLI process itself already had direct output-file access before this change.

Security Findings and Attack Paths

  • inferred — A party able to place exact matching records on CLI stdout could influence the forwarded version values if the CLI exits successfully. Repository evidence does not establish that less-trusted project output has this capability or that downstream consumers turn it into a security-sensitive outcome; this remains an exposure question, not a verified attack path.

Trust Boundaries and Controls

  • observed — Anchored parsing requires an allowed name and a nonempty value without quotes or line breaks. The action forwards through core.setOutput rather than constructing output-file records itself. Failure gating applies to buffered records, not to native writes already made by the CLI.

Resilience and Maintainability Implications

  • observed — Each invocation receives fresh collector state, and the normal entrypoint calls run once. Output publication uses separate writes with no rollback; an exception marks the action failed but does not retract prior writes. No reconciliation policy is implemented for simultaneous native and forwarded values. Runtime interruption and duplicate-key resolution remain unverified.

Hardening Proposals

  • proposed — Document which CLI versions produce these records and whether project logs can reproduce them. If native and forwarded outputs can coexist, define authoritative precedence and validate that contract with a mixed-writer regression case.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: restoring version outputs from CLI builds.
Description check ✅ Passed The description explains the fix, line-ending handling, failed-build behavior, and regression testing. It omits the template sections for related issues, related PRs, a successful workflow run link, a…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files.
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 a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

A rabbit watched the stdout stream,
And gathered versions line by line.
It saved the last record for each,
Then shared them when the run was fine.
No final newline stopped its work,
The rabbit hopped away at nine.

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

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.10%. Comparing base (ae01712) to head (cb3f62e).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #854      +/-   ##
==========================================
+ Coverage   91.26%   92.10%   +0.84%     
==========================================
  Files           3        4       +1     
  Lines         103      114      +11     
  Branches       27       28       +1     
==========================================
+ Hits           94      105      +11     
  Misses          6        6              
  Partials        3        3              
Files with missing lines Coverage Δ
src/cli-outputs.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@frostebite

Copy link
Copy Markdown
Member

Thanks for chasing this down - and you're right that it's the CLI migration rather than your project's config.

game-ci's core.setOutput has only ever printed a line:

(mock) Output "buildVersion" is set to "1.166.0"

It never wrote the file a runner hands the step. That was harmless for as long as the CLI was the action. When unity-builder became a subprocess wrapper (#844, first shipped in v6.0.0) the action started relying on the CLI to publish buildVersion/androidVersionCode itself, on the reasoning that $GITHUB_OUTPUT is inherited by the child and needs no forwarding. Nothing ever wrote them, so both outputs have come out empty on every Unity build going through the CLI since v6.0.0.

So this PR is a correct read of the symptom, but the cause is on the CLI side, and the fix belongs there: src/module/actions/core.ts now appends a real record to $GITHUB_OUTPUT (the delimiter form, since the value is user-supplied and key=value cannot carry a newline) and keeps the printed line only as the no-runner fallback. $GITHUB_OUTPUT already reaches the CLI through process.env, so the wrapper needs no change at all - which is why I'd rather fix it here than parse the log line.

PR: game-ci/cli#301

It needs a CLI release before it reaches anyone. cliVersion defaults to latest, so no unity-builder release is required for that. Once it ships, the cli-outputs.ts parse in this PR can go away.

🤖 Addressed by Claude Code

frostebite added a commit to game-ci/cli that referenced this pull request Oct 3, 2026
… them (#301)

core.setOutput logged `(mock) Output "<key>" is set to "<value>"` and
returned; it never wrote the file a runner hands the step. The shim has
behaved that way since the first CLI commit, which was harmless while the
CLI *was* the action.

It stopped being harmless when unity-builder became a subprocess wrapper
(#844, first shipped in v6.0.0): the action runs the CLI as a child and
relies on it to publish buildVersion/androidVersionCode, since
$GITHUB_OUTPUT is inherited. Nothing published them, so both outputs
arrived empty on every Unity build.

Mirror the real @actions/core split - append to $GITHUB_OUTPUT when it is
set, and keep the printed line only as the standalone fallback. The
delimiter form is load-bearing: the value is a user-supplied version
string, and `key=value` cannot carry a newline.

Refs game-ci/unity-builder#854

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@davidmfinol

Copy link
Copy Markdown
Member Author

Awesome, closing this PR

@davidmfinol davidmfinol closed this Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants