Skip to content

changelog: switch prepare-artifact bool CLI params to bool?#3410

Open
cotti wants to merge 2 commits into
mainfrom
fix/changelog-prepare-artifact-nullable-bools
Open

changelog: switch prepare-artifact bool CLI params to bool?#3410
cotti wants to merge 2 commits into
mainfrom
fix/changelog-prepare-artifact-nullable-bools

Conversation

@cotti
Copy link
Copy Markdown
Contributor

@cotti cotti commented May 27, 2026

Summary

The changelog prepare-artifact command exposed isFork, canCommit, and maintainerCanModify as plain bool parameters. The Argh CLI framework treats bool as a presence-only switch — --flag sets true, omission leaves false. There is no --flag <value> form.

When elastic/docs-actions shelled --can-commit \"$CAN_COMMIT\" into this command (where \$CAN_COMMIT was the literal string \"true\" or \"false\"), the parser took the bare --can-commit as true and silently dropped the literal \"false\" as a stray positional. Every fork PR ended up with can_commit: true in the artifact metadata, which then routed the apply step into the commit-and-push branch where it failed on a detached-HEAD push.

See elastic/elastic-otel-java#1117's submit run for the user-visible failure mode.

Changes

Switching the three boolean parameters to bool? so:

  • Argh now generates --[no-]flag pairs for each one. --can-commit sets true, --no-can-commit sets false, omission leaves null. The --help output makes this explicit:
    ```
    --[no-]is-fork
    --[no-]can-commit
    --[no-]maintainer-can-modify
    ```
  • Callers that want to express "explicitly false" have a correct syntax to do so (--no-can-commit) instead of the silently-broken --flag false.
  • The service coerces nullfalse when writing ChangelogArtifactMetadata, so an omitted flag never grants commit permission to the downstream apply step (fail closed).

Behaviour summary at the CLI

Invocation Before After
--can-commit true true
--no-can-commit (not recognised) false
(omitted) false false (null → false)
--can-commit false true (literal "false" dropped silently — the bug) true (literal "false" still dropped — Argh design, but now there's a correct alternative)

Companion PR

The companion workflow fix in elastic/docs-actions#172 stops emitting --flag <value> patterns in the first place — the action now only appends the affirmative flag when the upstream string equals \"true\". The two PRs together close the loop.

Tests

  • New PrepareArtifact_NullableBoolsUnspecified_CoerceToFalseInMetadata asserts the fail-closed null → false coercion, which is the contract the apply step relies on.
  • Existing fork-fields tests (PrepareArtifact_ForkFields_PersistedInMetadata, PrepareArtifact_ForkNoMaintainerEdits_CanCommitFalse) still cover the explicit true/false paths — boolbool? is an implicit conversion at the call sites so they keep compiling unchanged.
  • All 33 evaluation/metadata tests pass.

Test plan

  • dotnet format --verify-no-changes clean.
  • ./build.sh build --skip-dirty-check succeeds (lint + compile).
  • dotnet publish src/tooling/docs-builder/docs-builder.csproj -c Release succeeds with 0 trimmer warnings (AOT path stays clean).
  • docs-builder changelog prepare-artifact --help now shows --[no-]is-fork, --[no-]can-commit, --[no-]maintainer-can-modify.
  • End-to-end against the AOT binary: --is-fork --no-can-commit --maintainer-can-modify writes is_fork: true, can_commit: false, maintainer_can_modify: true. Omitting --can-commit writes can_commit: false.
  • Merge alongside changelog/submit: stop routing fork PRs through the broken commit path docs-actions#172 and re-trigger an elastic-otel-java fork PR; should produce a comment-only changelog with no commit attempt.

Made with Cursor

The `changelog prepare-artifact` command exposed `isFork`, `canCommit`,
and `maintainerCanModify` as plain `bool` parameters. The Argh CLI
framework treats `bool` as a presence-only switch — `--flag` sets true,
omission leaves false. There is no `--flag <value>` form.

When `elastic/docs-actions` shelled `--can-commit "$CAN_COMMIT"` into
this command (where `$CAN_COMMIT` was the string "true" or "false"),
the parser took the bare `--can-commit` as "true" and silently dropped
the literal "false" as a stray positional. Every fork PR ended up with
`can_commit: true` in the artifact metadata, which then routed the
apply step into the commit-and-push branch where it failed on a
detached-HEAD push.

This commit changes the three boolean parameters to `bool?` so:

- Argh now generates `--[no-]flag` pairs for each one. `--can-commit`
  sets true, `--no-can-commit` sets false, omission leaves null. The
  `--help` output makes this explicit.
- Callers that want to express "explicitly false" have a correct
  syntax to do so instead of the silently-broken `--flag false`.
- The service coerces `null` → `false` when writing
  `ChangelogArtifactMetadata`, so an omitted flag never grants
  commit permission to the downstream apply step (fail closed).

Behaviour summary at the CLI:

  Before               After
  -------------------  -------------------------
  --can-commit         --can-commit             → true
  (omitted)            --no-can-commit          → false
  --can-commit false   (omitted)                → false  (null → false)

The companion workflow fix in elastic/docs-actions#172 stops emitting
`--flag <value>` patterns in the first place and only appends the
affirmative flag when the upstream string equals "true".

Tests:

- New PrepareArtifact_NullableBoolsUnspecified_CoerceToFalseInMetadata
  asserts the fail-closed null → false coercion, which is the
  contract the apply step relies on.
- Existing fork-fields tests still cover the explicit true/false paths
  (bool → bool? is an implicit conversion at the call sites).

Verified with the AOT binary against a fixture staging dir:
`docs-builder changelog prepare-artifact --is-fork --no-can-commit
--maintainer-can-modify ...` writes
`is_fork: true, can_commit: false, maintainer_can_modify: true` as
expected.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cotti cotti requested a review from a team as a code owner May 27, 2026 18:26
@cotti cotti requested a review from Mpdreamz May 27, 2026 18:26
@cotti cotti temporarily deployed to integration-tests May 27, 2026 18:26 — with GitHub Actions Inactive
@cotti cotti self-assigned this May 27, 2026
@cotti cotti added the fix label May 27, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

Review Change Stack

Warning

Review limit reached

@cotti, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes and 15 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 90b767ec-ad75-4bc2-b9f9-6e964936f714

📥 Commits

Reviewing files that changed from the base of the PR and between 03e3fe9 and 09650bf.

📒 Files selected for processing (2)
  • docs/cli-schema.json
  • src/tooling/docs-builder/Commands/ChangelogCommand.cs
📝 Walkthrough

Walkthrough

This PR implements tri-state boolean handling for changelog artifact CLI parameters. The IsFork, CanCommit, and MaintainerCanModify flags are changed from non-nullable bool to nullable bool? throughout the CLI binding and service layers, allowing the system to distinguish between "flag not provided" (null) and "explicitly set to false" (false). The service coerces unspecified null values to concrete false in persisted metadata, and a regression test verifies this fail-closed behavior.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: converting three boolean CLI parameters from non-nullable bool to nullable bool? to fix the command-line parsing issue.
Description check ✅ Passed The description is comprehensive and directly addresses the changeset, explaining the bug (Argh CLI framework treating bool as presence-only), the fix (switching to bool?), and the behavioral impact with a clear comparison table.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/changelog-prepare-artifact-nullable-bools

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 and usage tips.

The previous commit moved the bool→bool? rationale into a regular
`//` comment block sitting between the XML `<param>` lines and the
method declaration. That terminated the XML doc comment group for the
schema source-generator, which then dropped every param summary for
this command and broke the `Check CLI schema is up to date` CI step.

- Inline the explanation into the existing `<remarks>` block as a
  `<para>`, restoring the unbroken XML doc group above the method.
- Regenerate `docs/cli-schema.json` so it reflects the bool? CLI
  surface: the three flags now serialize with the updated summaries
  and `defaultValue: "default"` (nullable default) instead of `"false"`.

No behaviour change beyond the previous commit; this just makes the
schema check pass again.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant