Skip to content

Commit 05144ee

Browse files
committed
Switch to signed Android release APKs
1 parent b3c7c85 commit 05144ee

2 files changed

Lines changed: 156 additions & 45 deletions

File tree

Lines changed: 154 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,187 @@
11
on:
22
push:
33
tags:
4-
- '*'
4+
- "[0-9]*.[0-9]*.[0-9]*"
5+
6+
permissions:
7+
contents: write
8+
id-token: write
9+
attestations: write
10+
11+
env:
12+
BUILDOZER_BUILD_LOG: buildozer-build.log
13+
BUILDOZER_IMAGE: kivy/buildozer@sha256:fcfb08f4f7beecfdea10e23968c16933b935a2c820e012d8415f318cd8586aab
14+
RUST_TOOLCHAIN: 1.83.0
515

616
jobs:
717
release:
8-
runs-on: ubuntu-latest
18+
runs-on: ubuntu-22.04
919
steps:
10-
- uses: "actions/checkout@v2"
11-
12-
- name: Get the version
13-
id: version
14-
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
20+
- uses: "actions/checkout@v6"
1521

1622
- name: Update version from tag
17-
env:
18-
VERSION: ${{ steps.version.outputs.VERSION }}
1923
run: |
24+
VERSION="${GITHUB_REF_NAME}"
2025
echo "Version is: ${VERSION}"
21-
test -n "${VERSION}"
26+
[[ "${VERSION}" =~ ^[0-9]+[.][0-9]+[.][0-9]+$ ]]
2227
echo "__version__ = \"${VERSION}\"" > pythonhere/version_here.py
2328
2429
- name: Set up Python
25-
uses: "actions/setup-python@v2"
30+
uses: "actions/setup-python@v6"
2631
with:
27-
python-version: "3.8"
32+
python-version: "3.10"
2833
- name: Install dependencies
2934
run: |
3035
python -m pip install --upgrade pip
31-
pip install wheel twine
36+
pip install build twine
3237
- name: Build package
33-
run: python setup.py sdist bdist_wheel
38+
run: python -m build --sdist --wheel
3439
- name: List result
3540
run: ls -l dist
3641
- name: Check distribution
3742
run: python -m twine check dist/*
3843

39-
- name: Build Android APK with Buildozer
40-
id: buildozer
41-
uses: ArtemSBulgakov/buildozer-action@v1
42-
with:
43-
command: buildozer android debug
44-
repository_root: .
45-
workdir: .
46-
buildozer_version: stable
44+
- name: Extract release notes from changelog
45+
run: |
46+
python scripts/release/extract-changelog-section.py "${GITHUB_REF_NAME}"
47+
cat release-notes.rst
4748
48-
- name: List APK building result
49-
run: sudo ls -l "${{ steps.buildozer.outputs.filename }}"
49+
- name: Prepare Android release signing key
50+
env:
51+
ANDROID_RELEASE_KEYSTORE_BASE64: ${{ secrets.ANDROID_RELEASE_KEYSTORE_BASE64 }}
52+
P4A_RELEASE_KEYSTORE_PASSWD: ${{ secrets.P4A_RELEASE_KEYSTORE_PASSWD }}
53+
P4A_RELEASE_KEYALIAS: ${{ secrets.P4A_RELEASE_KEYALIAS }}
54+
P4A_RELEASE_KEYALIAS_PASSWD: ${{ secrets.P4A_RELEASE_KEYALIAS_PASSWD }}
55+
run: |
56+
test -n "${ANDROID_RELEASE_KEYSTORE_BASE64}"
57+
test -n "${P4A_RELEASE_KEYSTORE_PASSWD}"
58+
test -n "${P4A_RELEASE_KEYALIAS}"
59+
test -n "${P4A_RELEASE_KEYALIAS_PASSWD}"
60+
mkdir -p .release-signing/android
61+
printf '%s' "${ANDROID_RELEASE_KEYSTORE_BASE64}" | base64 --decode > .release-signing/android/pythonhere-release.keystore
62+
chmod 600 .release-signing/android/pythonhere-release.keystore
5063
51-
- name: Show APK checksum
52-
run: sha256sum "${{ steps.buildozer.outputs.filename }}"
64+
- name: Prepare Buildozer release spec
65+
run: |
66+
grep -qx 'title = PythonHereDev' buildozer.spec
67+
sed -i 's/^title = PythonHereDev$/title = PythonHere/' buildozer.spec
68+
sed -n '1,8p' buildozer.spec
5369
54-
- name: Create release
55-
id: create_release
56-
uses: actions/create-release@v1
70+
- name: Install Rust
71+
run: |
72+
rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal
73+
rustup default "$RUST_TOOLCHAIN"
74+
rustc --version
75+
cargo --version
76+
77+
- name: Build Android release APK with Buildozer Docker image
78+
shell: bash
5779
env:
58-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80+
P4A_RELEASE_KEYSTORE: /home/user/hostcwd/.release-signing/android/pythonhere-release.keystore
81+
P4A_RELEASE_KEYSTORE_PASSWD: ${{ secrets.P4A_RELEASE_KEYSTORE_PASSWD }}
82+
P4A_RELEASE_KEYALIAS: ${{ secrets.P4A_RELEASE_KEYALIAS }}
83+
P4A_RELEASE_KEYALIAS_PASSWD: ${{ secrets.P4A_RELEASE_KEYALIAS_PASSWD }}
84+
run: |
85+
set -o pipefail
86+
mkdir -p .buildozer bin
87+
sudo chown -R 1000:1000 .buildozer bin
88+
89+
docker run --rm \
90+
-e RUSTUP_HOME=/home/user/.rustup \
91+
-e CARGO_HOME=/home/user/.cargo \
92+
-e PATH=/home/user/.cargo/bin:/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
93+
-e P4A_RELEASE_KEYSTORE="${P4A_RELEASE_KEYSTORE}" \
94+
-e P4A_RELEASE_KEYSTORE_PASSWD="${P4A_RELEASE_KEYSTORE_PASSWD}" \
95+
-e P4A_RELEASE_KEYALIAS="${P4A_RELEASE_KEYALIAS}" \
96+
-e P4A_RELEASE_KEYALIAS_PASSWD="${P4A_RELEASE_KEYALIAS_PASSWD}" \
97+
-v "$PWD":/home/user/hostcwd \
98+
-v "$HOME/.rustup":/home/user/.rustup \
99+
-v "$HOME/.cargo":/home/user/.cargo \
100+
-w /home/user/hostcwd \
101+
"$BUILDOZER_IMAGE" \
102+
android release 2>&1 | tee "$BUILDOZER_BUILD_LOG"
103+
104+
- name: Prepare APK release assets
105+
id: apk
106+
run: |
107+
apk_name="pythonhere-${GITHUB_REF_NAME}-arm64-v8a-release.apk"
108+
apk="$(find bin -name '*.apk' -type f | head -n 1)"
109+
110+
if [[ -z "$apk" ]]; then
111+
echo "::error::No APK found"
112+
exit 1
113+
fi
114+
115+
sudo ls -l "$apk"
116+
sudo cp "$apk" "${apk_name}"
117+
sudo chown "$(id -u):$(id -g)" "${apk_name}"
118+
sha256sum "${apk_name}" > "${apk_name}.sha256"
119+
echo "filename=${apk_name}" >> "$GITHUB_OUTPUT"
120+
echo "sha256=${apk_name}.sha256" >> "$GITHUB_OUTPUT"
121+
ls -lh "${apk_name}" "${apk_name}.sha256"
122+
cat "${apk_name}.sha256"
123+
124+
- name: Generate APK provenance attestation
125+
uses: actions/attest@v4
59126
with:
60-
tag_name: "${{ steps.version.outputs.VERSION }}"
61-
release_name: "Release ${{ steps.version.outputs.VERSION }}"
127+
subject-path: |
128+
${{ steps.apk.outputs.filename }}
129+
${{ steps.apk.outputs.sha256 }}
62130
63-
- name: Upload APK
64-
uses: actions/upload-release-asset@v1
131+
- name: Create draft GitHub Release
132+
id: create_release
65133
env:
66-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67-
with:
68-
upload_url: ${{ steps.create_release.outputs.upload_url }}
69-
asset_path: "${{ steps.buildozer.outputs.filename }}"
70-
asset_name: "pythonhere-debug-${{ steps.version.outputs.VERSION }}.apk"
71-
asset_content_type: application/vnd.android.package-archive
134+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
135+
run: |
136+
if ! release_json="$(gh api "/repos/${GITHUB_REPOSITORY}/releases/tags/${GITHUB_REF_NAME}" 2>/dev/null)"; then
137+
release_json="$(
138+
gh api \
139+
--method POST \
140+
"/repos/${GITHUB_REPOSITORY}/releases" \
141+
-f tag_name="${GITHUB_REF_NAME}" \
142+
-f name="Release ${GITHUB_REF_NAME}" \
143+
-F body=@release-notes.rst \
144+
-F draft=true
145+
)"
146+
else
147+
gh api \
148+
--method PATCH \
149+
"/repos/${GITHUB_REPOSITORY}/releases/$(printf '%s' "${release_json}" | python -c 'import json, sys; print(json.load(sys.stdin)["id"])')" \
150+
-F body=@release-notes.rst \
151+
>/dev/null
152+
fi
153+
release_id="$(printf '%s' "${release_json}" | python -c 'import json, sys; print(json.load(sys.stdin)["id"])')"
154+
echo "release_id=${release_id}" >> "$GITHUB_OUTPUT"
72155
73-
- name: Upload package to PyPI
156+
- name: Upload APK to draft GitHub Release
74157
env:
75-
TWINE_USERNAME: __token__
76-
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
77-
run: twine upload dist/*
158+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159+
APK_FILE: ${{ steps.apk.outputs.filename }}
160+
APK_SHA256_FILE: ${{ steps.apk.outputs.sha256 }}
161+
run: |
162+
gh release upload "${GITHUB_REF_NAME}" "${APK_FILE}" "${APK_SHA256_FILE}" --clobber
163+
164+
# - name: Upload package to PyPI
165+
# env:
166+
# TWINE_USERNAME: __token__
167+
# TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
168+
# run: twine upload --skip-existing dist/*
169+
170+
# - name: Publish GitHub Release
171+
# env:
172+
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
173+
# RELEASE_ID: ${{ steps.create_release.outputs.release_id }}
174+
# run: |
175+
# gh api \
176+
# --method PATCH \
177+
# "/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}" \
178+
# -F draft=false
179+
180+
- name: Upload Buildozer build log
181+
if: always()
182+
uses: actions/upload-artifact@v4
183+
with:
184+
name: buildozer-build-log
185+
path: ${{ env.BUILDOZER_BUILD_LOG }}
186+
if-no-files-found: ignore
187+
retention-days: 8

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ coverage.xml
2929

3030
*.apk
3131
key.rsa
32+
.release-signing/
3233

3334
docker-compose.yml
34-
work
35+
work

0 commit comments

Comments
 (0)