Skip to content

Commit 943e762

Browse files
SliDeeNclaude
andcommitted
CI test build: version derived from last beta + signature hardening
Test builds are now named <lastBeta>.test.<run> (e.g. 2.6.6-beta.16.test.42) so they install over the beta they derive from while still letting the NEXT public beta supersede them. A naive "-test.N" suffix would sort after "beta" alphabetically and silently hide every following beta from the tester. Also: fail loudly when the keystore secret is missing (it used to skip the step and emit an unsigned APK), and verify signature schemes with --min-sdk-version 23 plus a real v1 presence check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent cb5fb29 commit 943e762

1 file changed

Lines changed: 61 additions & 9 deletions

File tree

‎.github/workflows/test-build.yml‎

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
715
on:
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

Comments
 (0)