Repository navigation
release: one release "latest" titled "Cerberus <version>", published on a version bump; cerberus 0.3.1 (#32) #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b9f8cdb
f596de5
0bf8925
661f338
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,13 +3,19 @@ name: ci | |
| on: | ||
| push: | ||
| branches: [master] | ||
| tags: ['v*'] | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| # One run per branch: on pull requests a newer push cancels the older run; on master it waits | ||
| # instead (only the newest waits), so a release is never cut off halfway. A manual run shares the | ||
| # push group. | ||
| concurrency: | ||
| group: ci-${{ github.event_name == 'pull_request' && 'pull_request' || 'push' }}-${{ github.ref }} | ||
| cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} | ||
|
|
||
| jobs: | ||
| # Pull requests: a change to src/, the installers, the Makefile or ci/ comes with a new | ||
| # CERBERUS_VERSION (MAJOR.MINOR.PATCH) and its CHANGELOG.md section (#33). The checkout is the | ||
|
|
@@ -76,10 +82,8 @@ jobs: | |
| matrix: | ||
| arch: [arm, mipsel, aarch64, x86_64] | ||
| steps: | ||
| # The version compiled into the binary is CERBERUS_VERSION in src/cerberus.c. | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| # git describe needs the tags: the version compiled into the binary comes from them. | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Toolchain and mbedTLS cache | ||
| uses: actions/cache@v4 | ||
|
|
@@ -98,36 +102,99 @@ jobs: | |
|
|
||
| release: | ||
| name: release | ||
| # A v* tag publishes the binaries that were just built and tested — the same files, not a rebuild — | ||
| # together with the installer, the uninstaller (now a wrapper around it) and SHA256SUMS over all of them. | ||
| # Asset names carry no version: cameras fetch releases/latest/download/<name>. | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| # The one release, "latest" (#32): published from master when CERBERUS_VERSION differs from the | ||
| # version in the title of the current "latest", with the binaries that were just built and tested | ||
| # (the same files, not a rebuild), the installer, the uninstaller (a wrapper around it), the license | ||
| # and SHA256SUMS over all of them. Asset names carry no version: cameras fetch | ||
| # releases/latest/download/<name>, so "latest" is updated in place, never deleted: the files are | ||
| # replaced, the tag is moved to the built commit, then the title and notes follow. A push without | ||
| # a new version publishes nothing, and only the head of master is published. | ||
| if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master' | ||
| needs: [lint, test, build] | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: A new version? | ||
| id: ver | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| # Only the head of master: a rerun of an older run must not roll the cameras back. | ||
| head=$(git ls-remote origin refs/heads/master | cut -f 1) | ||
| if [ "$head" != "$GITHUB_SHA" ]; then | ||
| echo "::notice::master is at ${head:0:7} now, not ${GITHUB_SHA::7}: not published"; exit 0 | ||
| fi | ||
| ver=$(sed -n 's/^#define CERBERUS_VERSION "\([^"]*\)"[[:space:]]*$/\1/p' src/cerberus.c) | ||
| [ "$(printf '%s\n' "$ver" | grep -c .)" = 1 ] || { echo "::error::expected one CERBERUS_VERSION"; exit 1; } | ||
| # "Not found" means there is no "latest" yet; any other failure stops here. | ||
| if prev=$(gh release view latest --repo "$GITHUB_REPOSITORY" --json name -q .name 2>err.txt); then | ||
| echo "exists=1" >> "$GITHUB_OUTPUT" | ||
| elif grep -qi 'not found' err.txt; then | ||
| prev="" | ||
| echo "exists=0" >> "$GITHUB_OUTPUT" | ||
| else | ||
| cat err.txt; echo "::error::cannot read the current \"latest\" release"; exit 1 | ||
| fi | ||
| echo "latest is \"${prev:-none}\", src/cerberus.c says $ver" | ||
| echo "ver=$ver" >> "$GITHUB_OUTPUT" | ||
| if [ "$prev" != "Cerberus $ver" ]; then | ||
| echo "new=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| # same version: publish again only if a publication was cut off and files are missing | ||
| have=$(gh release view latest --repo "$GITHUB_REPOSITORY" --json assets -q '.assets[].name') | ||
| for f in cerberus-arm cerberus-mipsel cerberus-aarch64 cerberus-x86_64 install.sh uninstall.sh LICENSE.md SHA256SUMS; do | ||
| printf '%s\n' "$have" | grep -qx "$f" || { echo "latest lacks $f: publishing again"; echo "new=true" >> "$GITHUB_OUTPUT"; break; } | ||
| done | ||
| fi | ||
|
|
||
| - uses: actions/download-artifact@v4 | ||
| if: steps.ver.outputs.new == 'true' | ||
| with: | ||
| pattern: cerberus-* | ||
| path: dist | ||
| merge-multiple: true | ||
|
|
||
| - name: The binaries were built as this tag | ||
| - name: The binaries were built as this version | ||
| if: steps.ver.outputs.new == 'true' | ||
| env: | ||
| VER: ${{ steps.ver.outputs.ver }} | ||
| run: | | ||
| chmod +x dist/cerberus-* | ||
| got=$(dist/cerberus-x86_64 --help 2>&1 | head -1 | cut -d' ' -f2) | ||
| echo "binary says $got, tag says ${GITHUB_REF_NAME#v}" | ||
| [ "$got" = "${GITHUB_REF_NAME#v}" ] | ||
| echo "binary says $got, src/cerberus.c says $VER" | ||
| [ "$got" = "$VER" ] | ||
|
|
||
| - name: Lay out the release | ||
| if: steps.ver.outputs.new == 'true' | ||
| run: ci/assemble.sh | ||
|
|
||
| - name: Publish | ||
| if: steps.ver.outputs.new == 'true' | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| VER: ${{ steps.ver.outputs.ver }} | ||
| EXISTS: ${{ steps.ver.outputs.exists }} | ||
| run: | | ||
| gh release create "$GITHUB_REF_NAME" dist/* \ | ||
| --repo "$GITHUB_REPOSITORY" --title "cerberus ${GITHUB_REF_NAME#v}" --generate-notes --verify-tag | ||
| url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" | ||
| cat > notes.md <<NOTES | ||
| Cerberus ${VER} (\`${GITHUB_SHA::7}\`): static binaries for arm, mipsel, aarch64 and x86_64, the installer and \`SHA256SUMS\`. | ||
|
|
||
| Install: \`curl -fsSL ${url}/releases/latest/download/install.sh | sh -s -- <token>\`. Changes: [CHANGELOG.md](${url}/blob/master/CHANGELOG.md); details: [README](${url}#readme). | ||
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Camera installs can fail during an update 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
|
||
| 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 | ||
|
Comment on lines
+187
to
+191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. The old latest release record remains 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
|
||
| else | ||
| # a "latest" tag left without its release would keep its old commit under --target: | ||
| # move it (a failure stops the job), or create the release when there is no such tag | ||
| if gh api "repos/${GITHUB_REPOSITORY}/git/refs/tags/latest" >/dev/null 2>&1; then | ||
| gh api -X PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/latest" -f sha="$GITHUB_SHA" -F force=true >/dev/null | ||
| fi | ||
| gh release create latest dist/* --repo "$GITHUB_REPOSITORY" --latest \ | ||
| --target "$GITHUB_SHA" --title "Cerberus ${VER}" --notes-file notes.md | ||
|
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
|
||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6. A newer push can leave older binaries live
🐞 Bug≡ CorrectnessAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools