Skip to content

release: one release "latest" titled "Cerberus <version>", published on a version bump; cerberus 0.3.1 (#32) - #37

Merged
keyldev merged 4 commits into
masterfrom
release/latest-on-version
Oct 17, 2026
Merged

keyldev merged 4 commits into
masterfrom
release/latest-on-version

Conversation

@compot-dev

Copy link
Copy Markdown
Collaborator

Closes #32. cerberus 0.3.1.

What changes

  • Release job (ci.yml): runs on master (pushes and manual runs) after lint, test, build. It reads CERBERUS_VERSION and publishes only when it differs from the version in the title of the current latest (releases/latest/download/install.sh is what new cameras install, so a release stays a deliberate version bump):
    • the binaries just built and tested, checked to report that version, plus the installers, the license and SHA256SUMS (ci/assemble.sh);
    • latest deleted with its tag and created again on the built commit, --latest, title Cerberus <version>, short notes (install command, CHANGELOG, README);
    • a failed lookup of latest (anything but "not found") stops the job; a push without a new version publishes nothing.
  • The v* tag trigger is gone. On master a newer push waits instead of cancelling a running workflow (no release cut off between delete and create); a manual run shares the push group.
  • ci/build.sh: the compiled version is CERBERUS_VERSION from src/cerberus.c (VERSION overrides it for a test build only); git describe is gone, so the build no longer needs tags or fetch-depth: 0.
  • CERBERUS_VERSION 0.3.1, the first release of the new scheme; CHANGELOG.md 0.3.1.
  • READMEs (all three): "Releases" (one release, latest, Cerberus <version>) and "CI and releases" (how a release is published; the git tag example is gone).

After the merge: check the first latest (Cerberus 0.3.1, the same file names, SHA256SUMS), then remove the v0.1.0…v0.3.0 releases and tags (their notes are in CHANGELOG.md since #35).

Tests

What Result
ci/build.sh, all four arches no warnings; static ELF, --help and the X25519/TLS checks under QEMU pass; sizes as in 0.3.0 (arm 308 396, mipsel 397 796, aarch64 337 432, x86_64 317 000); cerberus --help → cerberus 0.3.1
tests/run.sh 172 passed, 8 failed: the WireGuard data-plane checks (wg0, route, handshake, ping) that need NET_ADMIN, which this sandbox lacks; they fail the same way on master locally and pass in CI
shellcheck v0.10.0 -S warning clean
version check 0.3.0 → 0.3.1 with its CHANGELOG.md section

…on a version bump; cerberus 0.3.1 (#32)

- ci.yml: the release job runs on master (pushes and manual runs) after
  lint, test and build; it reads CERBERUS_VERSION and publishes only when
  it differs from the version in the title of the current "latest": the
  binaries just built and tested, the installers, the license and
  SHA256SUMS (ci/assemble.sh), "latest" deleted with its tag and created
  again on the built commit, titled "Cerberus <ver>". A failed lookup of
  "latest" (other than not found) stops the job. The v* tag trigger is
  gone; on master a newer push waits instead of cancelling.
- ci/build.sh: the compiled version is CERBERUS_VERSION in src/cerberus.c
  (VERSION overrides it for a test build only); no git describe, so the
  build no longer needs the tags or a full clone.
- CERBERUS_VERSION 0.3.1: the first release under this scheme.
- READMEs: "Releases" and "CI and releases" describe the one release
  and how to publish (bump the version with its CHANGELOG.md section).
- CHANGELOG.md: 0.3.1.

The v0.1.0...v0.3.0 releases and tags are removed after the first latest
is checked (their notes are in CHANGELOG.md, #35).

Tested: ci/build.sh (all four arches, compot cache): no warnings, ELF and
TLS checks under QEMU pass, sizes as in 0.3.0, cerberus --help says
0.3.1; tests/run.sh 172 passed, 8 failed — the WireGuard data-plane
checks that cannot run in this sandbox (no NET_ADMIN), as on master;
shellcheck v0.10.0 -S warning clean.

Closes #32
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Publish a single latest release when the Cerberus version changes

✨ Enhancement ⚙️ Configuration changes 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Replace tag-triggered releases with one latest release published after a version bump on
 master.
• Build binaries from the source version and publish the tested artifacts as Cerberus 0.3.1.
• Document the new release process and preserve stable camera download URLs.
Diagram

graph TD
  A["Master push"] --> B["CI checks"] --> E{"Version changed?"} -->|yes| G["Verified assets"] --> H["Latest release"]
  C["Source version"] --> E
  D["Current latest"] --> E
  E -->|no| F["Skip publish"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Update the existing release in place
  • ➕ Avoids the gap between deleting and recreating latest.
  • ➖ Requires coordinating tag movement, asset replacement, and metadata updates; downloads could briefly mix versions.

Recommendation: Recreating latest is simpler and matches the requirement for a single release with stable asset names. Master-run concurrency protects the delete/create sequence from cancellation, though reviewers should accept the brief period when latest is unavailable; use an in-place strategy if uninterrupted downloads are required.

Files changed (7) +94 / -39

Enhancement (1) +4 / -4
build.shStop deriving release versions from Git tags +4/-4

Stop deriving release versions from Git tags

• Removes git describe as the build-version default. Builds now retain CERBERUS_VERSION from source unless VERSION is explicitly supplied for a test build.

ci/build.sh

Documentation (4) +33 / -21
CHANGELOG.mdRecord the 0.3.1 release and release-policy change +13/-0

Record the 0.3.1 release and release-policy change

• Adds the 0.3.1 entry describing the single latest release, source-defined binary version, and version-bump expectations for pull requests.

CHANGELOG.md

README.mdExplain the single-release publishing process +7/-7

Explain the single-release publishing process

• Describes latest as the sole release and replaces tag-publishing instructions with the version-bump and changelog workflow.

README.md

README.ru.mdUpdate Russian release instructions +7/-7

Update Russian release instructions

• Documents the sole latest release, source-defined version, and master-based publishing process in Russian.

README.ru.md

README.zh-CN.mdUpdate Chinese release instructions +6/-7

Update Chinese release instructions

• Documents the sole latest release, source-defined version, and master-based publishing process in Chinese.

README.zh-CN.md

Other (2) +57 / -14
ci.ymlPublish latest from master only when the version changes +56/-13

Publish latest from master only when the version changes

• Removes the version-tag trigger and makes release depend on successful lint, test, and build jobs on master. Compares CERBERUS_VERSION with the current latest release title, verifies the built binary, and replaces latest with assembled assets and versioned notes; concurrency prevents master runs from cancelling publication.

.github/workflows/ci.yml

cerberus.cBump the source version to 0.3.1 +1/-1

Bump the source version to 0.3.1

• Sets CERBERUS_VERSION to 0.3.1, the version compiled into the first release under the new publishing scheme.

src/cerberus.c

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (1) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. The old latest release record remains 📎 Requirement gap ≡ Correctness
Description
The Publish branch for an existing release uploads over latest and edits it instead of deleting
it with --cleanup-tag. Whenever latest already exists, its release record is retained and only
its assets, tag target, title, and notes are mutated, so the required delete-and-recreate
publication is not performed.
Code

.github/workflows/ci.yml[R179-183]

+          if [ "$EXISTS" = 1 ]; then
+            # in place: files first, then the tag, then the title and notes
+            gh release upload latest dist/* --repo "$GITHUB_REPOSITORY" --clobber
+            gh api -X PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/latest" -f sha="$GITHUB_SHA" -F force=true >/dev/null
+            gh release edit latest --repo "$GITHUB_REPOSITORY" --latest --title "Cerberus ${VER}" --notes-file notes.md
Evidence
PR Compliance ID 3 requires deleting the old latest release and tag with --cleanup-tag, then
creating a new latest release on the built commit. The changed existing-release branch only
uploads with --clobber, force-moves the tag, and edits the release, with no delete or
--cleanup-tag operation.

Publish one correctly titled latest release
.github/workflows/ci.yml[179-183]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The existing `latest` release is edited in place rather than deleted with its tag and recreated on the built commit, which does not satisfy the required release replacement flow.
## Fix Focus Areas
- .github/workflows/ci.yml[179-183]
## Recommended Fix
Replace the existing-release upload and edit branch with a `gh release delete latest --cleanup-tag` operation followed by `gh release create latest` using the assembled assets, `--latest`, the built commit, the `Cerberus <version>` title, and the generated notes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Camera installs can fail during an update 🐞 Bug ☼ Reliability
Description
gh release upload latest dist/* --clobber replaces release assets separately, exposing binaries
and SHA256SUMS from different builds while publication is in progress. An installer that fetches
those files on opposite sides of a replacement fails checksum verification; an upload failure can
leave that mismatch in place until publication is retried.
Code

.github/workflows/ci.yml[181]

+            gh release upload latest dist/* --repo "$GITHUB_REPOSITORY" --clobber
Evidence
The assembly script computes checksums for the files being uploaded, but the installer fetches its
binary and checksum in separate requests and exits on a mismatch. The new upload step replaces the
live release's assets before completing the remaining publication steps.

.github/workflows/ci.yml[179-183]
ci/assemble.sh[17-25]
install.sh[95-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Updating the live release replaces assets separately, so installers can fetch a binary and checksum from different builds. A failed upload can leave that state in place.
## Fix Focus Areas
- .github/workflows/ci.yml[179-183]
- install.sh[95-105]
## Recommended Fix
Make publication recover from a partially replaced asset set, and have the installer retry fetching both the binary and checksum when they disagree during a release update. Ensure a failed upload cannot leave the live release permanently inconsistent.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. An incomplete first release stays broken ✓ Resolved
Description
gh release create latest dist/* can create the release with the final title before its asset
uploads finish, while the version gate checks only that title. If an upload then fails, reruns and
later pushes at the same source version skip every release step, leaving missing assets unavailable
to installers.
Code

.github/workflows/ci.yml[R188-189]

+            gh release create latest dist/* --repo "$GITHUB_REPOSITORY" --latest \
+              --target "$GITHUB_SHA" --title "Cerberus ${VER}" --notes-file notes.md
Evidence
The bootstrap command creates the titled release and uploads its assets in one operation. The next
run reads only the title, and all steps that could restore missing assets require the new output;
the installer requires both the binary and checksum assets.

.github/workflows/ci.yml[130-167]
.github/workflows/ci.yml[184-189]
ci/assemble.sh[16-25]
install.sh[95-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A failed asset upload during initial release creation can leave a release whose title matches the source version but whose assets are incomplete. The title-only gate prevents subsequent runs from repairing it.
## Fix Focus Areas
- .github/workflows/ci.yml[133-143]
- .github/workflows/ci.yml[184-189]
## Recommended Fix
Before treating a matching title as a completed publication, verify that every expected release asset exists and is complete. If the release is incomplete, repair or recreate its missing assets on a rerun even when the source version has not changed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View action required (2)
4. Old runs can downgrade camera downloads ✓ Resolved
Description
The release check treats any title mismatch as a new version without checking whether the workflow's
commit predates the current release. Rerunning an older master workflow after a newer version is
published passes that check, then deletes the newer release and republishes the older binaries at
the URL cameras use.
Code

.github/workflows/ci.yml[136]

+          [ "$prev" = "Cerberus $ver" ] || echo "new=true" >> "$GITHUB_OUTPUT"
Evidence
Master runs are not canceled, the release job accepts master runs, and a mismatch alone enables
deletion and recreation using the run's SHA. The installer fetches binaries from the mutable
latest URL.

.github/workflows/ci.yml[12-17]
.github/workflows/ci.yml[110-136]
.github/workflows/ci.yml[159-176]
install.sh[1-4]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An older master workflow rerun can replace a newer `latest` release because any version mismatch triggers publication.
## Fix Focus Areas
- .github/workflows/ci.yml[118-136]
- .github/workflows/ci.yml[159-176]
## Recommended Fix
Before replacing `latest`, verify that the candidate commit is not older than the commit of the currently published release. Recheck this condition immediately before publication and leave the newer release untouched when an old run is rerun.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Failed publishing breaks camera installs ✓ Resolved
Description
The Publish step deletes the existing latest release and tag before gh release create has
succeeded. If creation or asset upload fails after deletion, the installer's latest/download
requests have no complete release to fetch until someone reruns publication.
Code

.github/workflows/ci.yml[R172-175]

+          if [ "$EXISTS" = 1 ]; then
+            gh release delete latest --repo "$GITHUB_REPOSITORY" --cleanup-tag --yes
+          fi
+          gh release create latest dist/* --repo "$GITHUB_REPOSITORY" --latest \
Evidence
The workflow performs deletion before creation; the installer requires both the binary and its
checksum at the latest/download address and fails when either download fails.

.github/workflows/ci.yml[172-176]
install.sh[1-4]
install.sh[87-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Deleting `latest` before the replacement is successfully created and populated leaves camera download URLs unavailable if publishing fails.
## Fix Focus Areas
- .github/workflows/ci.yml[159-176]
## Recommended Fix
Stage and verify the replacement assets before removing the existing release, then switch the public release to the new version. Keep or restore the previous release if any publication step fails.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Camera releases can point to old commits ✓ Resolved
Description
The no-release branch suppresses errors when moving an existing latest tag, then creates the
release even if that tag still points to an older commit. When a tag remains after its release is
removed and the move fails, --target does not correct the existing tag; subsequent runs see the
expected title and asset names and skip publication.
Code

.github/workflows/ci.yml[R194-195]

+            gh api -X PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/latest" -f sha="$GITHUB_SHA" -F force=true \
+              >/dev/null 2>&1 || true
Evidence
The publish-path comment acknowledges that an existing tag retains its old commit under --target,
but the tag-update command discards every error before creating the release. The same-version gate
checks only the release title and required asset names, so it cannot detect that stale tag on a
later run.

.github/workflows/ci.yml[193-198]
.github/workflows/ci.yml[143-151]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The no-release publication path ignores failures to move an existing `latest` tag. Creating a release with `--target` does not retarget that existing tag, and the version gate will not detect the resulting stale commit.
## Fix Focus Areas
- .github/workflows/ci.yml[193-197]
- .github/workflows/ci.yml[143-151]
## Recommended Fix
Distinguish a missing tag from a failed tag update. Continue to release creation when the tag is absent, but stop publication if an existing tag cannot be moved to `GITHUB_SHA`; verify the tag target before treating a same-version release as complete.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can see how risky a PR is at a glance with blast radius labels

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/ci.yml Outdated
…place

Qodo on #37:
- a rerun of an older master workflow could replace a newer latest and
  roll the cameras back: the job publishes only when the built commit is
  the head of master (git ls-remote), otherwise it says so and stops.
- deleting latest before creating it again left the installer's
  releases/latest/download links without files if the create failed: an
  existing latest is now updated in place — the files replaced
  (--clobber), the tag moved to the built commit, then the title and
  notes. Only the very first publication creates it (moving a left-over
  latest tag first).

Refs #32
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Qodo findings, both fixed in f596de5:

  1. Old runs can downgrade camera downloads: the release job first checks that the built commit is the head of master (git ls-remote origin refs/heads/master); a rerun of an older run logs a notice and publishes nothing.
  2. Failed publishing breaks camera installs: an existing latest is no longer deleted. It is updated in place: gh release upload --clobber replaces the files (same names, so releases/latest/download/<name> always serves a file), then the latest tag is moved to the built commit, then title and notes are edited. Only the very first publication creates the release (after moving a left-over latest tag, since --target would not). The replacement of the files themselves is not atomic across assets on GitHub; a failure there fails the job visibly and leaves a downloadable release.

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Qodo findings, both fixed in f596de5:

  1. Old runs can downgrade camera downloads: the release job first checks that the built commit is the head of master (git ls-remote origin refs/heads/master); a rerun of an older run logs a notice and publishes nothing.
  2. Failed publishing breaks camera installs: an existing latest is no longer deleted. It is updated in place: gh release upload --clobber replaces the files (same names, so releases/latest/download/<name> always serves a file), then the latest tag is moved to the built commit, then title and notes are edited. Only the very first publication creates the release (after moving a left-over latest tag, since --target would not). The replacement of the files themselves is not atomic across assets on GitHub; a failure there fails the job visibly and leaves a downloadable release.

Thanks for the update. Based on f596de5:

  • finding 1 is addressed for reruns of commits no longer at the head of master; the head check prevents those runs from publishing older binaries.
  • finding 2 is substantially mitigated: existing releases are updated in place rather than deleted first, so a failed upload does not remove latest. The asset replacement itself remains non-atomic, so a failure could theoretically leave a mixed set of assets, but the release remains available.

I can’t mark findings implemented from this chat, but the cited changes appear to address both reported failure modes.

Comment thread .github/workflows/ci.yml
Comment on lines +179 to +183
if [ "$EXISTS" = 1 ]; then
# in place: files first, then the tag, then the title and notes
gh release upload latest dist/* --repo "$GITHUB_REPOSITORY" --clobber
gh api -X PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/latest" -f sha="$GITHUB_SHA" -F force=true >/dev/null
gh release edit latest --repo "$GITHUB_REPOSITORY" --latest --title "Cerberus ${VER}" --notes-file notes.md

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. The old latest release record remains 📎 Requirement gap ≡ Correctness

The Publish branch for an existing release uploads over latest and edits it instead of deleting
it with --cleanup-tag. Whenever latest already exists, its release record is retained and only
its assets, tag target, title, and notes are mutated, so the required delete-and-recreate
publication is not performed.
Agent Prompt
## Issue description
The existing `latest` release is edited in place rather than deleted with its tag and recreated on the built commit, which does not satisfy the required release replacement flow.

## Fix Focus Areas
- .github/workflows/ci.yml[179-183]

## Recommended Fix
Replace the existing-release upload and edit branch with a `gh release delete latest --cleanup-tag` operation followed by `gh release create latest` using the assembled assets, `--latest`, the built commit, the `Cerberus <version>` title, and the generated notes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread .github/workflows/ci.yml
NOTES
if [ "$EXISTS" = 1 ]; then
# in place: files first, then the tag, then the title and notes
gh release upload latest dist/* --repo "$GITHUB_REPOSITORY" --clobber

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Camera installs can fail during an update 🐞 Bug ☼ Reliability

gh release upload latest dist/* --clobber replaces release assets separately, exposing binaries
and SHA256SUMS from different builds while publication is in progress. An installer that fetches
those files on opposite sides of a replacement fails checksum verification; an upload failure can
leave that mismatch in place until publication is retried.
Agent Prompt
## Issue description
Updating the live release replaces assets separately, so installers can fetch a binary and checksum from different builds. A failed upload can leave that state in place.
## Fix Focus Areas
- .github/workflows/ci.yml[179-183]
- install.sh[95-105]
## Recommended Fix
Make publication recover from a partially replaced asset set, and have the installer retry fetching both the binary and checksum when they disagree during a release update. Ensure a failed upload cannot leave the live release permanently inconsistent.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread .github/workflows/ci.yml
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit f596de5

Qodo on #37: if a publication was cut off after the title was set, later
runs at the same version skipped it and left files missing for the
installer. With the same version in the title the job now checks the
release's files (the four binaries, the installers, LICENSE.md,
SHA256SUMS) and publishes again when one is missing.

Refs #32
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Qodo findings on f596de5:

  • 3. An incomplete first release stays broken: fixed in 0bf8925. When latest already carries this version, the job checks its files (the four binaries, install.sh, uninstall.sh, LICENSE.md, SHA256SUMS) and publishes again if one is missing, so a cut-off publication is completed by the next run.
  • 1. The old latest release record remains: by decision — in-place update replaced delete-and-recreate in the previous round, because of finding "Failed publishing breaks camera installs": cameras fetch releases/latest/download/<name>, and deleting the release leaves them nothing to fetch until it is created again. The sandbox release standard now names this variant for repositories whose latest devices install from (cerberus) or two branches write (OpenIPC/decoder); the issue text predates it.
  • 2. Camera installs can fail during an update: not adopted. Replacing several assets is not atomic on GitHub in any order; for the seconds of the upload an installer may get a binary and a SHA256SUMS from different builds, and then it reports the mismatch and exits without installing anything (that is what the checksum is for); running it again succeeds. A failed upload fails the job, and the next run publishes the full set (finding 3).

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Qodo findings on f596de5:

  • 3. An incomplete first release stays broken: fixed in 0bf8925. When latest already carries this version, the job checks its files (the four binaries, install.sh, uninstall.sh, LICENSE.md, SHA256SUMS) and publishes again if one is missing, so a cut-off publication is completed by the next run.
  • 1. The old latest release record remains: by decision — in-place update replaced delete-and-recreate in the previous round, because of finding "Failed publishing breaks camera installs": cameras fetch releases/latest/download/<name>, and deleting the release leaves them nothing to fetch until it is created again. The sandbox release standard now names this variant for repositories whose latest devices install from (cerberus) or two branches write (OpenIPC/decoder); the issue text predates it.
  • 2. Camera installs can fail during an update: not adopted. Replacing several assets is not atomic on GitHub in any order; for the seconds of the upload an installer may get a binary and a SHA256SUMS from different builds, and then it reports the mismatch and exits without installing anything (that is what the checksum is for); running it again succeeds. A failed upload fails the job, and the next run publishes the full set (finding 3).

Understood. Your rationale addresses the three current findings:

  • finding 3: addressed in commit 0bf8925 by repairing incomplete asset sets on subsequent runs.
  • finding 1: intentionally retained as an in-place update to avoid making latest unavailable during replacement.
  • finding 2: not adopted because checksum verification prevents installation of mismatched assets, and subsequent publication retries restore the complete set.

The findings remain open in Qodo’s review until explicitly dismissed; no review or PR changes were performed.

Comment thread .github/workflows/ci.yml Outdated
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0bf8925

Qodo on #37: the first-publication path hid a failure to move a latest
tag that survived without its release, and --target does not move an
existing tag. The tag is now moved only if it exists, and a failure
stops the job before the release is created.

Refs #32
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Qodo finding 6 (camera releases can point to old commits): fixed in 661f338. On the first-publication path the job checks whether a latest tag exists (git/refs/tags/latest); if it does, it is moved to the built commit and a failure stops the job before the release is created; if it does not, gh release create --target makes it on the built commit. Findings 1 and 2: unchanged, see the reply above.

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

@keyldev

keyldev commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Looks good — in-place update, the head-of-master guard and the asset check cover what I raised on #32. Merging once the test jobs are green.
Small follow-ups, not blockers: a README line that a rollback is "revert + bump"; the comment above CERBERUS_VERSION in src/cerberus.c still says release builds pass the tag in.
After the first latest (Cerberus 0.3.1) checks out, go ahead and remove v0.1.0…v0.3.0 — the cloud side is fine with it.

@keyldev
keyldev merged commit 632eae5 into master Oct 17, 2026
8 checks passed
Comment thread .github/workflows/ci.yml
Comment on lines +126 to +127
head=$(git ls-remote origin refs/heads/master | cut -f 1)
if [ "$head" != "$GITHUB_SHA" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. A newer push can leave older binaries live 🐞 Bug ≡ Correctness

A new version? checks the head of master only once, before downloading artifacts and publishing
the release. If another commit with the same version lands after that check, the older run can
publish its binaries, while the newer run sees a complete release with the expected title and skips
publication.
Agent Prompt
## Issue description
A push can advance `master` after the release job's sole head check, allowing an older run to publish assets that a subsequent same-version run will not replace.

## Fix Focus Areas
- .github/workflows/ci.yml[125-129]
- .github/workflows/ci.yml[174-200]

## Recommended Fix
Check the remote head again immediately before mutating the release. If it has advanced, exit without publishing so the queued run can publish from the newer commit.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 661f338

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.

Release: one release "latest" titled "Cerberus <version>", published on a version bump

2 participants