Adds release script to do the minor or patch release - #301
Conversation
📝 WalkthroughWalkthroughAdds a Bash tool for minor and patch releases plus a tag-triggered GitHub Actions workflow that validates tags, invokes the tool, and reports draft release details and image tags. ChangesRelease automation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GitHub
participant ReleaseWorkflow
participant ReleaseScript
participant Git
participant GitHubCLI
GitHub->>ReleaseWorkflow: deliver version tag push
ReleaseWorkflow->>ReleaseScript: invoke minor or patch release
ReleaseScript->>Git: inspect tags, branches, and commits
ReleaseScript->>GitHubCLI: create draft release
ReleaseWorkflow->>GitHub: publish release summary and image tags
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
hack/release.sh (1)
352-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse an array for the optional flag.
$notes_flagrelies on unquoted word splitting, which also breaks therun_cmdfix above onceevalis removed.♻️ Proposed refactor
- local notes_flag="" + local notes_args=() if [[ -n "$prev_tag" ]]; then - notes_flag="--notes-start-tag ${prev_tag}" + notes_args=(--notes-start-tag "$prev_tag") fi run_cmd gh release create "$next_version" \ --repo "$REPO" \ --generate-notes \ - $notes_flag + "${notes_args[@]}"🤖 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 `@hack/release.sh` around lines 352 - 359, Update the release creation flow around notes_flag to use an array for the optional --notes-start-tag argument, append its flag and value only when prev_tag is set, and pass the array safely to run_cmd without unquoted expansion. Preserve --generate-notes and the existing behavior when no previous tag exists.Source: Linters/SAST tools
🤖 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 `@hack/release.sh`:
- Around line 220-227: Validate VERSION_OVERRIDE before deriving next_minor_num
in the version-override flow. Require the value to match the expected v0.<minor>
format, and exit with a clear validation error for invalid versions; only then
compute release_branch, prev_minor_num, prev_release_branch, and prev_tag.
- Around line 512-521: Update the patch argument validation in the patch branch
of the release command so a missing value or a value beginning with “-” is
rejected before assigning PATCH_MINOR and shifting arguments. Preserve the
existing usage error and prevent options such as --dry-run from being consumed
as the minor version.
- Around line 27-34: Update run_cmd to invoke the received arguments directly
with "$@" instead of re-parsing them through eval. Preserve the existing dry-run
branch and logging behavior while ensuring arguments containing spaces, quotes,
or shell metacharacters remain data rather than executable shell code.
- Around line 156-175: Bound the polling loop around gh run list with an attempt
count or consecutive-error limit, treating unknown results as failures and
exiting once the limit is reached. Ensure the exhaustion path terminates the
script through the existing manual-release instructions, while preserving normal
polling until status becomes completed.
- Around line 91-111: Update get_latest_patch_for_minor and get_max_patch_number
to avoid grep -P by using POSIX-compatible parsing, or add an early GNU grep
dependency check that fails clearly before these helpers run. Preserve the
existing version filtering and sorting behavior.
---
Nitpick comments:
In `@hack/release.sh`:
- Around line 352-359: Update the release creation flow around notes_flag to use
an array for the optional --notes-start-tag argument, append its flag and value
only when prev_tag is set, and pass the array safely to run_cmd without unquoted
expansion. Preserve --generate-notes and the existing behavior when no previous
tag exists.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| run_cmd() { | ||
| if $DRY_RUN; then | ||
| dry_run "$*" | ||
| else | ||
| info "Running: $*" | ||
| eval "$@" | ||
| fi | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Drop eval in run_cmd. eval "$@" re-parses already-split arguments, so any value containing spaces, quotes, or shell metacharacters (e.g. --version 'v0.1.0 && …', which is never validated) is executed as code. Invoking "$@" directly preserves quoting and removes the injection path.
🔒 Proposed fix
run_cmd() {
if $DRY_RUN; then
dry_run "$*"
else
- info "Running: $*"
- eval "$@"
+ info "Running: $*"
+ "$@"
fi
}📝 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.
| run_cmd() { | |
| if $DRY_RUN; then | |
| dry_run "$*" | |
| else | |
| info "Running: $*" | |
| eval "$@" | |
| fi | |
| } | |
| run_cmd() { | |
| if $DRY_RUN; then | |
| dry_run "$*" | |
| else | |
| info "Running: $*" | |
| "$@" | |
| fi | |
| } |
🧰 Tools
🪛 ast-grep (0.44.1)
[error] 31-31: eval is invoked on a variable, parameter expansion, or command-substitution result, which re-parses the value as shell code. If any part of that value is attacker-controlled (arguments, environment, file contents, network output), it allows arbitrary command execution. Do not eval dynamic data: invoke the command directly with proper quoting (e.g. "$cmd" "$arg"), use arrays for argument lists (cmd=(prog --flag "$value"); "${cmd[@]}"), or restrict input to a validated allowlist before running it.
Context: eval "$@"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(eval-on-variable-bash)
🪛 Shellcheck (0.11.0)
[warning] 32-32: eval negates the benefit of arrays. Drop eval to preserve whitespace/symbols (or eval as string).
(SC2294)
🤖 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 `@hack/release.sh` around lines 27 - 34, Update run_cmd to invoke the received
arguments directly with "$@" instead of re-parsing them through eval. Preserve
the existing dry-run branch and logging behavior while ensuring arguments
containing spaces, quotes, or shell metacharacters remain data rather than
executable shell code.
Source: Linters/SAST tools
| get_all_tags() { | ||
| git tag -l 'v*' | sort -V | ||
| } | ||
|
|
||
| get_latest_minor() { | ||
| get_all_tags | grep -oP 'v\K[0-9]+\.[0-9]+' | sort -t. -k1,1n -k2,2n | tail -1 | ||
| } | ||
|
|
||
| get_latest_patch_for_minor() { | ||
| local minor="$1" | ||
| get_all_tags | grep -P "^v${minor}\.[0-9]+$" | sort -V | tail -1 | ||
| } | ||
|
|
||
| get_max_patch_number() { | ||
| local minor="$1" | ||
| get_all_tags | grep -P "^v${minor}\.[0-9]+$" | grep -oP '\.[0-9]+$' | tr -d '.' | sort -n | tail -1 | ||
| } | ||
|
|
||
| get_latest_tag() { | ||
| get_all_tags | tail -1 | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check whether the repo documents macOS/GNU tooling requirements for hack scripts
fd -t f -e md . -x rg -n --heading 'gnu-|coreutils|grep -P|GNU grep' {} \; | head -50
rg -nP 'grep -[oP]{1,2}P?' --glob 'hack/**' -C1Repository: redhat-data-and-ai/unstructured-data-controller
Length of output: 185
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the release script around the cited lines
if [ -f hack/release.sh ]; then
wc -l hack/release.sh
sed -n '1,160p' hack/release.sh | cat -n
fi
# Search for release tooling docs or preflight checks mentioning GNU grep/coreutils/macOS
rg -n "release\.sh|GNU grep|coreutils|grep -P|macOS|BSD grep|brew install|greadlink|gsed|ggrep" -S . --glob '!**/.git/**'Repository: redhat-data-and-ai/unstructured-data-controller
Length of output: 12374
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the release flow around the version helpers' callers
sed -n '360,450p' hack/release.sh | cat -n
# Find docs or scripts that mention running the release helper locally
rg -n "hack/release\.sh|release helper|release script|minor release|patch release|v0\.[0-9]+\.[0-9]+" -S . --glob '!**/.git/**' --glob '!vendor/**'Repository: redhat-data-and-ai/unstructured-data-controller
Length of output: 30435
Replace grep -P with portable parsing or add a GNU grep check
These helpers fail on BSD grep (macOS), so release detection breaks outside GNU environments. Either switch to POSIX-compatible parsing or fail fast with a grep dependency check.
🤖 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 `@hack/release.sh` around lines 91 - 111, Update get_latest_patch_for_minor and
get_max_patch_number to avoid grep -P by using POSIX-compatible parsing, or add
an early GNU grep dependency check that fails clearly before these helpers run.
Preserve the existing version filtering and sorting behavior.
| while true; do | ||
| local run_data | ||
| run_data=$(gh run list \ | ||
| --repo "$REPO" \ | ||
| --workflow "test-e2e.yml" \ | ||
| --branch "$version" \ | ||
| --limit 1 \ | ||
| --json status,conclusion \ | ||
| --jq '.[0] | "\(.status) \(.conclusion)"' 2>/dev/null || echo "unknown unknown") | ||
|
|
||
| status=$(echo "$run_data" | awk '{print $1}') | ||
| conclusion=$(echo "$run_data" | awk '{print $2}') | ||
|
|
||
| if [[ "$status" == "completed" ]]; then | ||
| break | ||
| fi | ||
|
|
||
| echo -ne "\r ⏳ CI status: ${status}... (polling every 30s, Ctrl+C to stop)" | ||
| sleep 30 | ||
| done |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Polling loop can spin forever. When gh run list fails (auth expiry, rate limit, network), the fallback is "unknown unknown", so status never becomes completed and the loop polls indefinitely with no timeout. Add a bounded attempt count / consecutive-error limit so the script exits with the manual-release instructions instead of hanging.
⏱️ Proposed fix
local status=""
local conclusion=""
+ local attempts=0
+ local max_attempts=120 # ~60 minutes at 30s
while true; do
local run_data
run_data=$(gh run list \
@@
status=$(echo "$run_data" | awk '{print $1}')
conclusion=$(echo "$run_data" | awk '{print $2}')
if [[ "$status" == "completed" ]]; then
break
fi
+ if (( ++attempts >= max_attempts )); then
+ echo ""
+ warn "Timed out waiting for CI. Tag ${version} is pushed; create the release manually:"
+ echo " gh release create ${version} --repo ${REPO} --generate-notes"
+ exit 1
+ fi
+
echo -ne "\r ⏳ CI status: ${status}... (polling every 30s, Ctrl+C to stop)"
sleep 30
done📝 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.
| while true; do | |
| local run_data | |
| run_data=$(gh run list \ | |
| --repo "$REPO" \ | |
| --workflow "test-e2e.yml" \ | |
| --branch "$version" \ | |
| --limit 1 \ | |
| --json status,conclusion \ | |
| --jq '.[0] | "\(.status) \(.conclusion)"' 2>/dev/null || echo "unknown unknown") | |
| status=$(echo "$run_data" | awk '{print $1}') | |
| conclusion=$(echo "$run_data" | awk '{print $2}') | |
| if [[ "$status" == "completed" ]]; then | |
| break | |
| fi | |
| echo -ne "\r ⏳ CI status: ${status}... (polling every 30s, Ctrl+C to stop)" | |
| sleep 30 | |
| done | |
| local status="" | |
| local conclusion="" | |
| local attempts=0 | |
| local max_attempts=120 # ~60 minutes at 30s | |
| while true; do | |
| local run_data | |
| run_data=$(gh run list \ | |
| --repo "$REPO" \ | |
| --workflow "test-e2e.yml" \ | |
| --branch "$version" \ | |
| --limit 1 \ | |
| --json status,conclusion \ | |
| --jq '.[0] | "\(.status) \(.conclusion)"' 2>/dev/null || echo "unknown unknown") | |
| status=$(echo "$run_data" | awk '{print $1}') | |
| conclusion=$(echo "$run_data" | awk '{print $2}') | |
| if [[ "$status" == "completed" ]]; then | |
| break | |
| fi | |
| if (( ++attempts >= max_attempts )); then | |
| echo "" | |
| warn "Timed out waiting for CI. Tag ${version} is pushed; create the release manually:" | |
| echo " gh release create ${version} --repo ${REPO} --generate-notes" | |
| exit 1 | |
| fi | |
| echo -ne "\r ⏳ CI status: ${status}... (polling every 30s, Ctrl+C to stop)" | |
| sleep 30 | |
| done |
🤖 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 `@hack/release.sh` around lines 156 - 175, Bound the polling loop around gh run
list with an attempt count or consecutive-error limit, treating unknown results
as failures and exiting once the limit is reached. Ensure the exhaustion path
terminates the script through the existing manual-release instructions, while
preserving normal polling until status becomes completed.
| if [[ -n "$VERSION_OVERRIDE" ]]; then | ||
| next_version="${VERSION_OVERRIDE}" | ||
| next_minor_num=$(echo "$next_version" | grep -oP 'v0\.\K[0-9]+') | ||
| release_branch="release-v0.${next_minor_num}.x" | ||
|
|
||
| local prev_minor_num=$((next_minor_num - 1)) | ||
| prev_release_branch="release-v0.${prev_minor_num}.x" | ||
| prev_tag=$(get_latest_patch_for_minor "0.${prev_minor_num}") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate --version before deriving the minor number. grep -oP 'v0\.\K[0-9]+' returns empty for anything not matching v0.<n> (e.g. v1.0.0, 0.11.0, a typo). With set -e and an empty next_minor_num, $((next_minor_num - 1)) aborts with an arithmetic error, and release_branch becomes release-v0..x in other paths.
🐛 Proposed fix
if [[ -n "$VERSION_OVERRIDE" ]]; then
+ if [[ ! "$VERSION_OVERRIDE" =~ ^v0\.[0-9]+\.0$ ]]; then
+ error "Invalid --version for a minor release: ${VERSION_OVERRIDE} (expected v0.X.0)"
+ exit 1
+ fi
next_version="${VERSION_OVERRIDE}"
next_minor_num=$(echo "$next_version" | grep -oP 'v0\.\K[0-9]+')📝 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.
| if [[ -n "$VERSION_OVERRIDE" ]]; then | |
| next_version="${VERSION_OVERRIDE}" | |
| next_minor_num=$(echo "$next_version" | grep -oP 'v0\.\K[0-9]+') | |
| release_branch="release-v0.${next_minor_num}.x" | |
| local prev_minor_num=$((next_minor_num - 1)) | |
| prev_release_branch="release-v0.${prev_minor_num}.x" | |
| prev_tag=$(get_latest_patch_for_minor "0.${prev_minor_num}") | |
| if [[ -n "$VERSION_OVERRIDE" ]]; then | |
| if [[ ! "$VERSION_OVERRIDE" =~ ^v0\.[0-9]+\.0$ ]]; then | |
| error "Invalid --version for a minor release: ${VERSION_OVERRIDE} (expected v0.X.0)" | |
| exit 1 | |
| fi | |
| next_version="${VERSION_OVERRIDE}" | |
| next_minor_num=$(echo "$next_version" | grep -oP 'v0\.\K[0-9]+') | |
| release_branch="release-v0.${next_minor_num}.x" | |
| local prev_minor_num=$((next_minor_num - 1)) | |
| prev_release_branch="release-v0.${prev_minor_num}.x" | |
| prev_tag=$(get_latest_patch_for_minor "0.${prev_minor_num}") |
🤖 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 `@hack/release.sh` around lines 220 - 227, Validate VERSION_OVERRIDE before
deriving next_minor_num in the version-override flow. Require the value to match
the expected v0.<minor> format, and exit with a clear validation error for
invalid versions; only then compute release_branch, prev_minor_num,
prev_release_branch, and prev_tag.
| patch) | ||
| COMMAND="patch" | ||
| if [[ -z "${2:-}" ]]; then | ||
| error "patch requires a minor version argument (e.g., v0.10)" | ||
| echo " Usage: $(basename "$0") patch v0.X [OPTIONS]" | ||
| exit 1 | ||
| fi | ||
| PATCH_MINOR="$2" | ||
| shift 2 | ||
| ;; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
patch blindly consumes the next argument. release.sh patch --dry-run sets PATCH_MINOR=--dry-run and drops the flag, then fails later with a confusing "Invalid minor version format". Reject values starting with -.
🐛 Proposed fix
patch)
COMMAND="patch"
- if [[ -z "${2:-}" ]]; then
+ if [[ -z "${2:-}" || "${2}" == -* ]]; then
error "patch requires a minor version argument (e.g., v0.10)"📝 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.
| patch) | |
| COMMAND="patch" | |
| if [[ -z "${2:-}" ]]; then | |
| error "patch requires a minor version argument (e.g., v0.10)" | |
| echo " Usage: $(basename "$0") patch v0.X [OPTIONS]" | |
| exit 1 | |
| fi | |
| PATCH_MINOR="$2" | |
| shift 2 | |
| ;; | |
| patch) | |
| COMMAND="patch" | |
| if [[ -z "${2:-}" || "${2}" == -* ]]; then | |
| error "patch requires a minor version argument (e.g., v0.10)" | |
| echo " Usage: $(basename "$0") patch v0.X [OPTIONS]" | |
| exit 1 | |
| fi | |
| PATCH_MINOR="$2" | |
| shift 2 | |
| ;; |
🤖 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 `@hack/release.sh` around lines 512 - 521, Update the patch argument validation
in the patch branch of the release command so a missing value or a value
beginning with “-” is rejected before assigning PATCH_MINOR and shifting
arguments. Preserve the existing usage error and prevent options such as
--dry-run from being consumed as the minor version.
38e36dd to
cccd60b
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (4)
hack/release.sh (4)
27-34: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick winStill unsafe:
eval "$@"allows shell injection.Re-parsing already-split arguments via
evalexecutes any embedded shell metacharacters as code. This was flagged in a prior review and remains unresolved. Invoke"$@"directly to preserve quoting.🔒 Proposed fix
run_cmd() { if $DRY_RUN; then dry_run "$*" else info "Running: $*" - eval "$@" + "$@" fi }Note: once this is fixed, sites that build dynamic option strings for
run_cmd(e.g.notes_flagaround lines 250-258) should switch to arrays instead of relying on unquoted word-splitting, so both quoting and correctness are preserved together.🤖 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 `@hack/release.sh` around lines 27 - 34, Replace eval "$@" in run_cmd with direct "$@" invocation so arguments retain their original quoting and cannot execute shell metacharacters. Also update callers such as notes_flag to construct and pass command options as arrays rather than dynamic strings or unquoted word-splitting.Source: Linters/SAST tools
94-106: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winStill relies on GNU-only
grep -P.
get_latest_minor,get_latest_patch_for_minor, andget_max_patch_numberall usegrep -oP/grep -P, which fails on BSD grep (macOS default). This was flagged previously and remains unresolved. Either use POSIX-compatible parsing or add an explicit GNU-grep dependency check inpreflight.🤖 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 `@hack/release.sh` around lines 94 - 106, Replace the GNU-only grep usage in get_latest_minor, get_latest_patch_for_minor, and get_max_patch_number with POSIX-compatible shell parsing and filtering so these helpers work with BSD grep; alternatively, add and invoke an explicit GNU grep dependency check during preflight. Preserve each helper’s existing tag-selection and patch-number results.Source: Linters/SAST tools
127-134: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
--versionoverride still unvalidated before derivingnext_minor_num.If
VERSION_OVERRIDEdoesn't matchv0.<n>.0(typo,v1.0.0, etc.),grep -oP 'v0\.\K[0-9]+'returns empty and$((next_minor_num - 1))at line 132 aborts with an arithmetic error underset -e. Still unresolved from a prior review.🐛 Proposed fix
if [[ -n "$VERSION_OVERRIDE" ]]; then + if [[ ! "$VERSION_OVERRIDE" =~ ^v0\.[0-9]+\.0$ ]]; then + error "Invalid --version for a minor release: ${VERSION_OVERRIDE} (expected v0.X.0)" + exit 1 + fi next_version="${VERSION_OVERRIDE}" next_minor_num=$(echo "$next_version" | grep -oP 'v0\.\K[0-9]+')🤖 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 `@hack/release.sh` around lines 127 - 134, Validate VERSION_OVERRIDE in the override branch before deriving next_minor_num, requiring the expected v0.<minor>.0 format and rejecting invalid values with a clear error. Keep the existing release_branch, previous-minor, and previous-tag calculations unchanged for valid overrides, and ensure invalid input exits before arithmetic evaluation.
403-412: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
patchstill consumes the next token unconditionally as the minor argument.
release.sh patch --dry-runsetsPATCH_MINOR=--dry-runand drops the flag, later failing with a confusing "Invalid minor version format" instead of a clear usage error. Flagged previously, still present.🐛 Proposed fix
patch) COMMAND="patch" - if [[ -z "${2:-}" ]]; then + if [[ -z "${2:-}" || "${2}" == -* ]]; then error "patch requires a minor version argument (e.g., v0.10)"🤖 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 `@hack/release.sh` around lines 403 - 412, Update the patch command argument handling so the required minor-version argument is rejected when the next token is an option such as --dry-run, rather than consumed as PATCH_MINOR. Validate that $2 is present and represents the expected minor-version format before shift 2; otherwise emit the existing usage error and exit, while preserving normal option parsing after a valid version.
🧹 Nitpick comments (1)
hack/release.sh (1)
417-432: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSame "swallows next flag" pattern also affects
--upstream-remoteand--version.Neither checks whether the next token starts with
-. E.g.release.sh minor --upstream-remote --dry-runwould setUPSTREAM_REMOTE="--dry-run"and silently drop--dry-run, since only emptiness is checked. Same class of bug as thepatchargument issue above; worth applying the same guard here too.🤖 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 `@hack/release.sh` around lines 417 - 432, The option parsing cases for --upstream-remote and --version accept another flag as their value and then consume it. Update both validation branches to reject values that are empty or begin with “-”, while preserving their existing specific error messages and shift behavior for valid values.
🤖 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 @.github/workflows/release.yml:
- Around line 21-27: Update the release workflow steps that use github.ref_name,
steps.info.outputs.type, steps.info.outputs.minor, or github.repository in run
scripts, including “Validate tag format,” “Determine release type,” and
“Summary,” to pass each value through the step’s env mapping and reference the
resulting quoted environment variables in shell commands. Ensure no GitHub
context expressions are interpolated directly into script text, while preserving
the existing validation and release-summary behavior.
- Around line 34-46: Fix the patch-release invocation of hack/release.sh so
steps.info.outputs.minor, which already contains the major and minor components
such as 0.12, is prefixed with v only once. Update the patch path to pass v${{
steps.info.outputs.minor }} and preserve the existing minor-release behavior.
In `@hack/release.sh`:
- Around line 36-55: Update usage() to accept an exit-status argument and exit
with that value instead of unconditionally exiting 0. Keep the help path
invoking usage with status 0, and update the unknown-argument path near the
argument parser to invoke usage with a non-zero status after reporting the
error.
- Around line 158-176: Validate an existing release_branch alongside the
existing tag validation: when branch_exists is true, resolve the branch commit
and compare it with target_sha, reporting the branch and expected commit details
and exiting on mismatch. Keep the current behavior for a matching branch and for
branches that do not yet exist, using the existing release_branch, target_sha,
and target_short symbols.
---
Duplicate comments:
In `@hack/release.sh`:
- Around line 27-34: Replace eval "$@" in run_cmd with direct "$@" invocation so
arguments retain their original quoting and cannot execute shell metacharacters.
Also update callers such as notes_flag to construct and pass command options as
arrays rather than dynamic strings or unquoted word-splitting.
- Around line 94-106: Replace the GNU-only grep usage in get_latest_minor,
get_latest_patch_for_minor, and get_max_patch_number with POSIX-compatible shell
parsing and filtering so these helpers work with BSD grep; alternatively, add
and invoke an explicit GNU grep dependency check during preflight. Preserve each
helper’s existing tag-selection and patch-number results.
- Around line 127-134: Validate VERSION_OVERRIDE in the override branch before
deriving next_minor_num, requiring the expected v0.<minor>.0 format and
rejecting invalid values with a clear error. Keep the existing release_branch,
previous-minor, and previous-tag calculations unchanged for valid overrides, and
ensure invalid input exits before arithmetic evaluation.
- Around line 403-412: Update the patch command argument handling so the
required minor-version argument is rejected when the next token is an option
such as --dry-run, rather than consumed as PATCH_MINOR. Validate that $2 is
present and represents the expected minor-version format before shift 2;
otherwise emit the existing usage error and exit, while preserving normal option
parsing after a valid version.
---
Nitpick comments:
In `@hack/release.sh`:
- Around line 417-432: The option parsing cases for --upstream-remote and
--version accept another flag as their value and then consume it. Update both
validation branches to reject values that are empty or begin with “-”, while
preserving their existing specific error messages and shift behavior for valid
values.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fafa7621-3301-48ef-8ac9-628d3c37e75e
📒 Files selected for processing (2)
.github/workflows/release.ymlhack/release.sh
| - name: Validate tag format | ||
| run: | | ||
| TAG="${{ github.ref_name }}" | ||
| if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| echo "::error::Invalid tag format: ${TAG}. Expected vMAJOR.MINOR.PATCH (e.g., v0.12.0)" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Unsanitized ${{ github.ref_name }}/context values interpolated directly into run: scripts (template injection).
Lines 23, 37, 54, 66, 71-73 splice GitHub context expressions (github.ref_name, steps.info.outputs.*, github.repository) directly into shell script text rather than passing them through env:. Notably, the very step meant to validate the tag (line 21-27) itself performs this interpolation before any validation occurs, so a maliciously-crafted tag name (by anyone with tag-push access) could inject shell syntax before the format check ever runs. The standard mitigation is to pass these values via env: and reference them as "$VAR" inside the script, which makes the value pure data instead of script text.
🔒 Proposed fix (pattern to apply at each flagged step)
- name: Validate tag format
+ env:
+ TAG: ${{ github.ref_name }}
run: |
- TAG="${{ github.ref_name }}"
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Invalid tag format: ${TAG}. Expected vMAJOR.MINOR.PATCH (e.g., v0.12.0)"
exit 1
fiApply the same env:-passing pattern to the "Determine release type" and "Summary" steps for github.ref_name, steps.info.outputs.type, and steps.info.outputs.minor.
📝 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.
| - name: Validate tag format | |
| run: | | |
| TAG="${{ github.ref_name }}" | |
| if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "::error::Invalid tag format: ${TAG}. Expected vMAJOR.MINOR.PATCH (e.g., v0.12.0)" | |
| exit 1 | |
| fi | |
| - name: Validate tag format | |
| env: | |
| TAG: ${{ github.ref_name }} | |
| run: | | |
| if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "::error::Invalid tag format: ${TAG}. Expected vMAJOR.MINOR.PATCH (e.g., v0.12.0)" | |
| exit 1 | |
| fi |
🧰 Tools
🪛 zizmor (1.26.1)
[error] 23-23: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 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/release.yml around lines 21 - 27, Update the release
workflow steps that use github.ref_name, steps.info.outputs.type,
steps.info.outputs.minor, or github.repository in run scripts, including
“Validate tag format,” “Determine release type,” and “Summary,” to pass each
value through the step’s env mapping and reference the resulting quoted
environment variables in shell commands. Ensure no GitHub context expressions
are interpolated directly into script text, while preserving the existing
validation and release-summary behavior.
Source: Linters/SAST tools
| usage() { | ||
| cat <<EOF | ||
| Usage: | ||
| $(basename "$0") minor [OPTIONS] Create a new minor release (v0.X.0) from origin/main | ||
| $(basename "$0") patch v0.X [OPTIONS] Create a patch release (v0.X.Y) on an existing release branch | ||
|
|
||
| Options: | ||
| --dry-run Show what would happen without making changes | ||
| --upstream-remote NAME Override the remote name (default: origin) | ||
| --version VERSION Override the auto-detected version (e.g., v0.11.0) | ||
| --force Proceed even when there are no new commits | ||
| -h, --help Show this help message | ||
|
|
||
| Examples: | ||
| $(basename "$0") minor --dry-run | ||
| $(basename "$0") patch v0.10 --dry-run | ||
| $(basename "$0") minor --version v0.11.0 # resume a partial release | ||
| EOF | ||
| exit 0 | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
usage() always exits 0, even on the error path — masks real failures.
usage() unconditionally calls exit 0 (line 54). It's invoked both for -h|--help (should exit 0) and after error "Unknown argument: $1" (line 441-442, should exit non-zero). As written, an invalid CLI invocation prints an error but the script still reports success, which is misleading for any caller checking the exit code.
🐛 Proposed fix
-usage() {
+usage() {
+ local exit_code="${1:-0}"
cat <<EOF
...
EOF
- exit 0
+ exit "$exit_code"
} *)
error "Unknown argument: $1"
- usage
+ usage 1
;;Also applies to: 437-449
🤖 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 `@hack/release.sh` around lines 36 - 55, Update usage() to accept an
exit-status argument and exit with that value instead of unconditionally exiting
0. Keep the help path invoking usage with status 0, and update the
unknown-argument path near the argument parser to invoke usage with a non-zero
status after reporting the error.
| if git rev-parse "${UPSTREAM_REMOTE}/${release_branch}" &>/dev/null 2>&1; then | ||
| branch_exists=true | ||
| fi | ||
|
|
||
| local target_sha | ||
| target_sha=$(git rev-parse "${UPSTREAM_REMOTE}/main") | ||
| local target_short | ||
| target_short=$(git rev-parse --short "${UPSTREAM_REMOTE}/main") | ||
|
|
||
| if $tag_exists; then | ||
| local existing_tag_sha | ||
| existing_tag_sha=$(git rev-parse "$next_version") | ||
| if [[ "$existing_tag_sha" != "$target_sha" ]]; then | ||
| error "Tag ${next_version} already exists but points to a different commit!" | ||
| echo " Tag points to: $(git rev-parse --short "$next_version")" | ||
| echo " Expected (main): ${target_short}" | ||
| exit 1 | ||
| fi | ||
| fi |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
branch_exists isn't validated against the target commit, unlike tag_exists.
Lines 154-176 verify that an already-existing tag points at the expected target_sha, but the same check is missing for branch_exists (line 158-160). If release_branch already exists but points elsewhere (e.g. created earlier from a different commit), line 238-244 will silently skip it, leaving the release branch misaligned with the tag/release for future patch computations.
🐛 Proposed fix
if git rev-parse "${UPSTREAM_REMOTE}/${release_branch}" &>/dev/null 2>&1; then
branch_exists=true
fi+ if $branch_exists; then
+ local existing_branch_sha
+ existing_branch_sha=$(git rev-parse "${UPSTREAM_REMOTE}/${release_branch}")
+ if [[ "$existing_branch_sha" != "$target_sha" ]]; then
+ error "Branch ${release_branch} already exists but points to a different commit!"
+ echo " Branch points to: $(git rev-parse --short "${UPSTREAM_REMOTE}/${release_branch}")"
+ echo " Expected (main): ${target_short}"
+ exit 1
+ fi
+ fi📝 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.
| if git rev-parse "${UPSTREAM_REMOTE}/${release_branch}" &>/dev/null 2>&1; then | |
| branch_exists=true | |
| fi | |
| local target_sha | |
| target_sha=$(git rev-parse "${UPSTREAM_REMOTE}/main") | |
| local target_short | |
| target_short=$(git rev-parse --short "${UPSTREAM_REMOTE}/main") | |
| if $tag_exists; then | |
| local existing_tag_sha | |
| existing_tag_sha=$(git rev-parse "$next_version") | |
| if [[ "$existing_tag_sha" != "$target_sha" ]]; then | |
| error "Tag ${next_version} already exists but points to a different commit!" | |
| echo " Tag points to: $(git rev-parse --short "$next_version")" | |
| echo " Expected (main): ${target_short}" | |
| exit 1 | |
| fi | |
| fi | |
| if git rev-parse "${UPSTREAM_REMOTE}/${release_branch}" &>/dev/null 2>&1; then | |
| branch_exists=true | |
| fi | |
| local target_sha | |
| target_sha=$(git rev-parse "${UPSTREAM_REMOTE}/main") | |
| local target_short | |
| target_short=$(git rev-parse --short "${UPSTREAM_REMOTE}/main") | |
| if $branch_exists; then | |
| local existing_branch_sha | |
| existing_branch_sha=$(git rev-parse "${UPSTREAM_REMOTE}/${release_branch}") | |
| if [[ "$existing_branch_sha" != "$target_sha" ]]; then | |
| error "Branch ${release_branch} already exists but points to a different commit!" | |
| echo " Branch points to: $(git rev-parse --short "${UPSTREAM_REMOTE}/${release_branch}")" | |
| echo " Expected (main): ${target_short}" | |
| exit 1 | |
| fi | |
| fi | |
| if $tag_exists; then | |
| local existing_tag_sha | |
| existing_tag_sha=$(git rev-parse "$next_version") | |
| if [[ "$existing_tag_sha" != "$target_sha" ]]; then | |
| error "Tag ${next_version} already exists but points to a different commit!" | |
| echo " Tag points to: $(git rev-parse --short "$next_version")" | |
| echo " Expected (main): ${target_short}" | |
| exit 1 | |
| fi | |
| 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 `@hack/release.sh` around lines 158 - 176, Validate an existing release_branch
alongside the existing tag validation: when branch_exists is true, resolve the
branch commit and compare it with target_sha, reporting the branch and expected
commit details and exiting on mismatch. Keep the current behavior for a matching
branch and for branches that do not yet exist, using the existing
release_branch, target_sha, and target_short symbols.
cccd60b to
c7dab71
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
hack/release.sh (1)
219-227: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse an array for the optional
--notes-start-tagflag.Unquoted
$notes_flagrelies on word splitting (SC2086) and breaks the momentrun_cmddropsevaland quotes arguments properly.♻️ Proposed refactor
- local notes_flag="" + local notes_flag=() if [[ -n "$prev_tag" ]]; then - notes_flag="--notes-start-tag ${prev_tag}" + notes_flag=(--notes-start-tag "$prev_tag") fi run_cmd gh release create "$next_version" \ --repo "$REPO" \ --generate-notes \ --draft \ - $notes_flag + "${notes_flag[@]}"🤖 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 `@hack/release.sh` around lines 219 - 227, Update the release creation flow around notes_flag to represent the optional --notes-start-tag arguments as an array, append the flag and prev_tag only when prev_tag is set, and expand the array safely when invoking run_cmd gh release create. Remove the unquoted scalar expansion while preserving the existing command behavior.Source: Linters/SAST tools
.github/workflows/release.yml (1)
16-19: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSerialize release runs before mutating release state.
Two tags pushed close together can run concurrently while the release script creates/pushes branches and draft releases, causing push conflicts or duplicate drafts. Add a workflow-level concurrency group with
cancel-in-progress: false, or provide equivalent locking/idempotency in the script.Proposed fix
permissions: contents: write +concurrency: + group: release + cancel-in-progress: false + env:🤖 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/release.yml around lines 16 - 19, Add workflow-level concurrency to the release job identified by release, using a stable group for release runs and setting cancel-in-progress to false so queued tag-triggered runs execute serially without cancellation.
🤖 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 @.github/workflows/release.yml:
- Around line 29-32: Update the release workflow before the hack/release.sh
execution to guard v* tag pushes: allow only trusted maintainers or validate
that the tag matches protected release history, and skip the release script
otherwise. Preserve the existing checkout and release behavior for authorized,
validated tags.
In `@hack/release.sh`:
- Around line 273-295: Validate VERSION_OVERRIDE in the patch-version flow
before deriving override_patch, requiring the exact v${minor}.<numeric_patch>
format and rejecting mismatched or malformed values with the script’s standard
error handling. When deriving latest_patch_tag in this path, verify that the
resulting previous tag exists before calling git rev-list; report a clear error
and exit if it is missing, while preserving the existing tag validation for
next_version.
---
Nitpick comments:
In @.github/workflows/release.yml:
- Around line 16-19: Add workflow-level concurrency to the release job
identified by release, using a stable group for release runs and setting
cancel-in-progress to false so queued tag-triggered runs execute serially
without cancellation.
In `@hack/release.sh`:
- Around line 219-227: Update the release creation flow around notes_flag to
represent the optional --notes-start-tag arguments as an array, append the flag
and prev_tag only when prev_tag is set, and expand the array safely when
invoking run_cmd gh release create. Remove the unquoted scalar expansion while
preserving the existing command behavior.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8a37b49f-c708-4025-8efd-464905f4a1f1
📒 Files selected for processing (2)
.github/workflows/release.ymlhack/release.sh
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
wc -l .github/workflows/release.yml
cat -n .github/workflows/release.yml | sed -n '1,220p'Repository: redhat-data-and-ai/unstructured-data-controller
Length of output: 3223
Guard release tags before running hack/release.sh
Any push to v* can check out that tag’s commit and run hack/release.sh with contents: write and GH_TOKEN. Limit v* tag creation/update to trusted maintainers or require the tag to match protected release history before executing the script.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 29-32: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 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/release.yml around lines 29 - 32, Update the release
workflow before the hack/release.sh execution to guard v* tag pushes: allow only
trusted maintainers or validate that the tag matches protected release history,
and skip the release script otherwise. Preserve the existing checkout and
release behavior for authorized, validated tags.
| local next_version | ||
| if [[ -n "$VERSION_OVERRIDE" ]]; then | ||
| next_version="${VERSION_OVERRIDE}" | ||
| local override_patch="${next_version##*.}" | ||
| if (( override_patch > 0 )); then | ||
| latest_patch_tag="v${minor}.$((override_patch - 1))" | ||
| fi | ||
| else | ||
| local next_patch=$((max_patch + 1)) | ||
| next_version="v${minor}.${next_patch}" | ||
| fi | ||
|
|
||
| info "Existing v${minor}.x tags: $(get_all_tags | grep -P "^v${minor}\.[0-9]+$" | tr '\n' ' ')" | ||
| info "Latest patch: ${latest_patch_tag}" | ||
| info "Next version: ${BOLD}${next_version}${NC}" | ||
|
|
||
| if ! git rev-parse "$next_version" &>/dev/null 2>&1; then | ||
| error "Tag ${next_version} does not exist. Create and push the tag first." | ||
| exit 1 | ||
| fi | ||
|
|
||
| local new_commits | ||
| new_commits=$(git rev-list --count "${latest_patch_tag}..${UPSTREAM_REMOTE}/${release_branch}") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate --version in the patch path and verify the derived previous tag exists.
Two gaps here:
VERSION_OVERRIDEis never checked againstv${minor}.<n>, so a mismatched or malformed value (e.g.patch v0.10 --version v0.9.3, or a non-numeric suffix) either builds notes against the wrong lineage or aborts on the arithmetic at line 277.- Line 278 assumes
v${minor}.$((override_patch-1))exists. With a gap in patch numbering,git rev-listat line 295 dies with a raw "unknown revision" error.
🐛 Proposed fix
if [[ -n "$VERSION_OVERRIDE" ]]; then
+ if [[ ! "$VERSION_OVERRIDE" =~ ^v${minor}\.[0-9]+$ ]]; then
+ error "Invalid --version for a v${minor}.x patch release: ${VERSION_OVERRIDE}"
+ exit 1
+ fi
next_version="${VERSION_OVERRIDE}"
local override_patch="${next_version##*.}"
if (( override_patch > 0 )); then
latest_patch_tag="v${minor}.$((override_patch - 1))"
+ if ! git rev-parse "$latest_patch_tag" &>/dev/null 2>&1; then
+ latest_patch_tag=$(get_latest_patch_for_minor "$minor")
+ fi
fi
else📝 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.
| local next_version | |
| if [[ -n "$VERSION_OVERRIDE" ]]; then | |
| next_version="${VERSION_OVERRIDE}" | |
| local override_patch="${next_version##*.}" | |
| if (( override_patch > 0 )); then | |
| latest_patch_tag="v${minor}.$((override_patch - 1))" | |
| fi | |
| else | |
| local next_patch=$((max_patch + 1)) | |
| next_version="v${minor}.${next_patch}" | |
| fi | |
| info "Existing v${minor}.x tags: $(get_all_tags | grep -P "^v${minor}\.[0-9]+$" | tr '\n' ' ')" | |
| info "Latest patch: ${latest_patch_tag}" | |
| info "Next version: ${BOLD}${next_version}${NC}" | |
| if ! git rev-parse "$next_version" &>/dev/null 2>&1; then | |
| error "Tag ${next_version} does not exist. Create and push the tag first." | |
| exit 1 | |
| fi | |
| local new_commits | |
| new_commits=$(git rev-list --count "${latest_patch_tag}..${UPSTREAM_REMOTE}/${release_branch}") | |
| local next_version | |
| if [[ -n "$VERSION_OVERRIDE" ]]; then | |
| if [[ ! "$VERSION_OVERRIDE" =~ ^v${minor}\.[0-9]+$ ]]; then | |
| error "Invalid --version for a v${minor}.x patch release: ${VERSION_OVERRIDE}" | |
| exit 1 | |
| fi | |
| next_version="${VERSION_OVERRIDE}" | |
| local override_patch="${next_version##*.}" | |
| if (( override_patch > 0 )); then | |
| latest_patch_tag="v${minor}.$((override_patch - 1))" | |
| if ! git rev-parse "$latest_patch_tag" &>/dev/null 2>&1; then | |
| latest_patch_tag=$(get_latest_patch_for_minor "$minor") | |
| fi | |
| fi | |
| else | |
| local next_patch=$((max_patch + 1)) | |
| next_version="v${minor}.${next_patch}" | |
| fi | |
| info "Existing v${minor}.x tags: $(get_all_tags | grep -P "^v${minor}\.[0-9]+$" | tr '\n' ' ')" | |
| info "Latest patch: ${latest_patch_tag}" | |
| info "Next version: ${BOLD}${next_version}${NC}" | |
| if ! git rev-parse "$next_version" &>/dev/null 2>&1; then | |
| error "Tag ${next_version} does not exist. Create and push the tag first." | |
| exit 1 | |
| fi | |
| local new_commits | |
| new_commits=$(git rev-list --count "${latest_patch_tag}..${UPSTREAM_REMOTE}/${release_branch}") |
🤖 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 `@hack/release.sh` around lines 273 - 295, Validate VERSION_OVERRIDE in the
patch-version flow before deriving override_patch, requiring the exact
v${minor}.<numeric_patch> format and rejecting mismatched or malformed values
with the script’s standard error handling. When deriving latest_patch_tag in
this path, verify that the resulting previous tag exists before calling git
rev-list; report a clear error and exit if it is missing, while preserving the
existing tag validation for next_version.
Adds release script to do the minor or patch release
Summary by CodeRabbit
v*tags, validatesvMAJOR.MINOR.PATCH, computes minor vs patch, and runs the automation accordingly.