ci(release): exact tag checks and a retryable beta publish (#40)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Renovate / renovate (push) Successful in 1m26s
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Renovate / renovate (push) Successful in 1m26s
### What this changes - New `scripts/release_gate.sh`, used by the `detect` jobs of both `release.yaml` and `beta.yaml`, decides whether the committed version still needs publishing. Tags are read by exact name via `git ls-remote` instead of Codeberg's `git/refs/tags/<name>` API. - A beta counts as done only once its Codeberg pre-release carries the APK, so a publish that failed part-way is redone by the next push of the branch. - A beta is refused unless it is newer than the latest stable tag (previously only an exact `vX.Y.Z` tag was checked). - `publish_codeberg_release.sh` fails a pre-release when `CODEBERG_RELEASE_TOKEN` is missing (stable still skips), fails on any asset upload that doesn't return 201, and no longer aborts when the asset listing returns an error. - `version_info.sh` rejects leading zeros (`1.1.0-beta.01` would have shared `beta.1`'s versionCode under a different tag). - `beta.yaml` header and `docs/RELEASING.md` updated to match. ### Why Codeberg's `git/refs/tags/<name>` matches by prefix: asking for `v1.1.0` returns 200 because `v1.1.0-beta.1` exists. Merging 1.1.0 into `main` would have logged "tag already exists" and shipped nothing while the run stayed green, and `1.1.0-beta.2` would have been refused as "already shipped stable". `release/v1.1.0` needs `main` merged in after this lands, since `beta.yaml` runs from the pushed branch's files. ### Also in here `gradle/gradle-daemon-jvm.properties` now points at JetBrains' own download URLs for JBR 21.0.11 instead of foojay. foojay dropped JetBrains 21 from its index, so the pinned package ids return 400 and CI couldn't provision the daemon JVM (unrelated to the release change, but it blocks every PR until fixed). ### Checklist - [x] No `values-*/strings.xml` touched - [x] No `versionName` / `versionCode` bump - [x] `CHANGELOG.md` not updated: release infrastructure, not a user-visible change Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Reviewed-on: https://codeberg.org/jlmakiola/agendula/pulls/40
This commit is contained in:
@@ -3,7 +3,7 @@ name: Beta — Codeberg pre-release
|
||||
# A beta is cut by pushing a release branch whose committed versionName is
|
||||
# X.Y.Z-beta.N (see docs/RELEASING.md). Same model as release.yaml: the
|
||||
# committed version is the trigger and the vX.Y.Z-beta.N tag is an output. If
|
||||
# no tag exists for that version yet, this runs the unit tests, builds and
|
||||
# its Codeberg pre-release doesn't carry the APK yet, this runs the unit tests, builds and
|
||||
# signs the APK with the app key, records a Gitea pre-release (with the R8
|
||||
# mapping) and publishes a Codeberg pre-release with the APK + SHA-256.
|
||||
#
|
||||
@@ -36,53 +36,23 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Resolve version and whether it is a new beta
|
||||
- name: Resolve version and whether it still needs publishing
|
||||
id: v
|
||||
env:
|
||||
# Codeberg, not Gitea: see the same lookup in release.yaml.
|
||||
TAG_API: https://codeberg.org/api/v1/repos/jlmakiola/agendula
|
||||
run: |
|
||||
set -e
|
||||
INFO=$(bash scripts/version_info.sh)
|
||||
echo "$INFO"
|
||||
echo "$INFO" >> "$GITHUB_OUTPUT"
|
||||
VERSION=$(echo "$INFO" | sed -n 's/^version=//p')
|
||||
BASE=$(echo "$INFO" | sed -n 's/^base_version=//p')
|
||||
if [ "$(echo "$INFO" | sed -n 's/^channel=//p')" != "beta" ]; then
|
||||
echo "versionName $VERSION is not a beta — nothing to do."
|
||||
if [ "$(bash scripts/version_info.sh channel)" != beta ]; then
|
||||
echo "Not a beta — nothing to do."
|
||||
echo "is_beta=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
# Fatal on anything but a clean 200/404, as in release.yaml: guessing
|
||||
# "no tag" during an outage would re-cut a published beta.
|
||||
tag_status() {
|
||||
curl -s -o /dev/null -w '%{http_code}' "$TAG_API/git/refs/tags/$1" || echo 000
|
||||
}
|
||||
# A beta of a version that already shipped stable would carry a lower
|
||||
# versionCode than the stable one: nobody could install it over it.
|
||||
case "$(tag_status "v$BASE")" in
|
||||
200)
|
||||
echo "v$BASE already shipped as stable; a beta of it is pointless. Bump the version." >&2
|
||||
exit 1 ;;
|
||||
404) ;;
|
||||
*) echo "Codeberg tag lookup for v$BASE failed — refusing to guess." >&2; exit 1 ;;
|
||||
esac
|
||||
STATUS=$(tag_status "v$VERSION")
|
||||
case "$STATUS" in
|
||||
200)
|
||||
echo "Tag v$VERSION already exists on Codeberg — nothing to release."
|
||||
echo "is_beta=false" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
404)
|
||||
echo "No tag for v$VERSION on Codeberg yet — cutting the beta."
|
||||
echo "is_beta=true" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
*)
|
||||
echo "Codeberg tag lookup for v$VERSION returned HTTP $STATUS." >&2
|
||||
echo "Refusing to guess: treating this as 'no tag' could re-cut a published beta." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Done only once its Codeberg pre-release carries the APK, so a failed
|
||||
# publish is redone by the next push; refused unless newer than the
|
||||
# latest stable release.
|
||||
GATE=$(bash scripts/release_gate.sh)
|
||||
echo "is_beta=${GATE#cut=}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
beta:
|
||||
needs: detect
|
||||
|
||||
@@ -62,17 +62,6 @@ jobs:
|
||||
|
||||
- name: Resolve version and whether it is a new release
|
||||
id: v
|
||||
env:
|
||||
# Tags are read from Codeberg, which is canonical — deliberately NOT
|
||||
# from the Gitea API this workflow runs on. The Codeberg -> Gitea sync
|
||||
# is a push mirror, i.e. `git push --mirror`, which deletes refs the
|
||||
# source does not have. A tag minted here on Gitea is therefore wiped
|
||||
# by the next sync (Codeberg does not have it yet) and only reappears
|
||||
# once the tag push at the end of this workflow propagates back.
|
||||
# Asking Gitea inside that window would report "no tag" for a release
|
||||
# that already shipped, and cut it a second time.
|
||||
# Public repo, so this read needs no token.
|
||||
TAG_API: https://codeberg.org/api/v1/repos/jlmakiola/agendula
|
||||
run: |
|
||||
set -e
|
||||
# versionName -> versionCode, channel and the pre-release flag (set
|
||||
@@ -94,30 +83,11 @@ jobs:
|
||||
echo "versionName $VERSION on main is a beta. Set the stable version before merging to main." >&2
|
||||
exit 1
|
||||
fi
|
||||
# A tag for this version already existing means the release shipped on
|
||||
# an earlier push; do nothing. Absent => this merge cuts the release.
|
||||
#
|
||||
# Anything other than a clean 200/404 is treated as fatal rather than
|
||||
# as "no tag". A Codeberg outage or a network blip would otherwise
|
||||
# read as absent and re-cut a release that has already shipped —
|
||||
# republishing to F-Droid. Failing here is recoverable; a duplicate
|
||||
# release is not.
|
||||
STATUS=$(curl -s -o /dev/null -w '%{http_code}' "$TAG_API/git/refs/tags/v$VERSION" || echo 000)
|
||||
case "$STATUS" in
|
||||
200)
|
||||
echo "Tag v$VERSION already exists on Codeberg — nothing to release."
|
||||
echo "is_release=false" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
404)
|
||||
echo "No tag for v$VERSION on Codeberg yet — cutting the release."
|
||||
echo "is_release=true" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
*)
|
||||
echo "Codeberg tag lookup for v$VERSION returned HTTP $STATUS." >&2
|
||||
echo "Refusing to guess: treating this as 'no tag' could re-cut a shipped release." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Tags are read from Codeberg, the canonical forge, by exact name: its
|
||||
# git/refs/tags API matches by prefix, so v1.1.0-beta.1 would read as
|
||||
# v1.1.0. A lookup error is fatal rather than read as "no tag".
|
||||
GATE=$(bash scripts/release_gate.sh)
|
||||
echo "is_release=${GATE#cut=}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Before a single Gradle task runs: F-Droid truncates the in-client
|
||||
# changelog, so an over-long one would reach users cut off mid-sentence.
|
||||
|
||||
+7
-5
@@ -112,9 +112,11 @@ and to the stable release.
|
||||
2. **Optionally verify it on a device** with `scripts/verify-release.sh`, as for
|
||||
a stable release.
|
||||
3. **Push the branch to Codeberg.** When it reaches Gitea, `beta.yaml` sees a
|
||||
beta version without a tag, runs the unit tests, builds and signs the APK,
|
||||
creates the `vX.Y.Z-beta.1` tag + a Gitea pre-release (with the R8 mapping)
|
||||
and publishes the **Codeberg pre-release** with the APK + `.sha256`.
|
||||
beta whose Codeberg pre-release doesn't carry its APK yet, runs the unit
|
||||
tests, builds and signs the APK, creates the `vX.Y.Z-beta.1` tag + a Gitea
|
||||
pre-release (with the R8 mapping) and publishes the **Codeberg
|
||||
pre-release** with the APK + `.sha256`. If that publish fails part-way, the
|
||||
next push of the branch redoes it.
|
||||
4. **Next round:** bump to `-beta.2` (and its `versionCode`) and push again.
|
||||
5. **Going stable:** set `versionName = "X.Y.Z"` and its `versionCode`
|
||||
(`1.1.0` → `1010099`), then continue from step 2 of
|
||||
@@ -130,8 +132,8 @@ Who gets a beta:
|
||||
- **Play** never.
|
||||
|
||||
Guards: a beta version can't reach `main` (CI fails the PR, and `release.yaml`'s
|
||||
`detect` refuses one as a backstop), `beta.yaml` refuses a beta of a version
|
||||
that already shipped stable, and betas start at 1.1.0 (the 1.0.x codes have no
|
||||
`detect` refuses one as a backstop), `beta.yaml` refuses a beta that isn't
|
||||
newer than the latest stable release, and betas start at 1.1.0 (the 1.0.x codes have no
|
||||
room below them).
|
||||
|
||||
---
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7083b89563e7ce20943037b8cd2b8cc2/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/060bbb778a1f55ea705fdebd2ccfeab9/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d09679dc60fe5aa05ef7d03efdefac20/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ed4e3bf2f5e7c5d9aabc4cbd8acd555e/redirect
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-aarch64-b1163.116.tar.gz
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-x64-b1163.116.tar.gz
|
||||
toolchainUrl.LINUX.AARCH64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-aarch64-b1163.116.tar.gz
|
||||
toolchainUrl.LINUX.X86_64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-x64-b1163.116.tar.gz
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-osx-aarch64-b1163.116.tar.gz
|
||||
toolchainUrl.MAC_OS.X86_64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-osx-x64-b1163.116.tar.gz
|
||||
toolchainUrl.UNIX.AARCH64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-aarch64-b1163.116.tar.gz
|
||||
toolchainUrl.UNIX.X86_64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-linux-x64-b1163.116.tar.gz
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-windows-aarch64-b1163.116.tar.gz
|
||||
toolchainUrl.WINDOWS.X86_64=https\://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.11-windows-x64-b1163.116.tar.gz
|
||||
toolchainVendor=JETBRAINS
|
||||
toolchainVersion=21
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# Publish TAG on Codeberg, which is canonical for tags and releases, with the
|
||||
# signed APK and its SHA-256 checksum attached: the direct-download channel
|
||||
# that Obtainium follows. Shared by .gitea/workflows/release.yaml (stable) and
|
||||
# beta.yaml (pre-release). Run from the repo checkout: it pushes the tag.
|
||||
# Publishes TAG on Codeberg with the signed APK and its SHA-256 attached.
|
||||
# Upserts, so re-runs are safe. A missing TOKEN skips a stable release but fails
|
||||
# a pre-release, where Codeberg is the only channel.
|
||||
#
|
||||
# Codeberg push-mirrors branches and tags to Gitea, but releases aren't git
|
||||
# objects and don't sync in either direction, so this pushes the tag straight
|
||||
# to Codeberg and creates the release over the API. Skips cleanly when TOKEN is
|
||||
# unset; fails loudly on anything else (see release.yaml for why).
|
||||
#
|
||||
# Env:
|
||||
# TOKEN CODEBERG_RELEASE_TOKEN (write:repository); empty = skip
|
||||
# API https://codeberg.org/api/v1/repos/<owner>/<repo>
|
||||
# TAG, SHA vX.Y.Z[-beta.N] and the commit it marks
|
||||
# PRERELEASE true | false
|
||||
# NOTES_FILE release notes (scripts/release_notes.sh)
|
||||
# APK the signed release APK
|
||||
# Env: TOKEN, API (.../api/v1/repos/<owner>/<repo>), TAG, SHA, PRERELEASE,
|
||||
# NOTES_FILE, APK
|
||||
set -euo pipefail
|
||||
if [ -z "${TOKEN:-}" ]; then
|
||||
if [ "${PRERELEASE:-}" = true ]; then
|
||||
echo "CODEBERG_RELEASE_TOKEN not set — a pre-release has nowhere else to go." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "CODEBERG_RELEASE_TOKEN not set — skipping Codeberg publish."
|
||||
exit 0
|
||||
fi
|
||||
@@ -32,16 +25,8 @@ ASSET_SUM="${ASSET_APK}.sha256"
|
||||
cp "$APK" "$WORK/$ASSET_APK"
|
||||
( cd "$WORK" && sha256sum "$ASSET_APK" > "$ASSET_SUM" )
|
||||
|
||||
# Push the tag to Codeberg ourselves. Under Codeberg-canonical the mirror runs
|
||||
# Codeberg -> Gitea, so waiting for a tag to arrive from Gitea (what 0.3.2 did)
|
||||
# would wait forever. The tag minted on Gitea is in fact *deleted* by the next
|
||||
# mirror sync until Codeberg has it, so pushing it here is what makes it
|
||||
# durable on both forges.
|
||||
#
|
||||
# Pushing the ref first and creating the release with NO target_commitish is
|
||||
# deliberate: a release POST carrying a target_commitish for a commit or tag
|
||||
# Codeberg hasn't received yet is what produced the empty-bodied 500s.
|
||||
# Attaching to a ref that already exists doesn't need the API to write one.
|
||||
# Push the tag first and create the release without target_commitish: a POST
|
||||
# naming a commit Codeberg hasn't received yet 500s.
|
||||
HOST=${API#https://}; HOST=${HOST%%/*}
|
||||
REPO=${API#*/repos/}
|
||||
git tag -f "$TAG" "$SHA"
|
||||
@@ -59,38 +44,37 @@ print(json.dumps({
|
||||
}))
|
||||
PY
|
||||
|
||||
# Create (or update) the release. Codeberg 500s on a POST/GET against a tag it
|
||||
# has only just received (the release request outruns the indexing of the ref
|
||||
# pushed a moment ago), so a single attempt can fail even though the very same
|
||||
# call succeeds seconds later. Retry with backoff, and PATCH in place if a
|
||||
# release already exists (re-run safe). A 5xx body still exits curl 0, so the
|
||||
# loop, not `set -e`, controls the flow.
|
||||
# Codeberg 500s on a freshly pushed tag for a few seconds, hence the retries.
|
||||
ID=""
|
||||
for attempt in 1 2 3 4 5 6; do
|
||||
EXIST=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" | jq -r '.id // empty' 2>/dev/null || true)
|
||||
if [ -n "$EXIST" ]; then
|
||||
curl -s -o /dev/null -w "release PATCH HTTP %{http_code}\n" -X PATCH \
|
||||
CODE=$(curl -s -o /dev/null -w '%{http_code}' -X PATCH \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d @"$WORK/payload.json" "$API/releases/$EXIST"
|
||||
ID="$EXIST"; break
|
||||
fi
|
||||
CODE=$(curl -s -o "$WORK/response.json" -w "%{http_code}" -X POST \
|
||||
-d @"$WORK/payload.json" "$API/releases/$EXIST" || echo 000)
|
||||
echo "release PATCH HTTP $CODE"
|
||||
if [ "$CODE" = 200 ]; then ID="$EXIST"; break; fi
|
||||
else
|
||||
CODE=$(curl -s -o "$WORK/response.json" -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d @"$WORK/payload.json" "$API/releases")
|
||||
-d @"$WORK/payload.json" "$API/releases" || echo 000)
|
||||
echo "release POST attempt $attempt HTTP $CODE"
|
||||
ID=$(jq -r '.id // empty' "$WORK/response.json" 2>/dev/null || true)
|
||||
[ -n "$ID" ] && break
|
||||
fi
|
||||
sleep $((attempt * 10))
|
||||
done
|
||||
if [ -z "$ID" ]; then echo "Could not resolve Codeberg release id after retries." >&2; exit 1; fi
|
||||
if [ -z "$ID" ]; then echo "Could not create or update the Codeberg release." >&2; exit 1; fi
|
||||
|
||||
# Attach APK + checksum, replacing any prior asset of the same name.
|
||||
for A in "$ASSET_APK" "$ASSET_SUM"; do
|
||||
OLD=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/$ID/assets" \
|
||||
| jq -r --arg n "$A" '.[] | select(.name==$n) | .id')
|
||||
[ -n "$OLD" ] && curl -s -X DELETE -H "Authorization: token $TOKEN" "$API/releases/$ID/assets/$OLD" >/dev/null || true
|
||||
curl -s -X POST -H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@$WORK/$A" \
|
||||
"$API/releases/$ID/assets?name=$A" -o /dev/null -w "asset $A HTTP %{http_code}\n"
|
||||
| jq -r --arg n "$A" '.[]? | select(.name==$n) | .id' 2>/dev/null || true)
|
||||
for O in $OLD; do
|
||||
curl -s -o /dev/null -X DELETE -H "Authorization: token $TOKEN" "$API/releases/$ID/assets/$O" || true
|
||||
done
|
||||
CODE=$(curl -s -o /dev/null -w '%{http_code}' -X POST -H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@$WORK/$A" "$API/releases/$ID/assets?name=$A" || echo 000)
|
||||
echo "asset $A HTTP $CODE"
|
||||
if [ "$CODE" != 201 ]; then echo "Uploading $A failed." >&2; exit 1; fi
|
||||
done
|
||||
echo "Published $TAG to Codeberg."
|
||||
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# Decides whether the committed version still needs publishing; prints cut=true|false.
|
||||
#
|
||||
# stable: no vX.Y.Z tag on Codeberg yet.
|
||||
# beta: its Codeberg pre-release doesn't carry the APK yet, so a failed
|
||||
# publish is redone by the next push. Refused unless it is newer than
|
||||
# every shipped stable release.
|
||||
#
|
||||
# Fails on any lookup error rather than guessing.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # repo root
|
||||
|
||||
REPO=${REPO:-jlmakiola/agendula}
|
||||
VERSION=$(bash scripts/version_info.sh version)
|
||||
BASE=$(bash scripts/version_info.sh base_version)
|
||||
CHANNEL=$(bash scripts/version_info.sh channel)
|
||||
|
||||
# Exact tag names. The Codeberg git/refs/tags/<name> API matches by prefix.
|
||||
TAGS=$(git ls-remote --tags --refs "https://codeberg.org/$REPO.git" | sed 's#.*refs/tags/##')
|
||||
|
||||
if [ "$CHANNEL" = stable ]; then
|
||||
if grep -qxF "v$VERSION" <<<"$TAGS"; then
|
||||
echo "Tag v$VERSION already exists on Codeberg — nothing to release." >&2
|
||||
echo "cut=false"
|
||||
else
|
||||
echo "No tag for v$VERSION on Codeberg yet — cutting the release." >&2
|
||||
echo "cut=true"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LATEST=$(grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' <<<"$TAGS" | sed 's/^v//' | sort -V | tail -n1 || true)
|
||||
if [ -n "$LATEST" ] && [ "$(printf '%s\n%s\n' "$BASE" "$LATEST" | sort -V | tail -n1)" = "$LATEST" ]; then
|
||||
echo "Beta $VERSION is not newer than the shipped stable $LATEST — bump the version." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ASSET="agendula_v${VERSION}.apk"
|
||||
BODY=$(mktemp); trap 'rm -f "$BODY"' EXIT
|
||||
STATUS=$(curl -s -o "$BODY" -w '%{http_code}' "https://codeberg.org/api/v1/repos/$REPO/releases/tags/v$VERSION" || echo 000)
|
||||
case "$STATUS" in
|
||||
200)
|
||||
if grep -qF "\"name\":\"$ASSET\"" "$BODY"; then
|
||||
echo "Pre-release v$VERSION already carries $ASSET — nothing to do." >&2
|
||||
echo "cut=false"
|
||||
else
|
||||
echo "Pre-release v$VERSION exists without $ASSET — publishing it again." >&2
|
||||
echo "cut=true"
|
||||
fi
|
||||
;;
|
||||
404)
|
||||
echo "No pre-release for v$VERSION yet — cutting the beta." >&2
|
||||
echo "cut=true"
|
||||
;;
|
||||
*)
|
||||
echo "Codeberg release lookup for v$VERSION returned HTTP $STATUS — refusing to guess." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -29,12 +29,12 @@ NAME=$(grep -oP 'versionName\s*=\s*"\K[^"]+' "$GRADLE" || true)
|
||||
COMMITTED=$(grep -oP 'versionCode\s*=\s*\K[0-9]+' "$GRADLE" || true)
|
||||
[ -n "$NAME" ] || { echo "No versionName in $GRADLE" >&2; exit 1; }
|
||||
|
||||
if [[ ! "$NAME" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-beta\.([0-9]+))?$ ]]; then
|
||||
if [[ ! "$NAME" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-beta\.([1-9][0-9]*))?$ ]]; then
|
||||
echo "versionName '$NAME' is neither X.Y.Z nor X.Y.Z-beta.N" >&2
|
||||
exit 1
|
||||
fi
|
||||
MAJOR=$((10#${BASH_REMATCH[1]})); MINOR=$((10#${BASH_REMATCH[2]})); PATCH=$((10#${BASH_REMATCH[3]}))
|
||||
BETA=${BASH_REMATCH[5]:+$((10#${BASH_REMATCH[5]}))}
|
||||
MAJOR=${BASH_REMATCH[1]}; MINOR=${BASH_REMATCH[2]}; PATCH=${BASH_REMATCH[3]}
|
||||
BETA=${BASH_REMATCH[5]}
|
||||
BASE="$MAJOR.$MINOR.$PATCH"
|
||||
|
||||
if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then
|
||||
|
||||
Reference in New Issue
Block a user