Skip to content

Update tagging/release workflow#633

Open
ashleyyli wants to merge 21 commits intomainfrom
ashleyl7/merge-release-deploy
Open

Update tagging/release workflow#633
ashleyyli wants to merge 21 commits intomainfrom
ashleyl7/merge-release-deploy

Conversation

@ashleyyli
Copy link
Copy Markdown
Contributor

@ashleyyli ashleyyli commented Mar 20, 2026

Addresses #613

  • Merge release and deploy-prod workflows
  • Only create release tag after tests have passed
  • Compare version to latest tag instead of package.json version in last commit: if deploy-prod or make-release fails, the workflow will rerun even if the version didn't change
  • Change workflow trigger

Light testing in https://github.com/acm-uiuc/core/tree/ashleyl7/test-workflow-branch

Summary by CodeRabbit

  • Chores
    • Streamlined release automation and triggers for production deployments; release creation is now automated when changes are pushed to main.
    • Build info now displays the full build hash instead of a truncated value.
  • Bug Fixes
    • Stronger version checks prevent creating releases when the version is unchanged or would be a semver downgrade (including prerelease ordering).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The deploy workflow was reworked: it now triggers on pushes to main, consolidates release/version logic into .github/workflows/deploy-prod.yml, and removes .github/workflows/release.yml. A new check-version job reads package.json version, compares it against the latest v* tag, outputs version and a prerelease flag, and fails on unchanged or semver-downgrade versions. test-unit and build depend on check-version; build sets VITE_BUILD_HASH from that job output. A make-release job creates v${version} releases (respecting prerelease) if absent. publish-node-client now depends on make-release. notify permissions were set explicitly. src/ui/util/revision.ts returns the full build hash instead of truncating to 7 chars.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: merging release and deploy-prod workflows and updating the tagging/release workflow trigger and logic.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 ashleyl7/merge-release-deploy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ashleyyli ashleyyli marked this pull request as ready for review March 20, 2026 03:25
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/deploy-prod.yml (1)

376-384: ⚠️ Potential issue | 🟡 Minor

Include check-version in the notification fan-in.

Line 377 omits the new gatekeeper job from needs, so version-check failures never show up in needs_json and the Discord alert path misses the real root cause.

Suggested fix
-    needs: [deploy-prod, publish-node-client, test-unit, build, test-e2e, make-release]
+    needs: [check-version, deploy-prod, publish-node-client, test-unit, build, test-e2e, make-release]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 376 - 384, The notify job's
needs array is missing the new gatekeeper job (check-version), so failures there
aren't included in needs_json and Discord alerts can miss the true cause; update
the notify job's needs list (the needs value used to build needs_json for the
lacherogwu/failed-jobs-discord-notification-action) to include "check-version"
alongside deploy-prod, publish-node-client, test-unit, build, test-e2e, and
make-release so the notification fan-in captures check-version failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy-prod.yml:
- Around line 175-181: The CI changed VITE_BUILD_HASH to a semantic version but
src/ui/util/revision.ts still assumes a git SHA and truncates to 7 chars; update
the consumer instead of reverting CI: modify the logic in
src/ui/util/revision.ts (the function/constant that reads
process.env.VITE_BUILD_HASH) to stop unconditionally slicing to 7 characters and
instead return the full env value or apply conditional truncation only when the
value matches a SHA pattern (e.g., hex of length >=7); ensure prerelease/long
semver strings are returned intact and update any exported symbol names used by
the UI accordingly.
- Around line 60-100: The current version_compare function uses plain string
comparison for prerelease parts (v1_pre, v2_pre) which misorders identifiers
like beta.2 vs beta.10; update version_compare to perform semver-correct
prerelease comparison by splitting v1_pre and v2_pre on '.' and comparing each
identifier: numeric identifiers compare numerically, numeric < non-numeric,
non-numeric compare lexically in ASCII order, and longer identifier lists win
only if all shared identifiers are equal; alternatively replace the hand-rolled
logic in version_compare with a proven semver-aware comparator (e.g., use sort
-V, a small Python/Node helper using packaging.version/semver library, or embed
the algorithm above) so prerelease ordering is semver compliant.
- Around line 10-15: The check-version job currently lacks an explicit
permissions block and inherits the full repo GITHUB_TOKEN scope; update the job
definition for check-version to declare minimal permissions (e.g., permissions:
contents: read) so the GITHUB_TOKEN only has read access to repository contents
for the steps that read the version outputs (keep the outputs keys is-prerelease
and version unchanged).
- Around line 327-344: The Create Release step is non-idempotent because it
always calls github.rest.repos.createRelease (tagName) and will fail on reruns
if the release/tag already exists; change the script to first check for an
existing release by tag (use github.rest.repos.getReleaseByTag or list releases
and match tagName) and only call createRelease when none exists, or wrap
createRelease in a try/catch and on a 422/already_exists error call
getReleaseByTag and reuse/update that release instead of failing; update the
script around the variables tagName, isPrerelease and the createRelease call to
implement this logic so the workflow becomes safe to rerun.

---

Outside diff comments:
In @.github/workflows/deploy-prod.yml:
- Around line 376-384: The notify job's needs array is missing the new
gatekeeper job (check-version), so failures there aren't included in needs_json
and Discord alerts can miss the true cause; update the notify job's needs list
(the needs value used to build needs_json for the
lacherogwu/failed-jobs-discord-notification-action) to include "check-version"
alongside deploy-prod, publish-node-client, test-unit, build, test-e2e, and
make-release so the notification fan-in captures check-version failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0d6f003b-3254-4c61-9f01-2eeaaa2fc343

📥 Commits

Reviewing files that changed from the base of the PR and between 6ca15ec and 2d68c09.

📒 Files selected for processing (2)
  • .github/workflows/deploy-prod.yml
  • .github/workflows/release.yml
💤 Files with no reviewable changes (1)
  • .github/workflows/release.yml

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/deploy-prod.yml (1)

1-7: ⚠️ Potential issue | 🔴 Critical

Serialize this workflow before relying on the latest-tag gate.

Because check-version only compares against the latest existing tag, two main pushes with the same package.json version can both pass if the first run has not reached make-release yet. The later run can then deploy a different commit while make-release exits early because v${version} already exists, leaving prod ahead of the tagged release.

Suggested fix
 name: Deploy all resources to PROD
 run-name: PROD deploy - @${{ github.actor }}
 
+concurrency:
+  group: prod-release-${{ github.ref }}
+  cancel-in-progress: false
+
 on:
   push:
     branches:
       - 'main'

Also applies to: 31-48

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 1 - 7, The workflow can race
around the latest-tag gate; add a GitHub Actions concurrency block to serialize
deploys so only one run can proceed at a time (preventing a later push from
passing check-version before make-release finishes). Edit the deploy-prod
workflow to add a top-level concurrency: set a stable group name (e.g.,
"deploy-prod-${{ github.ref }}" or a repo-wide "deploy-prod") and set
cancel-in-progress: false so runs queue instead of running concurrently; keep
references to the existing check-version and make-release steps unchanged but
now protected by the serialized concurrency group.
🧹 Nitpick comments (1)
.github/workflows/deploy-prod.yml (1)

419-427: Include check-version in the notifier context.

needs_json is built from needs, so the new gate job will never appear in the Discord payload as written. If version-gate failures are actionable, add it here too.

Suggested fix
   notify:
     permissions: {}
-    needs: [deploy-prod, publish-node-client, test-unit, build, test-e2e, make-release]
+    needs: [check-version, deploy-prod, publish-node-client, test-unit, build, test-e2e, make-release]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 419 - 427, The notify job's
needs array (in the notify job definition) is missing the version gate job, so
its needs_json won't include that gate; update the notify job's needs (the needs
array referenced in the notify job named "notify") to include "check-version"
(or the exact version-gate job name used in your workflow) alongside
deploy-prod, publish-node-client, test-unit, build, test-e2e, and make-release
so failures from the version gate appear in the Discord payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/deploy-prod.yml:
- Around line 1-7: The workflow can race around the latest-tag gate; add a
GitHub Actions concurrency block to serialize deploys so only one run can
proceed at a time (preventing a later push from passing check-version before
make-release finishes). Edit the deploy-prod workflow to add a top-level
concurrency: set a stable group name (e.g., "deploy-prod-${{ github.ref }}" or a
repo-wide "deploy-prod") and set cancel-in-progress: false so runs queue instead
of running concurrently; keep references to the existing check-version and
make-release steps unchanged but now protected by the serialized concurrency
group.

---

Nitpick comments:
In @.github/workflows/deploy-prod.yml:
- Around line 419-427: The notify job's needs array (in the notify job
definition) is missing the version gate job, so its needs_json won't include
that gate; update the notify job's needs (the needs array referenced in the
notify job named "notify") to include "check-version" (or the exact version-gate
job name used in your workflow) alongside deploy-prod, publish-node-client,
test-unit, build, test-e2e, and make-release so failures from the version gate
appear in the Discord payload.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d276943-c000-4f3e-9b0c-1f0b6bbdd808

📥 Commits

Reviewing files that changed from the base of the PR and between 63317fb and ee5e5b1.

📒 Files selected for processing (2)
  • .github/workflows/deploy-prod.yml
  • src/ui/util/revision.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/deploy-prod.yml (1)

184-185: Keep QA deployment gated on unit tests.

This graph change removes the transitive test-unit gate from test-e2e, so a unit-test failure will still build, deploy to QA, and consume the serialized QA slot. Either re-add test-unit here, or add it directly to test-e2e.needs if you want to keep the build itself parallelized.

♻️ Minimal change in this segment
    needs:
      - check-version
+      - test-unit
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 184 - 185, The QA deployment
workflow removed the transitive `test-unit` dependency causing QA to proceed
even if unit tests fail; restore the gate by adding `test-unit` to the `needs:`
list alongside `check-version` (or alternately add `test-unit` to the `needs`
array of the `test-e2e` job) so that either the QA deployment job or the
`test-e2e` job explicitly depends on `test-unit` and will be blocked when unit
tests fail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy-prod.yml:
- Around line 423-425: The notify job's fan-in is missing the check-version job,
so when check-version is the only failing job the Discord alert can't surface
the real root cause; update the notify job's needs list (the notify job block
referenced as "notify") to include check-version alongside deploy-prod,
publish-node-client, test-unit, build, test-e2e, and make-release so needs_json
will contain the failing check-version job and alerts report the correct root
cause.

---

Nitpick comments:
In @.github/workflows/deploy-prod.yml:
- Around line 184-185: The QA deployment workflow removed the transitive
`test-unit` dependency causing QA to proceed even if unit tests fail; restore
the gate by adding `test-unit` to the `needs:` list alongside `check-version`
(or alternately add `test-unit` to the `needs` array of the `test-e2e` job) so
that either the QA deployment job or the `test-e2e` job explicitly depends on
`test-unit` and will be blocked when unit tests fail.
🪄 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: d832ab46-6902-4b6f-9026-5a9f2669f3d1

📥 Commits

Reviewing files that changed from the base of the PR and between ee5e5b1 and 189a735.

📒 Files selected for processing (1)
  • .github/workflows/deploy-prod.yml

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy-prod.yml:
- Around line 41-44: The current logic uses git's --sort=version:refname to set
LATEST_TAG and PREVIOUS_VERSION which misorders prereleases vs releases; replace
that by enumerating all tags (the output feeding LATEST_TAG), strip the leading
"v" (as PREVIOUS_VERSION does), and then determine the highest semver using the
same semver comparator used elsewhere in this workflow (not git's sort).
Concretely: collect tags into a list instead of relying on git --sort, normalize
them by removing the "v" prefix (the same normalization used to set
PREVIOUS_VERSION), and pick the max with your semver comparator function so
LATEST_TAG/PREVIOUS_VERSION reflect true semver ordering (release > prerelease).
🪄 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: 172ffe93-043b-4c91-b930-63f520b1f983

📥 Commits

Reviewing files that changed from the base of the PR and between 189a735 and 58b659f.

📒 Files selected for processing (1)
  • .github/workflows/deploy-prod.yml

Comment on lines +41 to +44
# Get previous version
LATEST_TAG=$(git tag -l 'v*' --sort=-version:refname | head -n 1)
PREVIOUS_VERSION=${LATEST_TAG#v}
PREVIOUS_VERSION=${PREVIOUS_VERSION:-0.0.0}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Apr 3, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
export HOME="$tmp/home"
mkdir -p "$HOME"
repo="$tmp/repo"
mkdir -p "$repo"
cd "$repo"

git init -q
git -c user.name=test -c user.email=test@example.com commit --allow-empty -m init -q
git tag v1.2.3
git tag v1.2.3-beta.10
git tag -l 'v*' --sort=-version:refname

Repository: acm-uiuc/core

Length of output: 157


Don't use Git's version sort for semver comparison.

git tag --sort=version:refname doesn't correctly order same-base prereleases vs. releases. Git sorts suffixes lexicographically by default, but SemVer requires release versions to outrank their prereleases. With tags v1.2.3 and v1.2.3-beta.10, Git's sort puts the prerelease first—so head -n 1 picks v1.2.3-beta.10 as the "latest" tag instead of v1.2.3. This breaks PREVIOUS_VERSION extraction and can allow downgrades past the later semver check (e.g., deploying 1.2.3-beta.11 when 1.2.3 already exists). Use the same semver comparator you implement below instead of relying on Git's sort.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 41 - 44, The current logic
uses git's --sort=version:refname to set LATEST_TAG and PREVIOUS_VERSION which
misorders prereleases vs releases; replace that by enumerating all tags (the
output feeding LATEST_TAG), strip the leading "v" (as PREVIOUS_VERSION does),
and then determine the highest semver using the same semver comparator used
elsewhere in this workflow (not git's sort). Concretely: collect tags into a
list instead of relying on git --sort, normalize them by removing the "v" prefix
(the same normalization used to set PREVIOUS_VERSION), and pick the max with
your semver comparator function so LATEST_TAG/PREVIOUS_VERSION reflect true
semver ordering (release > prerelease).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Git's version:refname sorts by version number rather than lexicographically (--sort=refname)

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.

@ashleyyli, you're correct that --sort=version:refname performs numeric-aware version ordering (e.g., correctly placing 1.10.0 after 1.2.0), unlike --sort=refname which is purely lexicographic.

However, the concern about prerelease vs. release ordering still stands. Even when version sort is used in git-tag, tagnames with the same base version but different suffixes are still sorted lexicographically, resulting in prerelease tags appearing after the main release (e.g., "1.0-rc1" after "1.0"). This is the opposite of what SemVer requires — when major, minor, and patch are equal, a pre-release version has lower precedence than a normal version (e.g., 1.0.0-alpha < 1.0.0).

The practical impact: if both v1.2.3 and v1.2.3-beta.10 exist, --sort=-version:refname | head -n 1 returns v1.2.3-beta.10 (the prerelease sorts lexicographically higher due to the - suffix), not v1.2.3 (the true semver maximum). This would set PREVIOUS_VERSION to 1.2.3-beta.10, incorrectly blocking a deployment of 1.2.3.

The version:refname sort order can be affected by the versionsort.suffix configuration variable — and as shown in the Git source, you'd need to configure that with - as the suffix to make prereleases sort before their base release. Without it, the default behaviour misaligns with semver.

@ashleyyli ashleyyli requested a review from a team April 4, 2026 06:18
@ashleyyli ashleyyli changed the title Ashleyl7/merge release deploy Update tagging/release workflow Apr 4, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 5, 2026

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