All checks were successful
review/code-claude Approve: lock held across container, no deadlock, releases on all exits
115 lines
5.8 KiB
Markdown
115 lines
5.8 KiB
Markdown
# Wolfskin TV container builds
|
|
|
|
Run from a full Git checkout with the upstream `v*` and `p*` tags available. The
|
|
host needs Docker, GNU Make, Bash, Git, and `flock` (util-linux), not Java or the
|
|
Android SDK.
|
|
|
|
```sh
|
|
git fetch origin --tags
|
|
make apk # clean, signed default release: three ABI splits + universal
|
|
make test # upstream testDefaultDebugUnitTest in the same image, no secrets
|
|
make apk-debug # default debug, no secrets; MPV stub and no extra codec decoders
|
|
```
|
|
|
|
APKs remain under `app/build/outputs/apk/default/{release,debug}/`. Debug builds
|
|
are not playback-complete and must not be distributed as releases. Upstream's
|
|
`.github/workflows` and dependency version catalog are unchanged; release builds
|
|
use the catalog's exact Wholphin extension version (currently `0.2.4`). Do not
|
|
place local extension AARs in `app/libs`: upstream prefers them over the pinned
|
|
GitHub Packages dependencies.
|
|
|
|
Upload release assets renamed to `Wolfskin.apk` / `Wolfskin-<abi>.apk` for the
|
|
in-app updater. Gradle outputs
|
|
`Wholphin-default-release-<versionName>-<versionCode>[-<abi>].apk`; strip the
|
|
flavor, version, and code as well as replacing the prefix.
|
|
|
|
Upstream enables JVM unit tests only for debug variants; there is no
|
|
`testDefaultReleaseUnitTest` task. `make test` uses the closest default-flavor
|
|
task without changing upstream's test configuration.
|
|
|
|
## Toolchain and disk use
|
|
|
|
`Dockerfile` pins Temurin JDK `21.0.11+10` by image digest, command-line tools
|
|
`23.0` and platform-tools `37.0.1` by archive and checksum, and build-tools
|
|
`36.0.0` by SDK package version. The SDK manager registers platform `37.0` and
|
|
its licenses; the build rejects any platform revision other than 2. An SDK
|
|
revision upgrade therefore requires a deliberate Dockerfile update.
|
|
Gradle comes from the committed wrapper. The image is built for `linux/amd64`;
|
|
the default local image tag is `wolfskin-build:sdk37-jdk21`.
|
|
Upstream's build timestamp means APKs are not byte-for-byte reproducible.
|
|
|
|
Gradle downloads and caches live in the named volume `wolfskin-gradle`, not
|
|
`/tmp`. Module outputs stay in the checkout. Builds run with the host UID/GID,
|
|
`--no-daemon`, and at most four workers. The repository's Git metadata is mounted
|
|
read-only, including when the checkout is a linked worktree.
|
|
|
|
Override `WOLFSKIN_BUILD_IMAGE` to change the locally built image tag and
|
|
`WOLFSKIN_GRADLE_VOLUME` to isolate a cache. `make build-image` builds only the
|
|
image. Do not delete shared caches during another build.
|
|
|
|
Every Gradle container holds a host-side exclusive lock for its entire run.
|
|
Concurrent targets sharing a cache queue rather than timing out on Gradle's
|
|
cross-container cache journal lock; a waiting invocation prints one line.
|
|
The default lock is `/var/tmp/${WOLFSKIN_GRADLE_VOLUME}.gradle.lock` (using
|
|
`wolfskin-gradle` when unset). Override `WOLFSKIN_GRADLE_LOCK_FILE` with a path
|
|
whose parent directory already exists. All callers sharing a volume must use
|
|
the same lock path on the Docker host. Do not delete the file while builds are
|
|
running or waiting. The lock releases automatically when the invocation exits.
|
|
|
|
## Release credentials
|
|
|
|
The default escrow is
|
|
`/opt/stacks/ventoy/machine-parity/manifest-tank/secrets/wolfskin/`. Check
|
|
`mountpoint -q /mnt/ventoy` before using that path. Set `WOLFSKIN_SECRETS_DIR`
|
|
to use another existing directory. Its required files are:
|
|
|
|
| File | Contents |
|
|
| --- | --- |
|
|
| `release.jks` | Separate Wolfskin PKCS12 keystore, RSA 4096, alias `wolfskin` |
|
|
| `release.properties` | Java properties `storePassword` and `keyPassword` |
|
|
| `github-packages-token` | GitHub token with `read:packages`, username `JustinZeus` |
|
|
|
|
The directory must be mode `0700`, each file mode `0600`, owned by the building
|
|
user. Never commit them or put their contents in logs. Back up the keystore and
|
|
passwords together: losing the release key forces a reinstall. Do not reuse
|
|
wolfskin-android's key or the gh CLI login token.
|
|
|
|
Release builds mount escrow read-only. The token is loaded inside the container
|
|
into upstream's `ORG_GRADLE_PROJECT_WholphinExtensionsUsername` and
|
|
`ORG_GRADLE_PROJECT_WholphinExtensionsPassword` environment hooks, never a Docker
|
|
command argument. The signing init script registers `wolfskin`; the nonsecret
|
|
`release-signing.properties` is mounted as `local.properties` so upstream's
|
|
`release.signing.config` hook selects it. Any host `local.properties` is hidden
|
|
only for the duration of this container. Keystore and passwords stay outside the
|
|
checkout and image. Missing credentials fail the release rather than silently
|
|
shipping the MPV stub.
|
|
|
|
## Versioning and local release markers
|
|
|
|
Upstream computes `versionName` from
|
|
`git describe --tags --long --match='v*'`, dropping the leading `v`, and computes
|
|
`versionCode` from the count of all local `v*` and `p*` tags. Preserve and fetch
|
|
those tags; a shallow or incomplete checkout can give an incorrect version.
|
|
Use the full `git describe` output as the human release name.
|
|
|
|
After committing the intended release, with a clean checkout and fetched tags:
|
|
|
|
```sh
|
|
make release-tag
|
|
make apk
|
|
```
|
|
|
|
The helper creates one lightweight `pwolfskin-YYYY_MM_DD` tag in UTC, appending
|
|
`_1`, `_2`, etc. on collision. Each marker adds one to `versionCode` without
|
|
changing upstream's `v*`-based version name. It never pushes tags, publishes a
|
|
release, or installs an APK. Do not delete published release markers. Tag
|
|
creation and publication must be serialized between release operators.
|
|
|
|
## Inspecting release artifacts
|
|
|
|
Use `apksigner verify --verbose --print-certs APK` and
|
|
`aapt2 dump badging APK` inside the build image. Compare the signer SHA-256 with
|
|
`keytool -list -v -alias wolfskin -keystore /path/to/release.jks` (enter its
|
|
password privately). Inspect APK ZIP entries for real native MPV and ffmpeg
|
|
libraries for each shipped ABI; a successful Java compilation alone does not
|
|
prove that codec extensions are included.
|