Repository navigation
147 lines (136 loc) · 6.33 KB
/
Copy pathtest-build.yml
File metadata and controls
147 lines (136 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
name: Test build
# Build de test signé par la clé plateforme, SANS publication dans les Releases.
# Les APK sortent en artifacts du run (onglet Actions → run → section Artifacts).
# L'OTA interroge /releases/latest, qui ignore artifacts, drafts et prereleases :
# ce workflow ne peut donc PAS perturber les mises à jour des utilisateurs.
#
# NOMMAGE — la version dérive de la DERNIÈRE beta publiée : "2.6.6-beta.13.test.42".
# Ce format n'est pas cosmétique, il conditionne l'OTA du testeur :
# • il est POSTÉRIEUR à beta.13 (plus d'identifiants à préfixe égal) → s'installe par-dessus ;
# • il reste ANTÉRIEUR à beta.14 (13 < 14 au 2ᵉ identifiant) → la prochaine beta publique est
# toujours proposée.
# ⚠️ Ne PAS simplifier en "2.6.6-test.42" : "test" > "beta" alphabétiquement, la beta suivante
# paraîtrait alors plus ancienne et ne serait JAMAIS proposée.
on:
workflow_dispatch:
inputs:
variant:
description: "Variante à construire"
type: choice
options: [both, online, offline]
default: both
build_type:
description: "Type de build"
type: choice
options: [release, debug]
default: release
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
env:
MG4_KEYSTORE_BASE64: ${{ secrets.MG4_KEYSTORE_BASE64 }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Decode platform keystore
run: |
# Sans "if:" : un secret absent sautait l'étape en silence et produisait un APK NON
# signé, impossible à installer par-dessus une version signée — et sans le dire.
if [ -z "$MG4_KEYSTORE_BASE64" ]; then
echo "::error::MG4_KEYSTORE_BASE64 absent : l'APK de test serait non signé."
exit 1
fi
printf '%s' "$MG4_KEYSTORE_BASE64" | tr -d '[:space:]' | base64 -d > "$RUNNER_TEMP/platform.keystore"
if [ "$(head -c1 "$RUNNER_TEMP/platform.keystore" | od -An -tx1 | tr -d ' ')" != "30" ]; then
echo "::error::MG4_KEYSTORE_BASE64 est invalide. Recréer le secret avec : base64 -w0 platform.keystore"
exit 1
fi
echo "MG4_KEYSTORE=$RUNNER_TEMP/platform.keystore" >> "$GITHUB_ENV"
# Reprend le suffixe de la dernière prerelease dont le cœur numérique correspond au
# versionName courant. Cœur différent = la version a été montée depuis, on repart de
# "beta.0" plutôt que d'hériter d'un numéro qui ne veut plus rien dire.
- name: Compute version from last beta
id: ver
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
BASE=$(sed -n 's/.*versionName = "\([^"]*\)".*/\1/p' app/build.gradle.kts | head -1)
if [ -z "$BASE" ]; then
echo "::error::versionName introuvable dans app/build.gradle.kts"; exit 1
fi
LAST=$(gh api "repos/$GITHUB_REPOSITORY/releases?per_page=50" \
| jq -r '.[] | select(.prerelease==true) | .tag_name' \
| sed 's/^v//' \
| awk -v base="$BASE" '{ c=$0; sub(/-.*/,"",c); if (c==base) { print; exit } }')
if [ -n "$LAST" ]; then
PRE="${LAST#$BASE-}"
echo "Dernière beta de $BASE : $LAST"
else
PRE="beta.0"
echo "Aucune beta pour $BASE → repli sur beta.0"
fi
SUFFIX="-${PRE}.test.${{ github.run_number }}"
echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT"
echo "full=${BASE}${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "Version de test : ${BASE}${SUFFIX}"
- name: Build APK(s)
env:
MG4_KEYSTORE_PASSWORD: ${{ secrets.MG4_KEYSTORE_PASSWORD }}
MG4_KEY_ALIAS: ${{ secrets.MG4_KEY_ALIAS }}
MG4_KEY_PASSWORD: ${{ secrets.MG4_KEY_PASSWORD }}
run: |
chmod +x gradlew
# "release" → assembleOnlineRelease ; "debug" → assembleOnlineDebug
case "${{ inputs.build_type }}" in
release) SUFFIX="Release" ;;
debug) SUFFIX="Debug" ;;
esac
case "${{ inputs.variant }}" in
both) TASKS="assembleOnline$SUFFIX assembleOffline$SUFFIX" ;;
online) TASKS="assembleOnline$SUFFIX" ;;
offline) TASKS="assembleOffline$SUFFIX" ;;
esac
echo "Tâches : $TASKS"
./gradlew $TASKS --no-daemon \
-Pmg4.versionSuffix='${{ steps.ver.outputs.suffix }}'
- name: Collect APKs
run: |
mkdir -p dist
find app/build/outputs/apk -name "*.apk" -exec cp {} dist/ \;
ls -la dist/
# /!\ --min-sdk-version 23 est OBLIGATOIRE pour que ce rapport dise la vérité : sans lui,
# apksigner prend le minSdk de l'APK (28), ne vérifie qu'en v3, et affiche
# "Verified using v1 scheme: false" sur un APK qui CONTIENT bien une signature v1.
- name: Verify signature schemes
run: |
APKSIGNER=$(ls "$ANDROID_SDK_ROOT"/build-tools/*/apksigner | sort -V | tail -1)
for f in dist/*.apk; do
echo "── $(basename "$f") ──"
"$APKSIGNER" verify --print-certs -v --min-sdk-version 23 "$f" \
| grep -E 'Verified using v[0-9]|certificate SHA-256 digest'
# Présence RÉELLE de la v1, indépendamment de ce qu'apksigner choisit de vérifier :
# sans elle, l'app refuse l'installation (getPackageArchiveInfo ne lit aucun
# certificat sur AAOS 9). Autant casser ici plutôt que de le découvrir sur la voiture.
if ! unzip -l "$f" | grep -qE 'META-INF/.*[.](SF|RSA|DSA|EC)$'; then
echo "::error::$(basename "$f") n a PAS de signature v1 (JAR)"
exit 1
fi
echo " v1 (JAR) presente : OUI"
echo " sha256 : $(sha256sum "$f" | cut -d' ' -f1)"
echo
done
- name: Upload APKs (artifacts, PAS une release)
uses: actions/upload-artifact@v4
with:
name: mg4control-${{ steps.ver.outputs.full }}-${{ inputs.variant }}-${{ inputs.build_type }}
path: dist/*.apk
retention-days: 14
if-no-files-found: error