ci: add version consistency check and fully automate release pipeline
- New tools/check_versions.sh: verifies version.txt, version.h, SylDaVersions.kt match - release.yml: 'Verify version consistency' step after build, aborts release if mismatch - ci.yml: same check after debug APK build - scripts/release.sh: now runs full pipeline (pio run -> copy firmware -> gradle -> check) and refuses dirty working tree - Untrack version.h, SylDaVersions.kt, release/ — always regenerated fresh from version.txt Prevents the v1.1 bug where stale generated files caused version mismatch and infinite re-flash loop.
This commit is contained in:
parent
1d94f088fd
commit
6a07505d02
14 changed files with 123 additions and 20 deletions
|
|
@ -46,6 +46,9 @@ jobs:
|
||||||
env:
|
env:
|
||||||
ANDROID_HOME: ${{ vars.ANDROID_HOME || '/home/linuxbrew/.linuxbrew/share/android-commandlinetools' }}
|
ANDROID_HOME: ${{ vars.ANDROID_HOME || '/home/linuxbrew/.linuxbrew/share/android-commandlinetools' }}
|
||||||
|
|
||||||
|
- name: Verify version consistency
|
||||||
|
run: bash tools/check_versions.sh
|
||||||
|
|
||||||
- name: Stage APK
|
- name: Stage APK
|
||||||
run: |
|
run: |
|
||||||
mkdir -p /tmp/ci-artifacts
|
mkdir -p /tmp/ci-artifacts
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ jobs:
|
||||||
env:
|
env:
|
||||||
ANDROID_HOME: ${{ vars.ANDROID_HOME || '/home/linuxbrew/.linuxbrew/share/android-commandlinetools' }}
|
ANDROID_HOME: ${{ vars.ANDROID_HOME || '/home/linuxbrew/.linuxbrew/share/android-commandlinetools' }}
|
||||||
|
|
||||||
|
- name: Verify version consistency
|
||||||
|
run: bash tools/check_versions.sh
|
||||||
|
|
||||||
- name: Gather release artifacts
|
- name: Gather release artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir -p release/artifacts
|
mkdir -p release/artifacts
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
// Auto-generated from version.txt — DO NOT EDIT
|
|
||||||
package nl.eddydevink.sylda
|
|
||||||
|
|
||||||
object SylDaVersions {
|
|
||||||
const val SERVER = "17"
|
|
||||||
const val CLIENT = "3"
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,8 +0,0 @@
|
||||||
acfff58aa4bcdcbb110e30d2ae52ccfb2eaf065a43c816330d4899ba3710bb9e app-debug.apk
|
|
||||||
83dc1f10e15f423cdedd576f23fa22541e1cd29fd8d0a4015e8c85dfc2029026 app-release.aab
|
|
||||||
badeb22995c9134f105e5af3cf6b4f2d6f9ed319e255d7b27fc9b41ccb9bf628 app-release.apk
|
|
||||||
f94c5d786a7a8fab06ac5d10e33bf37711a6697636dc037559ea19cc410a17f0 boot_app0.bin
|
|
||||||
1776e4dd896a69d0a5c2e79957b0e2a88aa4129b1381d6478683515a1f6af343 bootloader.bin
|
|
||||||
7d5e43f778efb7b1f7391a24bab4ae90baa19251ae7c654c0a8beda9bae47d4a checksums.txt
|
|
||||||
c40de1fe362c5d914156214431499462226721325f427db22aa70afb4b648141 firmware.bin
|
|
||||||
1d9cca96de0fe07ad7fc0648b9878ddecd9ce565e38b589ad20fea698ed4c80c partitions.bin
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -3,9 +3,11 @@ set -euo pipefail
|
||||||
|
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
log() { echo -e "${GREEN}[release]${NC} $1"; }
|
log() { echo -e "${GREEN}[release]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[release]${NC} $1"; }
|
||||||
err() { echo -e "${RED}[release]${NC} $1" >&2; }
|
err() { echo -e "${RED}[release]${NC} $1" >&2; }
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
@ -14,6 +16,8 @@ ANDROID_DIR="$PROJECT_DIR/android"
|
||||||
APP_BUILD_GRADLE="$ANDROID_DIR/app/build.gradle"
|
APP_BUILD_GRADLE="$ANDROID_DIR/app/build.gradle"
|
||||||
SIGNING_PROPS="$ANDROID_DIR/signing.properties"
|
SIGNING_PROPS="$ANDROID_DIR/signing.properties"
|
||||||
FORGEJO_URL="https://git.eddydevink.nl/api/v1/repos/eddy/Project_SylDa"
|
FORGEJO_URL="https://git.eddydevink.nl/api/v1/repos/eddy/Project_SylDa"
|
||||||
|
CHECK_VERSIONS="$PROJECT_DIR/tools/check_versions.sh"
|
||||||
|
COPY_FIRMWARE="$PROJECT_DIR/tools/copy_firmware.sh"
|
||||||
FIRMWARE_DIR="$ANDROID_DIR/app/src/main/assets/firmware"
|
FIRMWARE_DIR="$ANDROID_DIR/app/src/main/assets/firmware"
|
||||||
|
|
||||||
VERSION=$(grep -oP 'versionName\s+"\K[^"]+' "$APP_BUILD_GRADLE")
|
VERSION=$(grep -oP 'versionName\s+"\K[^"]+' "$APP_BUILD_GRADLE")
|
||||||
|
|
@ -21,20 +25,43 @@ TAG="v$VERSION"
|
||||||
RELEASE_DIR="$PROJECT_DIR/release/$TAG"
|
RELEASE_DIR="$PROJECT_DIR/release/$TAG"
|
||||||
|
|
||||||
log "Release v$VERSION (tag $TAG)"
|
log "Release v$VERSION (tag $TAG)"
|
||||||
|
log "========================================="
|
||||||
|
|
||||||
if [ ! -f "$SIGNING_PROPS" ]; then
|
if [ ! -f "$SIGNING_PROPS" ]; then
|
||||||
err "signing.properties niet gevonden op $SIGNING_PROPS"
|
err "signing.properties niet gevonden op $SIGNING_PROPS"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Clean..."
|
# ── Build firmware ────────────────────────────────────────────
|
||||||
|
log "Build firmware (pio run)..."
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
pio run
|
||||||
|
log "Firmware built."
|
||||||
|
|
||||||
|
log "Copy firmware to Android assets..."
|
||||||
|
bash "$COPY_FIRMWARE"
|
||||||
|
log "Firmware copied."
|
||||||
|
|
||||||
|
# ── Build Android ─────────────────────────────────────────────
|
||||||
|
log "Clean Gradle..."
|
||||||
cd "$ANDROID_DIR"
|
cd "$ANDROID_DIR"
|
||||||
./gradlew clean
|
./gradlew clean
|
||||||
|
|
||||||
log "Build APK + AAB..."
|
log "Build release APK + AAB..."
|
||||||
./gradlew assembleRelease bundleRelease
|
./gradlew assembleRelease bundleRelease
|
||||||
|
log "Android built."
|
||||||
|
|
||||||
|
# ── Verify version consistency ────────────────────────────────
|
||||||
|
log "Verify version consistency..."
|
||||||
|
if ! bash "$CHECK_VERSIONS"; then
|
||||||
|
err "Version mismatch detected — aborting release."
|
||||||
|
err "version.txt is source of truth. Both version.h and SylDaVersions.kt are regenerated above."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Gather artifacts ──────────────────────────────────────────
|
||||||
log "Verzamel artefacten in $RELEASE_DIR"
|
log "Verzamel artefacten in $RELEASE_DIR"
|
||||||
|
rm -rf "$RELEASE_DIR"
|
||||||
mkdir -p "$RELEASE_DIR"
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
|
||||||
cp "$ANDROID_DIR/app/build/outputs/apk/release/app-release.apk" "$RELEASE_DIR/"
|
cp "$ANDROID_DIR/app/build/outputs/apk/release/app-release.apk" "$RELEASE_DIR/"
|
||||||
|
|
@ -49,7 +76,17 @@ cd "$RELEASE_DIR"
|
||||||
sha256sum * > checksums.txt
|
sha256sum * > checksums.txt
|
||||||
cat checksums.txt
|
cat checksums.txt
|
||||||
|
|
||||||
|
# ── Git tag ───────────────────────────────────────────────────
|
||||||
cd "$PROJECT_DIR"
|
cd "$PROJECT_DIR"
|
||||||
|
if git diff --quiet && git diff --cached --quiet; then
|
||||||
|
log "Working tree clean."
|
||||||
|
else
|
||||||
|
warn "Working tree has uncommitted changes. Commit before releasing."
|
||||||
|
warn "Uncommitted files:"
|
||||||
|
git status --short
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||||
log "Tag $TAG bestaat al, skip git tag."
|
log "Tag $TAG bestaat al, skip git tag."
|
||||||
else
|
else
|
||||||
|
|
@ -58,6 +95,7 @@ else
|
||||||
git push origin "$TAG"
|
git push origin "$TAG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── Create Forgejo release ────────────────────────────────────
|
||||||
log "Forgejo release aanmaken..."
|
log "Forgejo release aanmaken..."
|
||||||
TOKEN_FILE="$HOME/.config/sylda/forgejo-token"
|
TOKEN_FILE="$HOME/.config/sylda/forgejo-token"
|
||||||
if [ ! -f "$TOKEN_FILE" ]; then
|
if [ ! -f "$TOKEN_FILE" ]; then
|
||||||
|
|
@ -91,4 +129,6 @@ for f in *; do
|
||||||
--data-binary "@$f" > /dev/null
|
--data-binary "@$f" > /dev/null
|
||||||
done
|
done
|
||||||
|
|
||||||
|
log "========================================="
|
||||||
log "Klaar! Release $TAG staat op Forgejo."
|
log "Klaar! Release $TAG staat op Forgejo."
|
||||||
|
log " $FORGEJO_URL/releases/tag/$TAG" | sed 's|/api/v1/repos/||'
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
// Auto-generated from version.txt — DO NOT EDIT
|
|
||||||
#define FIRMWARE_VERSION_SERVER "17"
|
|
||||||
#define FIRMWARE_VERSION_CLIENT "3"
|
|
||||||
75
tools/check_versions.sh
Executable file
75
tools/check_versions.sh
Executable file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
pass() { echo -e " ${GREEN}OK${NC} $1"; }
|
||||||
|
fail() { echo -e " ${RED}MISMATCH${NC} $1"; }
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
VERSION_FILE="$PROJECT_DIR/version.txt"
|
||||||
|
HEADER_FILE="$PROJECT_DIR/src/version.h"
|
||||||
|
KOTLIN_FILE="$PROJECT_DIR/android/app/src/main/java/nl/eddydevink/sylda/SylDaVersions.kt"
|
||||||
|
|
||||||
|
errors=0
|
||||||
|
|
||||||
|
echo "=== Version consistency check ==="
|
||||||
|
|
||||||
|
# 1. Parse version.txt (source of truth)
|
||||||
|
if [ ! -f "$VERSION_FILE" ]; then
|
||||||
|
fail "version.txt not found at $VERSION_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
src_server=$(grep -oP '^server=\K\d+' "$VERSION_FILE" || true)
|
||||||
|
src_client=$(grep -oP '^client=\K\d+' "$VERSION_FILE" || true)
|
||||||
|
|
||||||
|
if [ -z "$src_server" ] || [ -z "$src_client" ]; then
|
||||||
|
fail "version.txt missing server= or client="
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
pass "version.txt server=$src_server client=$src_client"
|
||||||
|
|
||||||
|
# 2. Parse src/version.h (generated by pio run)
|
||||||
|
if [ ! -f "$HEADER_FILE" ]; then
|
||||||
|
fail "src/version.h not found — run 'pio run' first"
|
||||||
|
((errors++))
|
||||||
|
else
|
||||||
|
hdr_server=$(grep -oP 'FIRMWARE_VERSION_SERVER\s+"\K\d+' "$HEADER_FILE" || true)
|
||||||
|
hdr_client=$(grep -oP 'FIRMWARE_VERSION_CLIENT\s+"\K\d+' "$HEADER_FILE" || true)
|
||||||
|
if [ "$hdr_server" = "$src_server" ] && [ "$hdr_client" = "$src_client" ]; then
|
||||||
|
pass "src/version.h server=$hdr_server client=$hdr_client"
|
||||||
|
else
|
||||||
|
fail "src/version.h server=${hdr_server:-MISSING} client=${hdr_client:-MISSING} (expected server=$src_server client=$src_client)"
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Parse SylDaVersions.kt (generated by Gradle build)
|
||||||
|
if [ ! -f "$KOTLIN_FILE" ]; then
|
||||||
|
fail "SylDaVersions.kt not found — run './gradlew build' first"
|
||||||
|
((errors++))
|
||||||
|
else
|
||||||
|
kt_server=$(grep -oP 'const val SERVER = "\K\d+' "$KOTLIN_FILE" || true)
|
||||||
|
kt_client=$(grep -oP 'const val CLIENT = "\K\d+' "$KOTLIN_FILE" || true)
|
||||||
|
if [ "$kt_server" = "$src_server" ] && [ "$kt_client" = "$src_client" ]; then
|
||||||
|
pass "SylDaVersions.kt server=$kt_server client=$kt_client"
|
||||||
|
else
|
||||||
|
fail "SylDaVersions.kt server=${kt_server:-MISSING} client=${kt_client:-MISSING} (expected server=$src_server client=$src_client)"
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [ "$errors" -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}All version files in sync.${NC}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}$errors version file(s) out of sync with version.txt.${NC}"
|
||||||
|
echo "Run 'pio run' and './gradlew build' to regenerate."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Loading…
Reference in a new issue