dist.sh builds versioned, signed artifacts for both apps from a git tag
release / build (push) Has been cancelled
release / build (push) Has been cancelled
(semver drives Android versionCode/versionName and package.json). The build-image/ Dockerfile pins the same toolchain for a portable, containerized Gitea Actions runner (build-image.sh builds and pushes it) so releases don't depend on any one machine's local setup. Pushing vX.Y.Z now builds and publishes a Gitea Release automatically.
This commit is contained in:
+137
-21
@@ -89,14 +89,30 @@ the whole Gradle configuration.
|
||||
### 2.4 Build the release bundle
|
||||
|
||||
```bash
|
||||
cd SchwertUndMagieOnPebbleCompanionApp
|
||||
./gradlew bundleRelease # produces app/build/outputs/bundle/release/app-release.aab
|
||||
./gradlew assembleRelease # produces app/build/outputs/apk/release/app-release.apk, for sideload testing
|
||||
./dist.sh # builds both apps, copies signed artifacts into dist/
|
||||
```
|
||||
|
||||
Play Store requires the **AAB** (`bundleRelease` output), not the APK — Play
|
||||
This runs `./gradlew bundleRelease assembleRelease` in
|
||||
`SchwertUndMagieOnPebbleCompanionApp/` and `pebble build` in
|
||||
`SchwertUndMagieOnPebbleWatchApp/`, then copies the outputs to
|
||||
`dist/schwert-und-magie.{aab,apk,pbw}`.
|
||||
|
||||
Before building, the script hard-stops (nonzero exit, nothing written to
|
||||
`dist/`) if the `pebble` CLI, `gradlew`, the Android SDK, the NDK version
|
||||
pinned in `app/build.gradle.kts`, or the VICE/nibtools source tarballs are
|
||||
missing — these are required for the build to succeed at all. It warns but
|
||||
still builds if `keystore.properties` (§2.1-2.3) is missing or points at a
|
||||
nonexistent keystore file, and checks the resulting APK's signature with
|
||||
`apksigner` afterward, warning if it's unsigned or debug-signed. In practice
|
||||
an incomplete signing config also makes Gradle's own `signReleaseBundle` task
|
||||
fail outright, so `dist/` won't be overwritten with an unusable artifact
|
||||
either way — but don't rely on that as the primary check; heed the warning.
|
||||
|
||||
Play Store requires the **AAB** (`schwert-und-magie.aab`), not the APK — Play
|
||||
re-packages per-device APKs from it (including ABI splits, so `arm64-v8a`/
|
||||
`x86_64` native VICE libraries each ship only to matching devices).
|
||||
`x86_64` native VICE libraries each ship only to matching devices). The APK
|
||||
(`schwert-und-magie.apk`) is for direct sideload distribution (§2.6 below)
|
||||
and F-Droid-style testing, not Play Store upload.
|
||||
|
||||
### 2.5 Play Console setup (one-time, per app listing)
|
||||
|
||||
@@ -119,12 +135,11 @@ re-packages per-device APKs from it (including ABI splits, so `arm64-v8a`/
|
||||
|
||||
### 2.6 Versioning for future releases
|
||||
|
||||
Bump both fields in `app/build.gradle.kts` before every release build:
|
||||
|
||||
```kotlin
|
||||
versionCode = 2 // must strictly increase on every Play Store upload
|
||||
versionName = "1.1" // user-visible, free-form
|
||||
```
|
||||
Comes from the git tag automatically — see §4. Pushing `vX.Y.Z` (or running
|
||||
`VERSION=X.Y.Z ./dist.sh` locally) patches `versionCode` (derived as
|
||||
`X*10000 + Y*100 + Z`, which strictly increases as long as X.Y.Z itself does)
|
||||
and `versionName` in `app/build.gradle.kts` at build time, then reverts them —
|
||||
no manual edit needed.
|
||||
|
||||
## 3. Android companion app → F-Droid
|
||||
|
||||
@@ -220,8 +235,100 @@ includes the app in the next index update (published roughly weekly).
|
||||
### 3.5 Versioning for F-Droid updates
|
||||
|
||||
Each new release requires a new `Builds` entry in the metadata file with an
|
||||
incremented `versionCode` and the corresponding git commit or tag. `versionCode`
|
||||
must match the value in `app/build.gradle.kts`.
|
||||
incremented `versionCode` and the corresponding git commit or tag.
|
||||
`versionCode` must match what that tag produces — `X*10000 + Y*100 + Z` for
|
||||
tag `vX.Y.Z` (§2.6, §4).
|
||||
|
||||
## 4. Automated releases via Gitea Actions
|
||||
|
||||
Pushing a tag `vX.Y.Z` builds both apps and publishes a Gitea Release with
|
||||
`schwert-und-magie-X.Y.Z.{aab,apk,pbw}` attached — no local `./dist.sh` run
|
||||
needed. The tag is the only source of truth for the version; nothing needs to
|
||||
be bumped in source files beforehand (`dist.sh` patches `versionCode`/
|
||||
`versionName`/`package.json` at build time and reverts them — see §4.4 for
|
||||
running the same thing locally).
|
||||
|
||||
The whole toolchain (Android SDK/NDK, Pebble SDK) lives in
|
||||
`build-image/Dockerfile`, built and pushed to a container registry by
|
||||
`build-image.sh`. This keeps the setup portable: the runner just needs Docker
|
||||
and pulls that image, so it isn't tied to any one machine's local toolchain
|
||||
install and can be moved or re-registered elsewhere without touching this
|
||||
repo's build scripts.
|
||||
|
||||
### 4.1 Build environment image
|
||||
|
||||
`build-image/Dockerfile` bakes in the Android SDK/NDK and Pebble SDK versions
|
||||
pinned in `app/build.gradle.kts`, matching what's validated for local builds.
|
||||
It does **not** contain the release keystore — that's injected at job runtime
|
||||
from Actions secrets (§4.3), never baked into the image.
|
||||
|
||||
```bash
|
||||
cp registry.env.example registry.env # fill in your registry credentials
|
||||
./build-image.sh # builds + pushes :latest and the pinned VERSION tag
|
||||
```
|
||||
|
||||
Rebuild and push whenever `build-image/Dockerfile` changes (e.g. a Pebble SDK
|
||||
or Android NDK version bump) — bump `build-image/VERSION` first so the tag is
|
||||
meaningful. The workflow (§4.2) pulls `:latest` by default; if you need a
|
||||
release to be reproducible against an exact toolchain image, pin the `image:`
|
||||
line in `.gitea/workflows/release.yml` to the versioned tag instead.
|
||||
|
||||
### 4.2 Runner setup (one-time)
|
||||
|
||||
1. Enable Actions for the repo: repo Settings → Actions → enable, if not
|
||||
already on by default for this Gitea instance.
|
||||
2. Generate a runner registration token: Site Admin → Actions → Runners (or
|
||||
the repo/org-scoped equivalent) → "Create new runner".
|
||||
3. On any machine with Docker that can reach both your Gitea instance and
|
||||
your container registry:
|
||||
```bash
|
||||
# https://gitea.com/gitea/act_runner — grab the latest release binary
|
||||
./act_runner register --no-interactive \
|
||||
--instance <your gitea URL> --token <token> \
|
||||
--name <runner-name> --labels self-hosted:docker://node:20-bookworm
|
||||
./act_runner daemon
|
||||
```
|
||||
The image after `docker://` in `--labels` is only a fallback for jobs that
|
||||
don't specify their own `container:` — irrelevant here since
|
||||
`.gitea/workflows/release.yml` always pins its own image, but the runner
|
||||
still needs a Docker-executor label registered to use that executor at
|
||||
all. The label name itself (`self-hosted`) must match `runs-on:` in
|
||||
`.gitea/workflows/release.yml` — edit both together if you rename it.
|
||||
4. The runner's Docker daemon needs pull access to the registry — run
|
||||
`docker login <registry>` once on that machine with the same credentials
|
||||
as `registry.env`.
|
||||
|
||||
### 4.3 Repo secrets
|
||||
|
||||
Settings → Actions → Secrets, add:
|
||||
|
||||
| Secret | Value |
|
||||
|---|---|
|
||||
| `RELEASE_KEYSTORE_B64` | `base64 -w0 SchwertUndMagieOnPebbleCompanionApp/release.keystore` |
|
||||
| `RELEASE_KEYSTORE_PROPERTIES` | the full contents of `SchwertUndMagieOnPebbleCompanionApp/keystore.properties` (§2.2) |
|
||||
|
||||
`secrets.GITEA_TOKEN` (used to create the release and upload assets) is
|
||||
Gitea's own auto-generated per-job token — nothing to create or add yourself.
|
||||
`.gitea/workflows/release.yml` requests `contents: write` explicitly so
|
||||
release creation works regardless of this instance's default Actions
|
||||
permission mode.
|
||||
|
||||
### 4.4 Cutting a release
|
||||
|
||||
```bash
|
||||
git tag v1.2.3
|
||||
git push origin v1.2.3
|
||||
```
|
||||
|
||||
Watch the run under the repo's Actions tab. On success, the release appears
|
||||
under the repo's Releases page with the three versioned artifacts attached.
|
||||
|
||||
To build the same versioned artifacts locally without pushing a tag (e.g. to
|
||||
test before releasing):
|
||||
|
||||
```bash
|
||||
VERSION=1.2.3 ./dist.sh
|
||||
```
|
||||
|
||||
## 5. Pebble watch app → Rebble app store / direct distribution
|
||||
|
||||
@@ -233,12 +340,19 @@ this repo and changes independently of it.
|
||||
|
||||
### 5.1 Build the artifact
|
||||
|
||||
```bash
|
||||
./dist.sh # also builds the Android side; see §2.4
|
||||
```
|
||||
|
||||
or, to build just the watch app:
|
||||
|
||||
```bash
|
||||
cd SchwertUndMagieOnPebbleWatchApp
|
||||
pebble build # produces build/SchwertUndMagieOnPebbleWatchApp.pbw
|
||||
```
|
||||
|
||||
The `.pbw` is the complete distributable — it bundles all target platforms
|
||||
`dist.sh` copies the result to `dist/schwert-und-magie.pbw`. The `.pbw` is
|
||||
the complete distributable — it bundles all target platforms
|
||||
(`aplite`/`basalt`/`chalk`/`diorite`/`emery`/`flint`/`gabbro`) declared in
|
||||
`package.json`. There is no signing step analogous to Android; Pebble apps
|
||||
are not cryptographically signed by the developer.
|
||||
@@ -267,19 +381,21 @@ pebble screenshot --vnc --no-open docs/screenshots/emery.png
|
||||
|
||||
### 5.4 Versioning
|
||||
|
||||
Bump `version` in `SchwertUndMagieOnPebbleWatchApp/package.json` before each
|
||||
release build.
|
||||
Comes from the git tag automatically — see §4. `dist.sh` patches
|
||||
`SchwertUndMagieOnPebbleWatchApp/package.json`'s `version` field at build
|
||||
time and reverts it afterward; no manual edit needed.
|
||||
|
||||
## 6. Pre-publish checklist
|
||||
|
||||
- [ ] Release keystore generated, passwords saved in a password manager, both
|
||||
gitignored (§1, §2.1)
|
||||
- [ ] `keystore.properties` exists locally and is **not** tracked by git
|
||||
- [ ] `./gradlew bundleRelease` succeeds and installs/runs on a real device
|
||||
from the resulting AAB (test via `bundletool` or Play internal testing)
|
||||
- [ ] `./dist.sh` (or a tag push, §4) succeeds and produces
|
||||
`dist/schwert-und-magie-<version>.{aab,apk,pbw}`
|
||||
- [ ] AAB installs/runs on a real device (test via `bundletool` or Play
|
||||
internal testing)
|
||||
- [ ] Play Console store listing content complete (icon, screenshots,
|
||||
privacy policy, content rating, data safety form)
|
||||
- [ ] F-Droid metadata YAML created and `fdroid build` passes locally (§3)
|
||||
- [ ] `pebble build` succeeds for all target platforms; `.pbw` sideloads and
|
||||
runs correctly against the signed companion app build
|
||||
- [ ] `versionCode`/`versionName` (Android) and `version` (Pebble) bumped
|
||||
- [ ] `.pbw` sideloads and runs correctly against the signed companion app
|
||||
build
|
||||
|
||||
Reference in New Issue
Block a user