Skip to content

Fix: Compare mode fails with 404 when target tag not yet created (#322)#324

Open
miroslavpojer wants to merge 14 commits into
masterfrom
bugfix/322-Compare-Mode-Fails-with-404-When-Target-Tag-Not-Yet-Created-2
Open

Fix: Compare mode fails with 404 when target tag not yet created (#322)#324
miroslavpojer wants to merge 14 commits into
masterfrom
bugfix/322-Compare-Mode-Fails-with-404-When-Target-Tag-Not-Yet-Created-2

Conversation

@miroslavpojer

@miroslavpojer miroslavpojer commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Problem

When from-tag-name is provided and either tag does not exist in the repository,
repo.compare() returns a GitHub 404 which is swallowed by _safe_call, leaving
comparison as None. The subsequent list(comparison.commits) call then raises
an AttributeError, producing a confusing crash instead of a clear action failure.

Solution

Add fail-fast tag-existence validation before the compare API is called:

  • DataMiner._validate_tag_exists(repo, tag_name) — calls repo.get_git_ref("tags/<name>")
    via the existing _safe_call wrapper; returns False if the ref is absent or the API errors.
  • DataMiner._validate_compare_mode_tags(repo) — iterates both from-tag-name and tag-name;
    logs a clear error and exits with code 1 on the first missing tag.
  • ActionInputs.validate_compare_mode_tag_names() — input-level guard (called from
    validate_inputs()) that exits early if either tag input is an empty string, before any
    API call is made.
  • COMPARE_MODE_TAG_MISSING_ERROR constant centralises the user-facing error string.
  • The if comparison is None guard after repo.compare() is retained to handle
    non-404 API failures (network errors, rate-limit exhaustion, etc.) that can occur
    even after both tags are confirmed to exist.

Tests

  • test_mine_data_compare_mode_exits_when_target_tag_missing — end-to-end: mine_data
    exits and repo.compare is never called when tag-name ref is absent.
  • test_mine_data_compare_mode_exits_when_from_tag_missing — same for from-tag-name.
  • test_validate_compare_mode_tag_names_* — three unit tests for the ActionInputs
    input-level guard (both set, empty tag-name, empty from-tag-name).

Docs / contract

  • action.yml — updated from-tag-name description to state both tags must exist.
  • README.md, docs/features/compare_mode.md, docs/motivation.md — added prerequisite
    note; removed an unimplemented "list of recent tags" promise.
  • CONTRIBUTING.md — added compare mode contract section for future contributors.

Release Notes

  • Compare mode now exits with a clear error when either tag is missing, instead of crashing with a 404
  • Both tag-name and from-tag-name are validated before any API call is made
  • Exit code 1 on missing tag; error names the missing tag and repository
  • Docs updated to reflect the tag-existence prerequisite

Closes #322

Update 2026-06-29

Correction to Solution section (as-implemented, ref f5e6830):

The Solution description above does not match the code that was merged. Actual behaviour:

  • DataMiner._validate_tag_exists(repo, tag_name) — calls repo.get_git_ref(f"tags/{tag}") directly in a try/except GithubException block (not via _safe_call). On a 404 or any other error it logs the specific failure and calls sys.exit(1). It does not return a boolean and does not use the _safe_call wrapper.
  • DataMiner._validate_compare_mode_tags(repo) — this helper was not added. Instead, _handle_compare_mode calls self._validate_tag_exists(repo, from_tag) and self._validate_tag_exists(repo, to_tag) directly, in sequence.
  • COMPARE_MODE_TAG_MISSING_ERROR constant — was not added; error strings are inlined in _validate_tag_exists.
  • ActionInputs.validate_compare_mode_tag_names() — implemented as described; validates non-empty strings and exits before any API call.

Summary by CodeRabbit

  • Documentation

    • Clarified compare mode requirements in the README, contributing guide, and feature documentation.
    • Documented the new fail-fast behavior when either required git tag is missing.
  • Bug Fixes

    • Compare mode now validates that both tag-name and from-tag-name exist before calling the compare API, and exits early with a clear, tag-specific error if either is absent.
    • Improved input handling for empty/whitespace from-tag-name in compare mode.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds compare-mode tag validation before repo.compare(). ActionInputs now distinguishes raw versus normalized from-tag-name input, DataMiner checks both tag refs through GitHub, and docs plus tests reflect the new required tags and exit-on-error behavior.

Changes

Compare-mode tag validation

Layer / File(s) Summary
ActionInputs input validation
release_notes_generator/action_inputs.py, tests/unit/release_notes_generator/test_action_inputs.py
Adds raw vs normalized from-tag-name detection, compare-mode validation for empty from-tag-name, and tests covering raw input states plus the validation exit path.
DataMiner compare flow
release_notes_generator/data/miner.py, tests/unit/release_notes_generator/data/test_miner.py
Adds tag-ref existence checks before repo.compare(), with GitHub exception handling and tests for missing tags, API errors, successful validation, and unexpected errors.
Docs and action metadata
action.yml, README.md, CONTRIBUTING.md, docs/features/compare_mode.md, docs/motivation.md
Updates configuration, contributor guidance, feature docs, and motivation text to require both tags and describe the compare-mode validation step.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • tmikula-dev
  • benedeki

🐇 I hopped through tags in a row,
Checked both refs before the show.
No 404s at the gate,
Just clean exits, crisp andేట్?
Compare mode now knows the way 🏷️

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR fails #322's requested fallback behavior and instead switches to fail-fast tag validation with no degraded-mode recovery. Implement the compare-mode fallback to the target tag/ref commit SHA, log a warning, continue in degraded mode, and exit only if both compare and fallback fail.
Docstring Coverage ⚠️ Warning Docstring coverage is 77.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main fix: compare mode failing with 404 when the target tag is missing.
Description check ✅ Passed It covers the problem, solution, tests, docs, release notes, and Closes #322, though it uses custom headings instead of the template.
Out of Scope Changes check ✅ Passed The docs, tests, and input validation changes all support the compare-mode tag-existence fix and do not add unrelated scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/322-Compare-Mode-Fails-with-404-When-Target-Tag-Not-Yet-Created-2

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds clearer, fail-fast handling for compare mode when required tags are missing, preventing a confusing AttributeError after a swallowed 404 from repo.compare().

Changes:

  • Add compare-mode tag existence checks (via repo.get_git_ref("tags/<name>")) before calling repo.compare().
  • Centralize the user-facing missing-tag error string and update docs/action metadata to state both tags must exist.
  • Add unit tests covering compare-mode missing-tag exits and the new ActionInputs guard.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/release_notes_generator/test_action_inputs.py Adds unit tests for validate_compare_mode_tag_names().
tests/unit/release_notes_generator/data/test_miner.py Adds end-to-end compare-mode exit tests and wires get_git_ref mocks.
release_notes_generator/utils/constants.py Introduces COMPARE_MODE_TAG_MISSING_ERROR message constant.
release_notes_generator/data/miner.py Adds compare-mode tag validation prior to repo.compare().
release_notes_generator/action_inputs.py Adds validate_compare_mode_tag_names() and calls it from validate_inputs().
README.md Documents compare-mode prerequisite that both tags exist.
docs/motivation.md Updates “Fail Safe” description to include compare-mode tag prerequisite.
docs/features/compare_mode.md Documents prerequisite and updates flow diagram accordingly.
CONTRIBUTING.md Adds “Compare Mode Contract” section for contributors.
action.yml Clarifies from-tag-name description and compare-mode activation/prerequisite.

Comment thread release_notes_generator/data/miner.py Outdated
Comment thread release_notes_generator/data/miner.py Outdated

@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: 3

🤖 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 `@release_notes_generator/action_inputs.py`:
- Around line 690-693: The compare-mode validation in ActionInputs is
incorrectly gated on the normalized from_tag_name value, which skips the new
fail-fast check for blank or whitespace-only input. Update the conditional
around validate_compare_mode_tag_names() to depend on the raw from-tag-name
being present/provided rather than from_tag_name.strip(), so explicitly invalid
compare-mode inputs still trigger the clear input error while keeping the
existing prior-validation guard.

In `@tests/unit/release_notes_generator/data/test_miner.py`:
- Line 593: The inline comment inside the `_make_compare_miner` helper in
`test_miner.py` violates the test-file comment rule; remove it or fold the
intent into the surrounding code so no non-section comments remain outside test
methods. Use the surrounding helper logic in `_make_compare_miner` and the
`tag_exists` simulation to make the behavior self-explanatory without comments,
keeping only `# --- section ---` headers in `test_*.py` files.

In `@tests/unit/release_notes_generator/test_action_inputs.py`:
- Around line 191-199: The success-path test for
ActionInputs.validate_compare_mode_tag_names only verifies that sys.exit is not
called, but it should also assert that no error is logged. Update the test to
patch release_notes_generator.action_inputs.logger.error alongside sys.exit,
then assert the logger.error mock is not called when both tag names are set.
This keeps the test aligned with the “no exit, no error” contract and covers the
logging behavior of ActionInputs.validate_compare_mode_tag_names.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f025c7dd-3428-4c27-830c-b324334e5126

📥 Commits

Reviewing files that changed from the base of the PR and between 4fe4a9a and 5afa957.

📒 Files selected for processing (10)
  • CONTRIBUTING.md
  • README.md
  • action.yml
  • docs/features/compare_mode.md
  • docs/motivation.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/data/miner.py
  • release_notes_generator/utils/constants.py
  • tests/unit/release_notes_generator/data/test_miner.py
  • tests/unit/release_notes_generator/test_action_inputs.py

Comment thread release_notes_generator/action_inputs.py Outdated
Comment thread tests/unit/release_notes_generator/data/test_miner.py Outdated
Comment thread tests/unit/release_notes_generator/test_action_inputs.py Outdated

@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

🤖 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 `@release_notes_generator/action_inputs.py`:
- Around line 178-183: The docstring in the input-checking helper should match
the actual whitespace-only handling: it currently says “non-blank value,” but
the implementation intentionally treats whitespace-only input as explicitly
provided. Update the summary in the helper used by validate_inputs() and the
from-tag-name input logic to describe “explicitly provided” raw input without
implying it is already valid.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a13fc02d-9b9e-451a-a454-f0349cb5fbe7

📥 Commits

Reviewing files that changed from the base of the PR and between 5afa957 and da97ff2.

📒 Files selected for processing (4)
  • release_notes_generator/action_inputs.py
  • release_notes_generator/utils/constants.py
  • tests/unit/release_notes_generator/data/test_miner.py
  • tests/unit/release_notes_generator/test_action_inputs.py
✅ Files skipped from review due to trivial changes (1)
  • tests/unit/release_notes_generator/data/test_miner.py

Comment thread release_notes_generator/action_inputs.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Comment thread release_notes_generator/action_inputs.py Outdated
Comment thread release_notes_generator/utils/constants.py Outdated
Comment thread README.md Outdated
Comment thread docs/features/compare_mode.md Outdated
Comment thread docs/motivation.md Outdated
Comment thread action.yml
Comment thread CONTRIBUTING.md
Comment thread tests/unit/release_notes_generator/data/test_miner.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Comment thread release_notes_generator/data/miner.py Outdated
Comment thread docs/motivation.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Comment thread release_notes_generator/data/miner.py
Comment thread release_notes_generator/data/miner.py
Comment thread release_notes_generator/action_inputs.py Outdated
@miroslavpojer miroslavpojer requested a review from Copilot June 29, 2026 10:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Comment thread release_notes_generator/data/miner.py

@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.

🧹 Nitpick comments (2)
release_notes_generator/data/miner.py (1)

166-193: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Avoid introducing another sys.exit() path in DataMiner.

Lines 184 and 192 make this leaf module terminate the process directly. Raising a typed error here would keep compare-mode failures composable and preserve exit-code translation at the entry point instead of burying everything behind SystemExit. As per coding guidelines: "Prefer raising exceptions in leaf modules and translating failures to action failure output / exit codes at the entry point".

🤖 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 `@release_notes_generator/data/miner.py` around lines 166 - 193, The
_validate_tag_exists method in DataMiner is terminating the process directly
with sys.exit(), which should be avoided in this leaf module. Replace both exit
paths in _validate_tag_exists with a typed exception that carries the validation
context, and let the entry point handle translating that failure into the
appropriate exit code. Keep the existing logging in place, but make sure
compare-mode callers can catch and compose the error rather than having
Repository tag validation end the process inside this method.

Source: Coding guidelines

tests/unit/release_notes_generator/data/test_miner.py (1)

829-843: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the missing second-tag error-path cases.

These tests only exercise non-404 and unexpected exceptions on the first get_git_ref() call. Because validation is sequential, a regression in the second-tag branch would still pass this suite. Please add the to_tag equivalents for those two scenarios. As per coding guidelines: "Cover all distinct combinations in tests; each test must state its scenario in the docstring".

Also applies to: 860-873

🤖 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 `@tests/unit/release_notes_generator/data/test_miner.py` around lines 829 -
843, The compare-mode from-tag error coverage is incomplete because it only
tests the first get_git_ref() validation path; add matching to_tag scenarios for
the non-404 GitHubException case and the unexpected exception case so a
regression in the second-tag branch is caught. Update the relevant tests in
test_miner.py around test_mine_data_compare_mode_from_tag_api_error_exits and
the neighboring exception-case test, using _make_compare_miner,
mock_repo.get_git_ref, and logger.error, and make each new test’s docstring
clearly state the specific scenario it covers.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@release_notes_generator/data/miner.py`:
- Around line 166-193: The _validate_tag_exists method in DataMiner is
terminating the process directly with sys.exit(), which should be avoided in
this leaf module. Replace both exit paths in _validate_tag_exists with a typed
exception that carries the validation context, and let the entry point handle
translating that failure into the appropriate exit code. Keep the existing
logging in place, but make sure compare-mode callers can catch and compose the
error rather than having Repository tag validation end the process inside this
method.

In `@tests/unit/release_notes_generator/data/test_miner.py`:
- Around line 829-843: The compare-mode from-tag error coverage is incomplete
because it only tests the first get_git_ref() validation path; add matching
to_tag scenarios for the non-404 GitHubException case and the unexpected
exception case so a regression in the second-tag branch is caught. Update the
relevant tests in test_miner.py around
test_mine_data_compare_mode_from_tag_api_error_exits and the neighboring
exception-case test, using _make_compare_miner, mock_repo.get_git_ref, and
logger.error, and make each new test’s docstring clearly state the specific
scenario it covers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2468c00b-14a2-4b58-a90b-b8372840483a

📥 Commits

Reviewing files that changed from the base of the PR and between da97ff2 and f5e6830.

📒 Files selected for processing (8)
  • CONTRIBUTING.md
  • README.md
  • docs/features/compare_mode.md
  • docs/motivation.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/data/SPEC.md
  • release_notes_generator/data/miner.py
  • tests/unit/release_notes_generator/data/test_miner.py
✅ Files skipped from review due to trivial changes (3)
  • docs/motivation.md
  • README.md
  • docs/features/compare_mode.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • CONTRIBUTING.md
  • release_notes_generator/action_inputs.py

@tmikula-dev tmikula-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please see comments.

Comment thread release_notes_generator/data/miner.py Outdated
Comment on lines +107 to +111
ActionInputs.get_from_tag_name(),
ActionInputs.get_tag_name(),
)
comparison = self._safe_call(repo.compare)(ActionInputs.get_from_tag_name(), ActionInputs.get_tag_name())
from_tag = ActionInputs.get_from_tag_name()
to_tag = ActionInputs.get_tag_name()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You are running the same method twice under each other. Please optimize it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code improved.

Comment on lines +196 to +197
tag = ActionInputs.get_tag_name()
if not tag.strip():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I love to put := everywhere is possible. Not needed, but suggestion 😄 :

Suggested change
tag = ActionInputs.get_tag_name()
if not tag.strip():
if not tag := ActionInputs.get_tag_name().strip():

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

propose used.

Comment on lines +199 to +203
sys.exit(1)
from_tag = ActionInputs.get_from_tag_name()
if not from_tag.strip():
logger.error("'from-tag-name' must not be empty when running in compare mode. Ending!")
sys.exit(1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am really confused here, because you created extra method, that is is_from_tag_name_provided and when the result of this method is True, then you check it here once again. but if ActionInputs.get_from_tag_name(). For me it is the same logic used twice and this whole method is just checking if tag is provided. But if we are in the compare mode, we miss the info that "Existing tag has to be created before RN Generator is started"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

addressed.

Comment thread CONTRIBUTING.md
## Compare Mode Contract

When contributing changes that touch compare mode (the `from-tag-name` path):
- Both `tag-name` and `from-tag-name` must exist as git tags before the compare API is called.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the first time, there is mentioned this crucial info. Should be in the error message, when the run failes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

addressed.

Comment thread README.md

You can integrate this Action with your release process.

### Example — Manual Release Dispatch

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe it would be great if this example would get updated and clearly add, that tag creation step has to be before the generate release notes one.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

addressed.

Comment thread README.md
| `GITHUB_TOKEN` | GitHub token for authentication | Yes | - |
| `tag-name` | Target tag for the release | Yes | - |
| `chapters` | YAML multi-line list mapping titles to labels (supports `label` or `labels`) | No | - |
| `verbose` | Enable detailed logging | No | false |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Missing the from-tag-name input a little bit. Understand, that it is in the configuration-reference file probably, but the input is mentioned right under, so it would be nice to have it in this input table as well.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

addressed.

Comment on lines +701 to +704
# Compare mode: validate both tag names are non-empty strings.
# Only runs when all prior validations passed to avoid cascading errors.
if not errors and ActionInputs.is_from_tag_name_provided():
ActionInputs.validate_compare_mode_tag_names()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This whole block could be added after errors section at line 707, since it is maybe better to write errors first (wrong config) and then look at the missing inputs. This if statement will not have to check if not errors (for me a sign, that it should be under). What do you think?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed usage of this method.

return value.strip() != ""

@staticmethod
def is_from_tag_name_provided() -> bool:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There already exists a method called: is_from_tag_name_defined. Can you please look at it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

addressed.

@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

🤖 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 `@tests/unit/release_notes_generator/test_action_inputs.py`:
- Around line 220-229: The test for ActionInputs.validate_inputs is too
permissive because it only patches ActionInputs.is_from_tag_name_defined to
return True, so it won’t catch a regression where the helper is called without
use_raw=True. Update the test to assert the patched
ActionInputs.is_from_tag_name_defined helper was called with use_raw=True during
validate_inputs(), alongside the existing logger.error and sys.exit checks, so
the raw-mode contract is explicitly enforced.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17835c68-b0f3-4ad3-854a-a65f12c6fb22

📥 Commits

Reviewing files that changed from the base of the PR and between f5e6830 and 982128f.

📒 Files selected for processing (4)
  • README.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/data/miner.py
  • tests/unit/release_notes_generator/test_action_inputs.py
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • release_notes_generator/data/miner.py

Comment on lines +220 to +229
mocker.patch(
"release_notes_generator.action_inputs.ActionInputs.is_from_tag_name_defined",
return_value=True,
)
try:
mock_error = mocker.patch("release_notes_generator.action_inputs.logger.error")
mock_exit = mocker.patch("sys.exit")
ActionInputs.validate_inputs()
assert any("from-tag-name" in str(c) for c in mock_error.call_args_list)
mock_exit.assert_called_once_with(1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the raw-mode call contract.

This test still passes if validate_inputs() regresses to calling is_from_tag_name_defined() without use_raw=True, because the patch returns True for any invocation. Please assert the patched helper was called with use_raw=True so the new compare-mode behavior is actually locked in.

Suggested fix
-    mocker.patch(
+    mock_is_from_tag_name_defined = mocker.patch(
         "release_notes_generator.action_inputs.ActionInputs.is_from_tag_name_defined",
         return_value=True,
     )
@@
         mock_error = mocker.patch("release_notes_generator.action_inputs.logger.error")
         mock_exit = mocker.patch("sys.exit")
         ActionInputs.validate_inputs()
+        mock_is_from_tag_name_defined.assert_called_once_with(use_raw=True)
         assert any("from-tag-name" in str(c) for c in mock_error.call_args_list)
         mock_exit.assert_called_once_with(1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mocker.patch(
"release_notes_generator.action_inputs.ActionInputs.is_from_tag_name_defined",
return_value=True,
)
try:
mock_error = mocker.patch("release_notes_generator.action_inputs.logger.error")
mock_exit = mocker.patch("sys.exit")
ActionInputs.validate_inputs()
assert any("from-tag-name" in str(c) for c in mock_error.call_args_list)
mock_exit.assert_called_once_with(1)
mock_is_from_tag_name_defined = mocker.patch(
"release_notes_generator.action_inputs.ActionInputs.is_from_tag_name_defined",
return_value=True,
)
try:
mock_error = mocker.patch("release_notes_generator.action_inputs.logger.error")
mock_exit = mocker.patch("sys.exit")
ActionInputs.validate_inputs()
mock_is_from_tag_name_defined.assert_called_once_with(use_raw=True)
assert any("from-tag-name" in str(c) for c in mock_error.call_args_list)
mock_exit.assert_called_once_with(1)
🤖 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 `@tests/unit/release_notes_generator/test_action_inputs.py` around lines 220 -
229, The test for ActionInputs.validate_inputs is too permissive because it only
patches ActionInputs.is_from_tag_name_defined to return True, so it won’t catch
a regression where the helper is called without use_raw=True. Update the test to
assert the patched ActionInputs.is_from_tag_name_defined helper was called with
use_raw=True during validate_inputs(), alongside the existing logger.error and
sys.exit checks, so the raw-mode contract is explicitly enforced.

@tmikula-dev tmikula-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please see comments.

Comment thread CONTRIBUTING.md

## Compare Mode Contract

When contributing changes that touch compare mode (the `from-tag-name` path):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
When contributing changes that touch compare mode (the `from-tag-name` path):
When contributing changes that touch compare mode (once `from-tag-name` input is provided):

Comment thread CONTRIBUTING.md
Comment on lines +32 to +34
- Input-level check: `ActionInputs.validate_compare_mode_tag_names()` (called from `validate_inputs()`) exits with code 1 if either input string is empty.
- Tag-existence check: `DataMiner._handle_compare_mode()` calls `repo.get_git_ref("tags/<tag>")` for both tags and exits with code 1 naming the absent tag if either lookup fails.
- Any change to this validation logic must update `docs/features/compare_mode.md` and the tests in `tests/unit/release_notes_generator/data/test_miner.py`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is please in the CONTRIBUTING file described, how the tags are checked? Other topics in this file are named as Branch Naming or Proposing New Features. This described section looks here odd to me.

return value.strip() != ""
if use_raw:
return get_action_input(FROM_TAG_NAME, default="") != ""
return ActionInputs.get_from_tag_name().strip() != ""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you please explain to me the reason of having this use_raw switch? If this whole workaround is for user not to be able to add a whitespace only as the from-tag input, I feel like we do to much for a bad config.

From input is set as a whitespace -> comparison happens, the tag called whitespace is not exisiting -> error. This is too confusing for not almost existing issue.

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.

bug: Compare Mode Fails with 404 When Target Tag Not Yet Created

3 participants