ci(release): make the pipeline prerelease-aware (#80)
Some checks are pending
CI / Unit tests (node --test) (push) Waiting to run
CI / Android unit tests (Kotlin schedule evaluator vectors) (push) Waiting to run
CI / Boot smoke + version check (push) Waiting to run

Tagging a pre-release (e.g. v1.9.0-rc1) was unsafe. Four fixes:

1. bump-version.sh writes a numeric-only x.y.z to tizen/config.xml (strips a
   -rc1/-beta.N suffix) so the .wgt still signs/installs; the full VERSION
   (with the suffix) still drives server/Android/package.json.
2. release.yml flags the GitHub Release --prerelease for a -suffix version
   (keeps it off "Latest" and out of the /releases/latest API).
3. release.yml moves docker :latest only for final releases - a pre-release no
   longer repoints :latest onto untested code.
4. upgrade.sh excludes pre-release tags from its default selection - GNU
   `sort -V` ranks 1.9.0-rc1 above the final 1.9.0, so the unfiltered default
   would silently pick an RC (which then auto-OTAs to field kiosks). An explicit
   `upgrade.sh v1.9.0-rc1` still works.

Verified the strip, tag selection, prerelease/tags logic, and YAML validity in
isolation.

Closes #80

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ScreenTinker 2026-06-12 08:51:20 -05:00 committed by screentinker
parent bd732f4c48
commit 11e339dd89
3 changed files with 39 additions and 10 deletions

View file

@ -62,11 +62,15 @@ jobs:
- name: Resolve version + previous tag
id: ver
run: |
echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT"
VERSION="$(cat VERSION)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
PREV="$(git describe --tags --abbrev=0 "${GITHUB_REF_NAME}^" 2>/dev/null || true)"
echo "prev=$PREV" >> "$GITHUB_OUTPUT"
echo "Releasing ${GITHUB_REF_NAME} (version $(cat VERSION)); previous tag: ${PREV:-<none>}"
# #80: a version carrying a -suffix (e.g. 1.9.0-rc1) is a pre-release.
case "$VERSION" in *-*) PRE=true ;; *) PRE=false ;; esac
echo "prerelease=$PRE" >> "$GITHUB_OUTPUT"
echo "Releasing ${GITHUB_REF_NAME} (version $VERSION, prerelease=$PRE); previous tag: ${PREV:-<none>}"
- name: Build Tizen .wgt (unsigned in CI)
run: |
@ -107,7 +111,11 @@ jobs:
echo " Sign it with your own Samsung certificate (Tizen Studio + a profile that includes"
echo " your TV's DUID) to install, or - easiest - point a Tizen TV browser / URL Launcher"
echo " at \`https://<your-instance>/player\` (no signing needed)."
echo "- Docker image: \`ghcr.io/screentinker/screentinker:${{ steps.ver.outputs.version }}\` (also \`:latest\`)."
if [ "${{ steps.ver.outputs.prerelease }}" = "true" ]; then
echo "- Docker image: \`ghcr.io/screentinker/screentinker:${{ steps.ver.outputs.version }}\` (pre-release - \`:latest\` is NOT moved)."
else
echo "- Docker image: \`ghcr.io/screentinker/screentinker:${{ steps.ver.outputs.version }}\` (also \`:latest\`)."
fi
echo "- \`ScreenTinker.apk\` - signed Android player (attached during release finalization)."
} > RELEASE_NOTES.md
cat RELEASE_NOTES.md
@ -116,7 +124,12 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# #80: pre-release tags publish as a GitHub *pre-release* (not "Latest"),
# which also keeps the /releases/latest API pointing at the last stable.
PRERELEASE_FLAG=""
[ "${{ steps.ver.outputs.prerelease }}" = "true" ] && PRERELEASE_FLAG="--prerelease"
gh release create "${{ steps.ver.outputs.tag }}" \
$PRERELEASE_FLAG \
--title "ScreenTinker ${{ steps.ver.outputs.tag }}" \
--notes-file RELEASE_NOTES.md \
"${TARBALL}" \
@ -129,7 +142,17 @@ jobs:
steps:
- uses: actions/checkout@v6
- id: ver
run: echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT"
run: |
VERSION="$(cat VERSION)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# #80: move :latest only for final releases - a pre-release (1.9.0-rc1) must
# not repoint :latest onto untested code (anyone on :latest pulls it on restart).
TAGS="ghcr.io/screentinker/screentinker:$VERSION"
case "$VERSION" in
*-*) echo "Pre-release $VERSION: :latest will NOT be moved" ;;
*) TAGS="${TAGS}"$'\n'"ghcr.io/screentinker/screentinker:latest" ;;
esac
{ echo "tags<<__EOF__"; printf '%s\n' "$TAGS"; echo "__EOF__"; } >> "$GITHUB_OUTPUT"
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
@ -142,9 +165,7 @@ jobs:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/screentinker/screentinker:${{ steps.ver.outputs.version }}
ghcr.io/screentinker/screentinker:latest
tags: ${{ steps.ver.outputs.tags }}
# TODO (deferred): build + sign the Android APK in CI. Requires the release
# keystore + passwords as encrypted Actions secrets. For now the maintainer

View file

@ -47,7 +47,12 @@ sed -i -E "s/(versionCode[[:space:]]*=[[:space:]]*)[0-9]+/\1$((CODE + 1))/" andr
# has a leading space before version= so the guard below would otherwise hit
# it (issue #77). The leading-space guard still excludes tizen:application
# required_version="..." (that's "...d_version", no preceding space).
sed -i -E "/^<\?xml/! s/([[:space:]]version=\")[0-9][^\"]*(\")/\1${NEW}\2/" tizen/config.xml
# #80: Tizen requires a strictly-numeric x.y.z widget version, so a pre-release
# suffix (e.g. 1.9.0-rc1) is invalid and the .wgt fails to sign/install. Strip
# the suffix for config.xml only - the full VERSION (with -rc1/-beta.N) still
# drives the server/Android/package.json version.
NUMERIC="${NEW%%-*}"
sed -i -E "/^<\?xml/! s/([[:space:]]version=\")[0-9][^\"]*(\")/\1${NUMERIC}\2/" tizen/config.xml
# 5) commit + annotated tag (no push)
git add VERSION server/package.json server/package-lock.json android/app/build.gradle.kts tizen/config.xml

View file

@ -21,8 +21,11 @@ BACKUP_DIR="${BACKUP_DIR:-$APP_DIR/backups}"
echo "==> Fetching tags"
git fetch --tags origin
# Target tag: explicit arg, or the highest semver v* tag.
TARGET="${1:-$(git tag -l 'v*' | sort -V | tail -1)}"
# Target tag: explicit arg, or the highest semver v* tag. #80: exclude pre-release
# tags (-rc/-beta/-alpha) from the default - GNU `sort -V` ranks 1.9.0-rc1 ABOVE the
# final 1.9.0, so an unfiltered default would silently pick an RC. An explicit arg
# still lets you target a pre-release deliberately (scripts/upgrade.sh v1.9.0-rc1).
TARGET="${1:-$(git tag -l 'v*' | grep -vE -- '-(rc|beta|alpha|pre)' | sort -V | tail -1)}"
if [ -z "$TARGET" ] || ! git rev-parse -q --verify "refs/tags/$TARGET^{commit}" >/dev/null; then
echo "ERROR: no such release tag: '${TARGET:-<none found>}'" >&2
exit 1