Skip to content

fix: mark pre-release versions correctly on GitHub releases - #32

Open
ThetaSinner wants to merge 1 commit into
mainfrom
fix/github-release-marking
Open

fix: mark pre-release versions correctly on GitHub releases#32
ThetaSinner wants to merge 1 commit into
mainfrom
fix/github-release-marking

Conversation

@ThetaSinner

Copy link
Copy Markdown
Member

Summary

  • Pre-release versions, such as v0.5.0-dev.0, are now created as pre-releases on GitHub and are never marked as the latest release.
  • Other versions are only marked as the latest release when they are higher than the version of the current latest release. This stops a patch release from a release branch, such as v0.3.7, from replacing a newer release, such as v0.4.2, as the latest release. GitHub marks every new release as the latest one by default, regardless of its version, so this needs to be requested explicitly.
  • The exit status of the GitHub CLI is now checked when creating a release. It was previously ignored, so a failed release creation was reported as a successful release.
  • Added unit tests for tag classification and the latest release comparison, and documented the behaviour in the maintainers section of the README.

Notes

  • The pre-release and latest decisions are separated into pure functions, so they are unit tested. The gh invocation itself has no automated coverage, since the integration tests run against Gitea and skip GitHub release creation.
  • Flag behaviour was checked against gh release create --help and the REST API documentation for make_latest.

Pre-release versions are now created as pre-releases on GitHub and are never
marked as the latest release.

Other versions are only marked as the latest release when they are higher than
the version of the current latest release. This stops a patch release from a
release branch, such as v0.3.7, from replacing a newer release, such as v0.4.2,
as the latest release. GitHub would otherwise mark every new release as the
latest one, regardless of its version.

Also check the exit status of the GitHub CLI when creating a release, which was
previously ignored so that a failed release creation was reported as a
successful release.
@cocogitto-bot

cocogitto-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

✔️ 2000db2 - Conventional commits check succeeded.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Release publishing now parses semver release tags, including optional v prefixes, to identify prereleases and compare versions with the current GitHub latest release. Release creation conditionally adds --prerelease and --latest=false, and reports failed GitHub CLI commands with their exit status. Unit tests cover tag parsing and latest-release decisions, while the README documents the resulting latest-release behavior.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main GitHub release tagging change.
Description check ✅ Passed The description clearly matches the release handling, exit-status, tests, and README updates in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/github-release-marking

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.

@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 `@crates/release_util/src/publish_release.rs`:
- Around line 124-158: Update get_latest_release_tag to capture stderr and
distinguish an absent release from other gh release view failures. Return
Ok(None) only when the command failure indicates no releases exist; otherwise
propagate a descriptive error containing the command failure details, preserving
successful JSON parsing and tag extraction.
🪄 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 Plus

Run ID: 553ac20c-1013-4ba2-a4e9-00908f7f49a2

📥 Commits

Reviewing files that changed from the base of the PR and between 6d27c17 and 2000db2.

📒 Files selected for processing (2)
  • README.md
  • crates/release_util/src/publish_release.rs

Comment on lines +124 to +158
/// Get the tag of the repository's current latest release, if it has one.
///
/// Pre-releases and drafts are never the latest release, so they are not considered here.
fn get_latest_release_tag(dir: impl AsRef<Path>) -> anyhow::Result<Option<String>> {
let output = std::process::Command::new("gh")
.current_dir(dir)
.arg("release")
.arg("view")
.arg("--json")
.arg("tagName")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.context("Failed to run `gh release view`")?;

// The command fails when the repository has no releases yet, which is not an error here.
if !output.status.success() {
println!("No current latest release found, this release will become the latest.");
return Ok(None);
}

let value = serde_json::from_slice::<serde_json::Value>(&output.stdout)
.context("Failed to parse `gh release view` output")?;

Ok(Some(
value
.as_object()
.context("Expected a JSON object as release view output")?
.get("tagName")
.context("Missing 'tagName' in release data")?
.as_str()
.context("Expected the tag name to be a string")?
.to_string(),
))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files:\n'
git ls-files | rg 'crates/release_util/src/publish_release\.rs|Cargo\.toml|README|gh|release' | head -200 || true

printf '\nRelevant function and callers:\n'
wc -l crates/release_util/src/publish_release.rs
sed -n '1,230p' crates/release_util/src/publish_release.rs

printf '\nSearch for should_be_latest_release references:\n'
rg -n "should_be_latest_release|get_latest_release_tag|release view|latest release" -S .

Repository: holochain/release-integration

Length of output: 11597


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect gh installation/version if available without running repo code.
if command -v gh >/dev/null 2>&1; then
  printf 'gh path:\n'
  command -v gh
  printf '\ngh version:\n'
  gh version
  printf '\ngh help release view relevant output:\n'
  gh help release view | sed -n '1,220p'
else
  printf 'gh not installed in sandbox\n'
fi

Repository: holochain/release-integration

Length of output: 1478


🌐 Web query:

GitHub CLI gh release view no release error exit code message

💡 Result:

When the GitHub CLI (gh) command gh release view fails to find a specified release (or the latest release), it exits with exit code 1 [1][2]. The specific error message typically displayed is: release not found [3][2] In accordance with general GitHub CLI conventions, any command failure, including this "not found" scenario, results in an exit code of 1 [4][5]. Because this is a standard error behavior, it is generally recommended to avoid relying on brittle string matching of the error message in scripts [6]. Instead, checking the command's exit code is the standard way to handle such failures [6]. For example, you can handle this condition in a shell script as follows: if! gh release view "$TAG" > /dev/null 2>&1; then echo "Release $TAG does not exist." fi If you specifically need to distinguish between a "not found" error and other potential errors (such as network issues or authentication failures), you would currently need to inspect the stderr output, though this is discouraged as the exact message is subject to change [1][6].

Citations:


🌐 Web query:

GitHub CLI gh release view prerelease draft exit code "release not found"

💡 Result:

When the GitHub CLI (gh) fails to find a specified release, it typically exits with exit code 1 [1][2][3]. Key details regarding this behavior and potential causes: Exit Code 1: Like most gh commands, gh release view returns 1 when it encounters an error, including when the requested release tag cannot be found [1][3][4]. API Inconsistency (Replication Lag): Even if a release exists (such as a draft or a recently created release), gh may return a "release not found" error if the command is executed immediately after the release is created [5][6]. This occurs because of transient replication lag between the GitHub APIs (e.g., GraphQL vs. REST) [5]. To resolve this, it is common practice to implement a retry mechanism with exponential backoff or add a short sleep (e.g., 2-3 seconds) after the release creation command [5][6]. Prereleases and Drafts: - Prereleases: If you run gh release view without arguments, it defaults to the "latest" release [7]. Because GitHub does not consider prereleases to be the "latest" release, the command will fail to find them unless you explicitly provide the specific tag name [7]. - Drafts: Similarly, draft releases are not "latest" and must be referenced by their specific tag name [7]. Troubleshooting: - Ensure you are providing the correct Git tag name, not a display name, as the identifier for the command [2]. - If you are running this in an automated workflow immediately after creating a release, use a retry loop that checks for success and handles "not found" errors by waiting [6]. Top Results: [1][3][5][6]

Citations:


Distinguish not-found from gh release view failures.

gh release view returns 1 for missing releases, but it also returns non-zero for transient/other failures, and every such failure currently returns None to should_be_latest_release. That can make an older release appear newer and be created as latest via --latest=false. Capture stderr so only the intentional “no latest release” cases are converted to None, and let auth/network/type errors fail clearly.

🤖 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 `@crates/release_util/src/publish_release.rs` around lines 124 - 158, Update
get_latest_release_tag to capture stderr and distinguish an absent release from
other gh release view failures. Return Ok(None) only when the command failure
indicates no releases exist; otherwise propagate a descriptive error containing
the command failure details, preserving successful JSON parsing and tag
extraction.

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.

1 participant