From 854d795c5d88389cf7f0c245f0df1cf4b10320f2 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 6 Sep 2026 18:57:33 +0200 Subject: [PATCH] fix(release): corrige release.yml pour Forgejo et y attache un APK signe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release.yml datait d'avant la migration vers Forgejo et n'avait jamais ete reteste : refs d'action bares (actions/checkout@v4, softprops/action-gh- release@v2) sans le prefixe URL complet qu'exige ce runner self-hosted (meme contrainte deja rencontree et documentee dans ci.yml). Ajoute aussi ce que #65 attendait reellement : un job build-android-apk (meme recette que le job build-android de ci.yml, issue #64) qui construit et signe l'APK, deduit versionName/versionCode du tag pousse (vX.Y.Z -> versionName X.Y.Z, versionCode majeur*10000+mineur*100+correctif) et l'attache a la Release Forgejo sous un nom de fichier stable (batchcooking.apk) via softprops/action-gh-release. C'est ce nom stable qui permet a /releases/latest/download/batchcooking.apk (page d'accueil, #65) de toujours pointer vers la derniere release sans jamais changer de lien. build.gradle : versionCode/versionName deviennent surchargeables via -PandroidVersionCode/-PandroidVersionName (defaut inchange : 1 / "1.0" pour tout build qui ne passe pas ces proprietes, comme le job build-android existant de ci.yml sur un simple push main). Duplique le job de build Android plutot que de factoriser en workflow_call reutilisable — le support des workflows reutilisables sur ce runner Forgejo/act self-hoste n'est pas verifie, et cette recette de ~15 lignes est deja eprouvee telle quelle dans ci.yml ; pas la peine de risquer une nouvelle surprise de compatibilite pour economiser un peu de duplication. Non teste de bout en bout dans cette PR : release.yml ne se declenche que sur un vrai tag pousse (jamais sur une simple branche/PR), et pousser un tag ici declencherait potentiellement un vrai redeploiement Portainer en production si PORTAINER_WEBHOOK_URL est deja configure — a tester deliberement avec l'utilisateur, pas par un tag de test improvise. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/release.yml | 120 +++++++++++++++++++++++++++--- apps/web/android/app/build.gradle | 9 ++- 2 files changed, 115 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e046fa..dc2d7a5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,9 +2,10 @@ name: Release # No image registry involved: Portainer is wired to this repo's Git remote # and builds/redeploys apps/api/Dockerfile itself. This workflow sanity-checks -# that the image actually builds at the tagged commit, publishes a GitHub -# Release, then (best-effort) pings Portainer's deploy webhook so it doesn't -# have to wait for its own polling interval. +# that the image actually builds at the tagged commit, builds+attaches a +# signed Android APK, publishes a Forgejo Release, then (best-effort) pings +# Portainer's deploy webhook so it doesn't have to wait for its own polling +# interval. on: push: tags: ["v*.*.*"] @@ -16,29 +17,124 @@ jobs: sanity-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: https://github.com/actions/checkout@v4 # Build only, no push, no registry — just confirms Portainer will be # able to build this same Dockerfile successfully at this tag before # anyone points it at this ref. - run: docker build -f apps/api/Dockerfile . - github-release: + # Builds the same signed APK as ci.yml's build-android job (issue #64), + # with one difference: the version baked into the APK is derived from the + # tag itself rather than left at build.gradle's default. Duplicated here + # rather than factored into a shared `workflow_call` reusable workflow — + # deliberate: reusable-workflow support on this self-hosted Forgejo/act + # runner is unverified, and this ~15-line recipe is proven working as-is + # in ci.yml; not worth risking a new class of runner-compatibility surprise + # (this repo has already hit several — see ci-forgejo-runner-constraints + # in project memory) to save a little duplication. Keep both copies in + # sync if the Android build steps ever change. + build-android-apk: runs-on: ubuntu-latest - needs: sanity-build steps: - - uses: actions/checkout@v4 + - uses: https://github.com/actions/checkout@v4 - - uses: softprops/action-gh-release@v2 + - uses: pnpm/action-setup@v4 + + - uses: https://github.com/actions/setup-node@v4 with: - # Auto-generated from merged PRs since the previous tag — no - # changelog tooling to maintain, consistent with there being no - # versioning tooling elsewhere in the repo yet. + node-version: 22 + cache: pnpm + + - uses: https://github.com/actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + + - uses: https://github.com/android-actions/setup-android@v3 + + - run: pnpm install --frozen-lockfile + + - name: Build le bundle web pour Capacitor + env: + VITE_API_URL: ${{ secrets.MOBILE_API_URL }} + run: pnpm --filter web build:capacitor + - run: pnpm --filter web exec cap sync android + + - name: Décode le keystore de release + env: + ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + run: echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > apps/web/android/app/release.keystore + + - name: Dérive versionName/versionCode depuis le tag + # GITHUB_REF_NAME = "v1.4.2" pour un tag `v1.4.2` — versionName = + # "1.4.2" (sans le `v`), versionCode = majeur*10000 + mineur*100 + + # correctif (ex. 1.4.2 -> 10402), un entier strictement croissant à + # chaque release comme Android l'exige (jamais réutilisé, jamais + # décroissant) tant que chaque partie reste sous 100 (largement + # suffisant ici). Exposé aux steps suivants via $GITHUB_ENV plutôt + # que recalculé. + run: | + tag="${GITHUB_REF_NAME#v}" + major="$(echo "$tag" | cut -d. -f1)" + minor="$(echo "$tag" | cut -d. -f2)" + patch="$(echo "$tag" | cut -d. -f3)" + # Préfixe 10# : force une lecture en base 10, sinon bash lirait + # un composant à zéro non significatif (ex. "08") comme de + # l'octal invalide et échouerait. + code=$((10#$major * 10000 + 10#$minor * 100 + 10#$patch)) + echo "Version dérivée du tag $GITHUB_REF_NAME : versionName=$tag versionCode=$code" + echo "ANDROID_VERSION_NAME=$tag" >> "$GITHUB_ENV" + echo "ANDROID_VERSION_CODE=$code" >> "$GITHUB_ENV" + + - name: Build l'APK signé + working-directory: apps/web/android + env: + ANDROID_KEYSTORE_PATH: release.keystore + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + run: | + chmod +x ./gradlew + ./gradlew assembleRelease -PandroidVersionName="$ANDROID_VERSION_NAME" -PandroidVersionCode="$ANDROID_VERSION_CODE" + + # Nom de fichier stable, jamais versionné : c'est ce qui permet à la + # page d'accueil (#65) de pointer en permanence vers + # /releases/latest/download/batchcooking.apk sans jamais changer de + # lien d'une release à l'autre. + - name: Renomme l'APK sous un nom stable + run: cp apps/web/android/app/build/outputs/apk/release/app-release.apk batchcooking.apk + + # v4+ exige l'API "Results" de GitHub, non supportée par ce Forgejo + # self-hosted ("GHESNotSupportedError") — v3 (ancienne API Artifacts) + # est la seule utilisable ici, voir ci.yml's build-android pour la + # même contrainte déjà rencontrée. + - uses: https://github.com/actions/upload-artifact@v3 + with: + name: batchcooking.apk + path: batchcooking.apk + + forgejo-release: + runs-on: ubuntu-latest + needs: [sanity-build, build-android-apk] + steps: + - uses: https://github.com/actions/checkout@v4 + + - uses: https://github.com/actions/download-artifact@v3 + with: + name: batchcooking.apk + + - uses: https://github.com/softprops/action-gh-release@v2 + with: + # Auto-généré depuis les PR mergées depuis le tag précédent — pas + # d'outillage de changelog à maintenir, cohérent avec l'absence + # d'outillage de versioning ailleurs dans le repo pour l'instant. generate_release_notes: true + files: batchcooking.apk notify-portainer: runs-on: ubuntu-latest - needs: github-release + needs: forgejo-release steps: - name: Trigger Portainer redeploy # Best-effort: does nothing (and doesn't fail the workflow) until diff --git a/apps/web/android/app/build.gradle b/apps/web/android/app/build.gradle index 239f07c..57c5edd 100644 --- a/apps/web/android/app/build.gradle +++ b/apps/web/android/app/build.gradle @@ -7,8 +7,13 @@ android { applicationId "fr.kyuno.batchcooking" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" + // Surchargeables depuis la CI via `-PandroidVersionCode=... -PandroidVersionName=...` + // (release.yml, dérivés du tag `vX.Y.Z` poussé) — la valeur par + // défaut ci-dessous ne sert qu'aux builds locaux/CI qui ne passent + // pas ces propriétés (Android Studio, le job build-android de + // ci.yml sur un simple push main), jamais à une vraie release. + versionCode (project.hasProperty("androidVersionCode") ? (project.androidVersionCode as Integer) : 1) + versionName (project.hasProperty("androidVersionName") ? project.androidVersionName : "1.0") testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. -- 2.45.2