@@ -4,6 +4,14 @@ name: Test build
44# Les APK sortent en artifacts du run (onglet Actions → run → section Artifacts).
55# L'OTA interroge /releases/latest, qui ignore artifacts, drafts et prereleases :
66# ce workflow ne peut donc PAS perturber les mises à jour des utilisateurs.
7+ #
8+ # NOMMAGE — la version dérive de la DERNIÈRE beta publiée : "2.6.6-beta.13.test.42".
9+ # Ce format n'est pas cosmétique, il conditionne l'OTA du testeur :
10+ # • il est POSTÉRIEUR à beta.13 (plus d'identifiants à préfixe égal) → s'installe par-dessus ;
11+ # • il reste ANTÉRIEUR à beta.14 (13 < 14 au 2ᵉ identifiant) → la prochaine beta publique est
12+ # toujours proposée.
13+ # ⚠️ Ne PAS simplifier en "2.6.6-test.42" : "test" > "beta" alphabétiquement, la beta suivante
14+ # paraîtrait alors plus ancienne et ne serait JAMAIS proposée.
715on :
816 workflow_dispatch :
917 inputs :
@@ -38,15 +46,49 @@ jobs:
3846 uses : gradle/actions/setup-gradle@v4
3947
4048 - name : Decode platform keystore
41- if : ${{ env.MG4_KEYSTORE_BASE64 != '' }}
4249 run : |
50+ # Sans "if:" : un secret absent sautait l'étape en silence et produisait un APK NON
51+ # signé, impossible à installer par-dessus une version signée — et sans le dire.
52+ if [ -z "$MG4_KEYSTORE_BASE64" ]; then
53+ echo "::error::MG4_KEYSTORE_BASE64 absent : l'APK de test serait non signé."
54+ exit 1
55+ fi
4356 printf '%s' "$MG4_KEYSTORE_BASE64" | tr -d '[:space:]' | base64 -d > "$RUNNER_TEMP/platform.keystore"
4457 if [ "$(head -c1 "$RUNNER_TEMP/platform.keystore" | od -An -tx1 | tr -d ' ')" != "30" ]; then
4558 echo "::error::MG4_KEYSTORE_BASE64 est invalide. Recréer le secret avec : base64 -w0 platform.keystore"
4659 exit 1
4760 fi
4861 echo "MG4_KEYSTORE=$RUNNER_TEMP/platform.keystore" >> "$GITHUB_ENV"
4962
63+ # Reprend le suffixe de la dernière prerelease dont le cœur numérique correspond au
64+ # versionName courant. Cœur différent = la version a été montée depuis, on repart de
65+ # "beta.0" plutôt que d'hériter d'un numéro qui ne veut plus rien dire.
66+ - name : Compute version from last beta
67+ id : ver
68+ env :
69+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
70+ run : |
71+ set -euo pipefail
72+ BASE=$(sed -n 's/.*versionName = "\([^"]*\)".*/\1/p' app/build.gradle.kts | head -1)
73+ if [ -z "$BASE" ]; then
74+ echo "::error::versionName introuvable dans app/build.gradle.kts"; exit 1
75+ fi
76+ LAST=$(gh api "repos/$GITHUB_REPOSITORY/releases?per_page=50" \
77+ | jq -r '.[] | select(.prerelease==true) | .tag_name' \
78+ | sed 's/^v//' \
79+ | awk -v base="$BASE" '{ c=$0; sub(/-.*/,"",c); if (c==base) { print; exit } }')
80+ if [ -n "$LAST" ]; then
81+ PRE="${LAST#$BASE-}"
82+ echo "Dernière beta de $BASE : $LAST"
83+ else
84+ PRE="beta.0"
85+ echo "Aucune beta pour $BASE → repli sur beta.0"
86+ fi
87+ SUFFIX="-${PRE}.test.${{ github.run_number }}"
88+ echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT"
89+ echo "full=${BASE}${SUFFIX}" >> "$GITHUB_OUTPUT"
90+ echo "Version de test : ${BASE}${SUFFIX}"
91+
5092 - name : Build APK(s)
5193 env :
5294 MG4_KEYSTORE_PASSWORD : ${{ secrets.MG4_KEYSTORE_PASSWORD }}
@@ -65,31 +107,41 @@ jobs:
65107 offline) TASKS="assembleOffline$SUFFIX" ;;
66108 esac
67109 echo "Tâches : $TASKS"
68- ./gradlew $TASKS --no-daemon
110+ ./gradlew $TASKS --no-daemon \
111+ -Pmg4.versionSuffix='${{ steps.ver.outputs.suffix }}'
69112
70113 - name : Collect APKs
71114 run : |
72115 mkdir -p dist
73116 find app/build/outputs/apk -name "*.apk" -exec cp {} dist/ \;
74117 ls -la dist/
75118
76- # Affiche les schémas de signature réellement posés (v1 / v2 / v3) et l'empreinte du
77- # certificat. Permet de contrôler ce que produit VRAIMENT la CI, sans installer l'APK.
78- - name : Signature report
119+ # /!\ --min-sdk-version 23 est OBLIGATOIRE pour que ce rapport dise la vérité : sans lui,
120+ # apksigner prend le minSdk de l'APK (28), ne vérifie qu'en v3, et affiche
121+ # "Verified using v1 scheme: false" sur un APK qui CONTIENT bien une signature v1.
122+ - name : Verify signature schemes
79123 run : |
80124 APKSIGNER=$(ls "$ANDROID_SDK_ROOT"/build-tools/*/apksigner | sort -V | tail -1)
81- echo "apksigner : $APKSIGNER"
82125 for f in dist/*.apk; do
83126 echo "── $(basename "$f") ──"
84- "$APKSIGNER" verify --print-certs -v "$f" 2>&1 \
85- | grep -E 'Verified using v[0-9]|certificate SHA-256 digest' || echo " (non vérifiable)"
127+ "$APKSIGNER" verify --print-certs -v --min-sdk-version 23 "$f" \
128+ | grep -E 'Verified using v[0-9]|certificate SHA-256 digest'
129+ # Présence RÉELLE de la v1, indépendamment de ce qu'apksigner choisit de vérifier :
130+ # sans elle, l'app refuse l'installation (getPackageArchiveInfo ne lit aucun
131+ # certificat sur AAOS 9). Autant casser ici plutôt que de le découvrir sur la voiture.
132+ if ! unzip -l "$f" | grep -qE 'META-INF/.*[.](SF|RSA|DSA|EC)$'; then
133+ echo "::error::$(basename "$f") n a PAS de signature v1 (JAR)"
134+ exit 1
135+ fi
136+ echo " v1 (JAR) presente : OUI"
137+ echo " sha256 : $(sha256sum "$f" | cut -d' ' -f1)"
86138 echo
87139 done
88140
89141 - name : Upload APKs (artifacts, PAS une release)
90142 uses : actions/upload-artifact@v4
91143 with :
92- name : mg4control-test- ${{ inputs.variant }}-${{ inputs.build_type }}-${{ github.run_number }}
144+ name : mg4control-${{ steps.ver.outputs.full }}-${{ inputs.variant }}-${{ inputs.build_type }}
93145 path : dist/*.apk
94146 retention-days : 14
95147 if-no-files-found : error
0 commit comments