Skip to content

[MISC] Mark current-line hotfix releases as latest (semver supersession)#2116

Merged
ritwik-g merged 3 commits into
mainfrom
oss-hotfix-latest-fix
Jun 25, 2026
Merged

[MISC] Mark current-line hotfix releases as latest (semver supersession)#2116
ritwik-g merged 3 commits into
mainfrom
oss-hotfix-latest-fix

Conversation

@ritwik-g

Copy link
Copy Markdown
Contributor

What

  • Fix create-release.yaml so a hotfix release on the current production line is marked GitHub latest.

Why

  • The workflow marked every non-main release latest=false, so a hotfix on the current production OSS line never became GitHub latest even when it superseded the existing latest.

How

  • Mark the release as latest iff its computed tag supersedes the current releases/latest by semver (was: only when MODE == main). Current-line hotfixes (e.g. latest v0.176.3, hotfix → v0.176.4) now become latest; hotfixes on older lines stay latest=false.

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • No. Scoped to the single --latest flag decision in the "Create GitHub release" step. Main-line releases are always the newest by semver, so they remain latest=true exactly as before. Only new behavior: current-line hotfixes correctly become latest. Verified the decision logic with a mocked gh across current-line hotfix (→true), older-line hotfix (→false), main release (→true), and no-existing-latest (→true).

Database Migrations

  • None.

Env Config

  • None.

Relevant Docs

Related Issues or PRs

  • Enterprise counterpart (same latest fix in promote-rc-build-to-stable.yaml, plus the /devkit:hotfix skill): Zipstack/unstract-cloud#1608

Dependencies Versions

  • None.

Notes on Testing

  • Extracted the edited bash decision block from the workflow and ran it under a mock gh (mirroring the Actions bash -euo pipefail shell); all cases produced the expected --latest flag. YAML validated.

Screenshots

Checklist

I have read and understood the Contribution Guidelines.

🤖 Generated with Claude Code

create-release.yaml marked every non-main release latest=false, so a hotfix on
the current production OSS line never became GitHub "latest" even when it should.

Mark the release as latest when its computed tag supersedes the current
releases/latest by semver, instead of only on main-branch releases. Hotfixes on
the current line (e.g. latest v0.176.3, hotfix -> v0.176.4) now become latest;
hotfixes on older lines stay latest=false. Main-line releases are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8f8cfd7d-04ce-425b-a9a4-4f8b9c4af79f

📥 Commits

Reviewing files that changed from the base of the PR and between 6e6a5eb and bed282a.

📒 Files selected for processing (1)
  • .github/workflows/create-release.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/create-release.yaml

Summary by CodeRabbit

  • Bug Fixes
    • Improved how releases are marked as “latest” by comparing the new tag against the current GitHub “latest” release using version ordering.
    • Pre-releases no longer get marked as “latest.”
    • If no current “latest” release exists, the new release is set as “latest.”
    • If the new version is already the current “latest,” its status remains unchanged.
    • Unexpected GitHub API errors now stop the release process instead of guessing.

Walkthrough

The release workflow now checks GitHub’s current latest release tag before creating a release. It sets --latest from prerelease status and version comparison against the existing latest tag.

Changes

Release latest tag selection

Layer / File(s) Summary
Latest tag decision
.github/workflows/create-release.yaml
The release step now treats prereleases as --latest=false, fetches releases/latest for stable releases, handles 404 and other API failures, and compares NEW_TAG to the current latest tag before setting the flag.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: marking current-line hotfix releases as latest via semver supersession.
Description check ✅ Passed The description follows the template well and includes all required sections with concrete details, testing, and impact notes.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch oss-hotfix-latest-fix

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
Contributor

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 @.github/workflows/create-release.yaml:
- Around line 240-243: The release selection logic in the create-release
workflow is treating any `gh api` failure as if there were no existing latest
release. Update the `CURRENT_LATEST` fetch so `gh api` errors are not swallowed,
and only add `RELEASE_ARGS+=(--latest=true)` when `gh api` succeeds and returns
an empty tag; keep the existing behavior in the `CURRENT_LATEST`/`RELEASE_ARGS`
block but separate “no release” from transient API or auth failures.
🪄 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: d80598ae-bd07-4511-a573-cfdaba9e8ced

📥 Commits

Reviewing files that changed from the base of the PR and between 4f2bb8d and 1ec8770.

📒 Files selected for processing (1)
  • .github/workflows/create-release.yaml

Comment thread .github/workflows/create-release.yaml Outdated
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the create-release.yaml workflow so that hotfix releases on the current production line are correctly marked as GitHub latest when they supersede the existing latest release by semver, replacing the previous MODE == main-only heuristic.

  • Core logic change: Replaces the hard if [[ "$MODE" == "main" ]] guard with a semver supersession check using sort -V against the live releases/latest tag — current-line hotfixes (e.g. v0.176.3v0.176.4) now become latest=true; older-line hotfixes stay latest=false.
  • Error handling improvement: Directly addresses the previous silent-failure concern by differentiating genuine 404 ("no latest release yet") from transient API errors; transient failures now fail loudly via exit 1 instead of silently falling through to --latest=true.
  • Pre-release guard: Pre-releases short-circuit the entire supersession check to avoid ever emitting --latest=true alongside --prerelease.

Confidence Score: 5/5

Safe to merge — the change is scoped entirely to the --latest flag decision within a single workflow step, with no effect on the release artifact itself or any other workflow.

The previous silent-failure path (the main concern from earlier review rounds) is fully addressed: transient API errors now fail loudly via exit 1 rather than falling through to --latest=true. The semver comparison via sort -V is correct for the vX.Y.Z tag format used by this repo (GNU sort on ubuntu-latest handles v-prefixed numeric version strings reliably). Main-line releases still always produce --latest=true because they are always the highest semver. Pre-release short-circuiting prevents any --latest=true + --prerelease combination. The equality guard is documented and harmless. No logic paths are left unhandled.

No files require special attention.

Important Files Changed

Filename Overview
.github/workflows/create-release.yaml Replaces the main-only --latest heuristic with a sort -V-based semver supersession check; adds differentiated 404 vs transient-error handling for the gh api releases/latest call.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Create GitHub release step] --> B{PRERELEASE == true?}
    B -- Yes --> C[RELEASE_ARGS += --latest=false]
    B -- No --> D[gh api releases/latest --jq .tag_name]
    D -- exit 0 --> E[CURRENT_LATEST = tag]
    D -- exit not 0 --> F{grep HTTP 404 or Not Found in stderr?}
    F -- Yes --> G[CURRENT_LATEST = empty string / no existing latest]
    F -- No --> H[echo error / exit 1 loud fail]
    E --> I{CURRENT_LATEST empty?}
    G --> I
    I -- Yes --> J[RELEASE_ARGS += --latest=true]
    I -- No --> K{NEW_TAG == CURRENT_LATEST?}
    K -- Yes --> L[RELEASE_ARGS += --latest=false]
    K -- No --> M[sort -V NEW_TAG CURRENT_LATEST / tail -n1 = NEWEST]
    M --> N{NEWEST == NEW_TAG?}
    N -- Yes supersedes --> O[RELEASE_ARGS += --latest=true]
    N -- No older line --> P[RELEASE_ARGS += --latest=false]
    C --> Q[gh release create]
    J --> Q
    L --> Q
    O --> Q
    P --> Q
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Create GitHub release step] --> B{PRERELEASE == true?}
    B -- Yes --> C[RELEASE_ARGS += --latest=false]
    B -- No --> D[gh api releases/latest --jq .tag_name]
    D -- exit 0 --> E[CURRENT_LATEST = tag]
    D -- exit not 0 --> F{grep HTTP 404 or Not Found in stderr?}
    F -- Yes --> G[CURRENT_LATEST = empty string / no existing latest]
    F -- No --> H[echo error / exit 1 loud fail]
    E --> I{CURRENT_LATEST empty?}
    G --> I
    I -- Yes --> J[RELEASE_ARGS += --latest=true]
    I -- No --> K{NEW_TAG == CURRENT_LATEST?}
    K -- Yes --> L[RELEASE_ARGS += --latest=false]
    K -- No --> M[sort -V NEW_TAG CURRENT_LATEST / tail -n1 = NEWEST]
    M --> N{NEWEST == NEW_TAG?}
    N -- Yes supersedes --> O[RELEASE_ARGS += --latest=true]
    N -- No older line --> P[RELEASE_ARGS += --latest=false]
    C --> Q[gh release create]
    J --> Q
    L --> Q
    O --> Q
    P --> Q
Loading

Reviews (3): Last reviewed commit: "[MISC] PR review round 2: never mark a p..." | Re-trigger Greptile

Comment thread .github/workflows/create-release.yaml Outdated
Comment thread .github/workflows/create-release.yaml Outdated
ritwik-g and others added 2 commits June 25, 2026 17:47
When reading releases/latest to decide the "latest" flag, a transient gh API
failure (rate limit / 5xx) previously collapsed to empty and wrongly marked the
release latest=true — which could let a back-version hotfix steal "latest".
Now distinguish a genuine 404 (no latest release yet) from a transient failure
and fail the job loudly on the latter, mirroring the guarded releases/latest
pattern already used in the "Fetch base release version" step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t dead branch

- A pre-release is never GitHub "latest": guard the supersession decision behind
  the PRERELEASE check so we never emit --latest=true alongside --prerelease
  (previously a superseding pre-release could get both).
- Comment the NEW_TAG == CURRENT_LATEST branch as a defensive guard unreachable
  in practice (the tag-collision check rejects a duplicate NEW_TAG upstream).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ritwik-g

Copy link
Copy Markdown
Contributor Author

Round-2 review fix (bed282a): addressed the Greptile 4/5 note about pre-releases. The --latest decision is now guarded behind the PRERELEASE check, so a superseding pre-release gets --latest=false (never --latest=true alongside --prerelease) — we no longer depend on the GitHub API's prerelease-can't-be-latest enforcement. Verified the decision block across full-release / older-line / pre-release / transient-failure cases.

@github-actions

Copy link
Copy Markdown
Contributor

Unstract test results

Per-group results

Status Group Tier Passed Failed Errors Skipped Duration (s)
unit-connectors unit 64 12 0 3 16.5
unit-core unit 0 0 4 0 1.2
unit-platform-service unit 9 0 1 0 1.3
unit-prompt-service unit 15 0 0 0 19.9
unit-rig unit 53 0 0 0 3.2
unit-runner unit 11 0 0 0 3.0
unit-sdk1 unit 390 0 0 0 20.3
unit-tool-registry unit 0 0 1 0 1.2
unit-workers unit 0 0 0 0 17.2
TOTAL 542 12 6 3 83.9

Critical paths

⚠️ Critical paths not yet covered

  • auth-login — User can log in and obtain a session cookie. (entry: POST /api/v1/auth/login; declared coverage: no groups declared)
  • adapter-register-llm — Register and validate an LLM adapter. (entry: POST /api/v1/adapter/; declared coverage: no groups declared)
  • workflow-create-execute — Create a workflow, configure source+destination, execute, poll, fetch result. (entry: POST /api/v1/workflow/{id}/execute/; declared coverage: e2e-workflow)
  • api-deployment-run — Deploy a workflow as an API, POST a document, receive structured JSON. (entry: POST /deployment/api/{org}/{name}/; declared coverage: e2e-api-deployment)
  • prompt-studio-fetch-response — Prompt Studio: create project, add prompt, run single-pass, get response. (entry: POST /api/v1/prompt-studio/prompt-studio-tool/{id}/fetch_response/; declared coverage: e2e-prompt-studio)
  • pipeline-etl-execute — Run an ETL pipeline from source connector to destination. (entry: POST /api/v1/pipeline/{id}/execute/; declared coverage: no groups declared)
  • usage-token-tracking — Per-execution token usage is recorded and retrievable. (entry: GET /api/v1/usage/get_token_usage/; declared coverage: no groups declared)
  • workflow-execution-fan-out — Multi-file workflow execution fans out to file-processing workers and rejoins. (entry: internal: backend → rabbitmq → workers/file_processing; declared coverage: no groups declared)
  • callback-result-delivery — Async results are posted back via the callback worker. (entry: internal: workers/callback → backend /internal endpoints; declared coverage: no groups declared)
✅ Covered critical paths
  • tool-sandbox-exec — covered by unit-runner

@ritwik-g ritwik-g merged commit 7321a7c into main Jun 25, 2026
9 checks passed
@ritwik-g ritwik-g deleted the oss-hotfix-latest-fix branch June 25, 2026 13:29
@sonarqubecloud

Copy link
Copy Markdown

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.

4 participants