From c1a4b2723f95da2397293419f6a6e1bc6551671a Mon Sep 17 00:00:00 2001 From: LucaZanni Date: Tue, 11 Aug 2026 08:51:01 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(capacitor-android):=20inietta?= =?UTF-8?q?=20versionName=20e=20versionCode=20da=20package.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Nuovo step "Inject Android version" dopo il sync Capacitor: riscrive versionName e versionCode in android/app/build.gradle prima della build - versionCode derivato come major*10000 + minor*100 + patch, monotono crescente fra release; pre-release e build metadata scartati dal calcolo ma mantenuti nel versionName - Nuovo input opzionale version-code per forzare un valore esplicito - Supporto Groovy e Kotlin DSL; fallisce con diagnostica se la piattaforma manca, la versione non e' semver, minor/patch superano 99 o l'iniezione non produce il valore atteso - Allineata la variante -github, corpo dello step identico Fixes #5 @1h30m --- .gitea/workflows/capacitor-android-github.yml | 85 +++++++++++++++++++ .gitea/workflows/capacitor-android.yml | 85 +++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/.gitea/workflows/capacitor-android-github.yml b/.gitea/workflows/capacitor-android-github.yml index dd003cf..5ddd5db 100644 --- a/.gitea/workflows/capacitor-android-github.yml +++ b/.gitea/workflows/capacitor-android-github.yml @@ -20,6 +20,10 @@ on: description: 'apk (sideload/test) | aab (Play Store)' type: string default: 'apk' + version-code: + description: 'versionCode Android esplicito. Se vuoto viene derivato da package.json: major*10000 + minor*100 + patch' + type: string + default: '' secrets: NPM_TOKEN: required: false @@ -96,6 +100,87 @@ jobs: - name: Sync Capacitor run: npx cap sync android + # La piattaforma Android puo essere generata da 'cap add' (default Capacitor: + # versionName "1.0", versionCode 1) oppure versionata nel repo consumer. + # In entrambi i casi la versione pubblicata deve derivare da package.json, + # unica fonte di verita, altrimenti l'APK/AAB dichiara una versione diversa + # da quella del tag e Play Store rifiuta upload con versionCode non crescente. + - name: Inject Android version + id: android-version + env: + PKG_VERSION: ${{ steps.app-info.outputs.version }} + VERSION_CODE_OVERRIDE: ${{ inputs.version-code }} + run: | + set -euo pipefail + + if [ -f android/app/build.gradle ]; then + GRADLE_FILE="android/app/build.gradle" + KTS=0 + elif [ -f android/app/build.gradle.kts ]; then + GRADLE_FILE="android/app/build.gradle.kts" + KTS=1 + else + echo "::error::Nessun build.gradle in android/app/ — piattaforma Android non generata" + exit 1 + fi + + VERSION_NAME="$PKG_VERSION" + + if [ -n "$VERSION_CODE_OVERRIDE" ]; then + VERSION_CODE="$VERSION_CODE_OVERRIDE" + else + CORE="${PKG_VERSION%%-*}" # scarta il pre-release: 1.2.3-beta.1 -> 1.2.3 + CORE="${CORE%%+*}" # scarta il build metadata: 1.2.3+abc -> 1.2.3 + MAJOR="$(echo "$CORE" | cut -d. -f1)" + MINOR="$(echo "$CORE" | cut -d. -f2)" + PATCH="$(echo "$CORE" | cut -d. -f3)" + MINOR="${MINOR:-0}" + PATCH="${PATCH:-0}" + + case "${MAJOR}${MINOR}${PATCH}" in + ''|*[!0-9]*) + echo "::error::Versione package.json non semver: '$PKG_VERSION'. Passare version-code esplicito." + exit 1 + ;; + esac + + if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then + echo "::error::minor/patch > 99 non rappresentabili ('$PKG_VERSION'). Passare version-code esplicito." + exit 1 + fi + + VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH )) + fi + + if [ "$KTS" -eq 1 ]; then + sed -i -E "s/versionCode[[:space:]]*=[[:space:]]*[0-9]+/versionCode = ${VERSION_CODE}/" "$GRADLE_FILE" + sed -i -E "s/versionName[[:space:]]*=[[:space:]]*\"[^\"]*\"/versionName = \"${VERSION_NAME}\"/" "$GRADLE_FILE" + else + sed -i -E "s/versionCode[[:space:]]+[0-9]+/versionCode ${VERSION_CODE}/" "$GRADLE_FILE" + sed -i -E "s/versionName[[:space:]]+\"[^\"]*\"/versionName \"${VERSION_NAME}\"/" "$GRADLE_FILE" + fi + + # Il sed silenzioso e' peggio di un fallimento: senza questa verifica una + # variazione del template Capacitor produrrebbe build con versione sbagliata. + # Si confrontano i valori estratti, non si rilegge il file con una regex + # costruita sulla versione: '+' e '.' di un semver sono metacaratteri ERE. + # '|| true': senza, pipefail farebbe uscire lo step su un file privo di + # versionCode/versionName, perdendo la diagnostica del blocco sottostante. + ACTUAL_CODE="$(grep -oE 'versionCode[[:space:]]*=?[[:space:]]*[0-9]+' "$GRADLE_FILE" | head -1 | grep -oE '[0-9]+$' || true)" + ACTUAL_NAME="$(grep -oE 'versionName[[:space:]]*=?[[:space:]]*"[^"]*"' "$GRADLE_FILE" | head -1 | cut -d'"' -f2 || true)" + + if [ "$ACTUAL_CODE" != "$VERSION_CODE" ] || [ "$ACTUAL_NAME" != "$VERSION_NAME" ]; then + echo "::error::Iniezione versione fallita in $GRADLE_FILE" + echo " atteso: versionName='${VERSION_NAME}' versionCode=${VERSION_CODE}" + echo " trovato: versionName='${ACTUAL_NAME}' versionCode=${ACTUAL_CODE}" + grep -nE 'versionCode|versionName' "$GRADLE_FILE" || true + exit 1 + fi + + echo "version-name=${VERSION_NAME}" >> $GITHUB_OUTPUT + echo "version-code=${VERSION_CODE}" >> $GITHUB_OUTPUT + echo "Android: versionName=${VERSION_NAME} versionCode=${VERSION_CODE} ($GRADLE_FILE)" + - name: Setup google-services.json if: secrets.GOOGLE_SERVICES_JSON != '' run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json diff --git a/.gitea/workflows/capacitor-android.yml b/.gitea/workflows/capacitor-android.yml index 4610377..e052e86 100644 --- a/.gitea/workflows/capacitor-android.yml +++ b/.gitea/workflows/capacitor-android.yml @@ -20,6 +20,10 @@ on: description: 'apk (sideload/test) | aab (Play Store)' type: string default: 'apk' + version-code: + description: 'versionCode Android esplicito. Se vuoto viene derivato da package.json: major*10000 + minor*100 + patch' + type: string + default: '' secrets: NPM_TOKEN: required: false @@ -96,6 +100,87 @@ jobs: - name: Sync Capacitor run: npx cap sync android + # La piattaforma Android puo essere generata da 'cap add' (default Capacitor: + # versionName "1.0", versionCode 1) oppure versionata nel repo consumer. + # In entrambi i casi la versione pubblicata deve derivare da package.json, + # unica fonte di verita, altrimenti l'APK/AAB dichiara una versione diversa + # da quella del tag e Play Store rifiuta upload con versionCode non crescente. + - name: Inject Android version + id: android-version + env: + PKG_VERSION: ${{ steps.app-info.outputs.version }} + VERSION_CODE_OVERRIDE: ${{ inputs.version-code }} + run: | + set -euo pipefail + + if [ -f android/app/build.gradle ]; then + GRADLE_FILE="android/app/build.gradle" + KTS=0 + elif [ -f android/app/build.gradle.kts ]; then + GRADLE_FILE="android/app/build.gradle.kts" + KTS=1 + else + echo "::error::Nessun build.gradle in android/app/ — piattaforma Android non generata" + exit 1 + fi + + VERSION_NAME="$PKG_VERSION" + + if [ -n "$VERSION_CODE_OVERRIDE" ]; then + VERSION_CODE="$VERSION_CODE_OVERRIDE" + else + CORE="${PKG_VERSION%%-*}" # scarta il pre-release: 1.2.3-beta.1 -> 1.2.3 + CORE="${CORE%%+*}" # scarta il build metadata: 1.2.3+abc -> 1.2.3 + MAJOR="$(echo "$CORE" | cut -d. -f1)" + MINOR="$(echo "$CORE" | cut -d. -f2)" + PATCH="$(echo "$CORE" | cut -d. -f3)" + MINOR="${MINOR:-0}" + PATCH="${PATCH:-0}" + + case "${MAJOR}${MINOR}${PATCH}" in + ''|*[!0-9]*) + echo "::error::Versione package.json non semver: '$PKG_VERSION'. Passare version-code esplicito." + exit 1 + ;; + esac + + if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then + echo "::error::minor/patch > 99 non rappresentabili ('$PKG_VERSION'). Passare version-code esplicito." + exit 1 + fi + + VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH )) + fi + + if [ "$KTS" -eq 1 ]; then + sed -i -E "s/versionCode[[:space:]]*=[[:space:]]*[0-9]+/versionCode = ${VERSION_CODE}/" "$GRADLE_FILE" + sed -i -E "s/versionName[[:space:]]*=[[:space:]]*\"[^\"]*\"/versionName = \"${VERSION_NAME}\"/" "$GRADLE_FILE" + else + sed -i -E "s/versionCode[[:space:]]+[0-9]+/versionCode ${VERSION_CODE}/" "$GRADLE_FILE" + sed -i -E "s/versionName[[:space:]]+\"[^\"]*\"/versionName \"${VERSION_NAME}\"/" "$GRADLE_FILE" + fi + + # Il sed silenzioso e' peggio di un fallimento: senza questa verifica una + # variazione del template Capacitor produrrebbe build con versione sbagliata. + # Si confrontano i valori estratti, non si rilegge il file con una regex + # costruita sulla versione: '+' e '.' di un semver sono metacaratteri ERE. + # '|| true': senza, pipefail farebbe uscire lo step su un file privo di + # versionCode/versionName, perdendo la diagnostica del blocco sottostante. + ACTUAL_CODE="$(grep -oE 'versionCode[[:space:]]*=?[[:space:]]*[0-9]+' "$GRADLE_FILE" | head -1 | grep -oE '[0-9]+$' || true)" + ACTUAL_NAME="$(grep -oE 'versionName[[:space:]]*=?[[:space:]]*"[^"]*"' "$GRADLE_FILE" | head -1 | cut -d'"' -f2 || true)" + + if [ "$ACTUAL_CODE" != "$VERSION_CODE" ] || [ "$ACTUAL_NAME" != "$VERSION_NAME" ]; then + echo "::error::Iniezione versione fallita in $GRADLE_FILE" + echo " atteso: versionName='${VERSION_NAME}' versionCode=${VERSION_CODE}" + echo " trovato: versionName='${ACTUAL_NAME}' versionCode=${ACTUAL_CODE}" + grep -nE 'versionCode|versionName' "$GRADLE_FILE" || true + exit 1 + fi + + echo "version-name=${VERSION_NAME}" >> $GITHUB_OUTPUT + echo "version-code=${VERSION_CODE}" >> $GITHUB_OUTPUT + echo "Android: versionName=${VERSION_NAME} versionCode=${VERSION_CODE} ($GRADLE_FILE)" + - name: Setup google-services.json if: secrets.GOOGLE_SERVICES_JSON != '' run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > android/app/google-services.json