-
Notifications
You must be signed in to change notification settings - Fork 0
151 lines (148 loc) · 7.06 KB
/
Copy pathandroid-release.yml
File metadata and controls
151 lines (148 loc) · 7.06 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
148
149
150
151
name: Android release
on:
workflow_call:
inputs:
version:
type: string
required: true
tag:
type: string
required: true
ref:
type: string
required: true
version-code:
description: Monotonic run number from the release entrypoint
type: string
required: true
secrets:
BF_ANDROID_KEYSTORE_BASE64:
required: true
BF_ANDROID_KEYSTORE_PASSWORD:
required: true
BF_ANDROID_KEY_ALIAS:
required: true
BF_ANDROID_KEY_PASSWORD:
required: true
permissions:
contents: write
jobs:
apk:
# Production credentials only belong to the release entrypoint on trusted refs.
if: >-
github.repository == 'BetterCorp/BetterFrame' &&
(github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
persist-credentials: false
- name: Validate release identity and version
env:
RELEASE_REF: ${{ inputs.ref }}
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_VERSION: ${{ inputs.version }}
RELEASE_RUN: ${{ inputs.version-code }}
VERSION_OFFSET: ${{ vars.BF_ANDROID_VERSION_CODE_OFFSET || '0' }}
CERTIFICATE_SHA256: ${{ vars.BF_ANDROID_CERT_SHA256 }}
run: |
python3 - <<'PY'
import os, re, subprocess
def require(condition, message):
if not condition:
raise SystemExit(message)
require(os.environ['RELEASE_REF'] == os.environ['GITHUB_SHA'], 'Release ref must match triggering commit')
require(subprocess.check_output(['git', 'rev-parse', 'HEAD'], text=True).strip() == os.environ['GITHUB_SHA'], 'Checkout does not match release commit')
version = os.environ['RELEASE_VERSION']
identifier = r'(?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)'
require(re.fullmatch(rf'(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-(alpha|beta|dev)\.{identifier}(\.{identifier})*)?', version), 'Invalid release version')
require(os.environ['RELEASE_TAG'] == 'v' + version, 'Release tag/version mismatch')
require(re.fullmatch(r'[0-9A-Fa-f]{64}', os.environ['CERTIFICATE_SHA256']), 'Configure BF_ANDROID_CERT_SHA256 with the permanent certificate fingerprint')
run, offset = os.environ['RELEASE_RUN'], os.environ['VERSION_OFFSET']
require(re.fullmatch(r'[0-9]+', run) and re.fullmatch(r'[0-9]+', offset), 'Invalid version counter or offset')
require(int(run) == int(os.environ['GITHUB_RUN_NUMBER']), 'Use the release entrypoint run number')
code = int(run) + int(offset)
require(1 <= code <= 2100000000, 'Android versionCode is out of range')
with open(os.environ['GITHUB_ENV'], 'a') as output:
output.write(f'BF_ANDROID_VERSION_CODE={code}\nBF_ANDROID_VERSION_NAME={version}\n')
PY
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- uses: android-actions/setup-android@v3
with:
packages: platform-tools
- uses: dtolnay/rust-toolchain@stable
with:
targets: armv7-linux-androideabi,aarch64-linux-android,x86_64-linux-android
- uses: gradle/actions/setup-gradle@v4
- name: Install Android build dependencies
run: sdkmanager 'platforms;android-36' 'build-tools;36.0.0' 'ndk;27.2.12479018'
- name: Build signed APK and Play bundle
working-directory: client/android
env:
BF_ANDROID_KEYSTORE_BASE64: ${{ secrets.BF_ANDROID_KEYSTORE_BASE64 }}
BF_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.BF_ANDROID_KEYSTORE_PASSWORD }}
BF_ANDROID_KEY_ALIAS: ${{ secrets.BF_ANDROID_KEY_ALIAS }}
BF_ANDROID_KEY_PASSWORD: ${{ secrets.BF_ANDROID_KEY_PASSWORD }}
BF_ANDROID_REQUIRE_SIGNING: 'true'
run: |
set -euo pipefail
umask 077
export BF_ANDROID_KEYSTORE_PATH="$RUNNER_TEMP/betterframe-release.p12"
trap 'rm -f -- "$BF_ANDROID_KEYSTORE_PATH"' EXIT
test -n "$BF_ANDROID_KEYSTORE_BASE64"
printf '%s' "$BF_ANDROID_KEYSTORE_BASE64" | base64 --decode > "$BF_ANDROID_KEYSTORE_PATH"
unset BF_ANDROID_KEYSTORE_BASE64
./gradlew --no-daemon assembleRelease bundleRelease lintRelease
- name: Verify signed APK before publication
env:
CERTIFICATE_SHA256: ${{ vars.BF_ANDROID_CERT_SHA256 }}
run: |
mkdir -p dist/android
cp client/android/app/build/outputs/apk/release/app-release.apk dist/android/betterframe-android.apk
python3 client/android/scripts/verify-apk.py \
--apk dist/android/betterframe-android.apk \
--certificate-sha256 "$CERTIFICATE_SHA256" \
--version-code "$BF_ANDROID_VERSION_CODE" \
--version-name "$BF_ANDROID_VERSION_NAME" \
--apksigner "$ANDROID_HOME/build-tools/36.0.0/apksigner" \
--aapt "$ANDROID_HOME/build-tools/36.0.0/aapt" \
--metadata dist/android/betterframe-android.json
- name: Verify Play bundle
env:
CERTIFICATE_SHA256: ${{ vars.BF_ANDROID_CERT_SHA256 }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release download 1.18.3 --repo google/bundletool --pattern bundletool-all-1.18.3.jar --dir "$RUNNER_TEMP"
echo "a099cfa1543f55593bc2ed16a70a7c67fe54b1747bb7301f37fdfd6d91028e29 $RUNNER_TEMP/bundletool-all-1.18.3.jar" | sha256sum --check
cp client/android/app/build/outputs/bundle/release/app-release.aab dist/android/betterframe-android.aab
python3 client/android/scripts/verify-aab.py \
--bundle dist/android/betterframe-android.aab \
--metadata dist/android/betterframe-android.json \
--bundletool "$RUNNER_TEMP/bundletool-all-1.18.3.jar" \
--certificate-sha256 "$CERTIFICATE_SHA256"
"$ANDROID_HOME/build-tools/36.0.0/zipalign" -c -P 16 4 dist/android/betterframe-android.apk
- name: Preserve verified Play publishing artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: android-play-${{ github.run_id }}
path: |
dist/android/betterframe-android.aab
dist/android/betterframe-android.json
if-no-files-found: error
overwrite: true
retention-days: 30
- name: Attach verified APK and public metadata to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
gh release upload "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
dist/android/betterframe-android.apk dist/android/betterframe-android.aab dist/android/betterframe-android.json --clobber
- name: Remove signing material
if: always()
run: rm -f -- "$RUNNER_TEMP/betterframe-release.p12"