wolfskin/docker/README.md
justinzeus 19adf54c23
All checks were successful
review/security-claude Carried from reviewed head: identical tree (re-pushed only to shed stale Actions statuses)
review/code-claude Carried from reviewed head: identical tree (re-pushed only to shed stale Actions statuses)
Pin platform tools and use the upstream debug unit task
2026-10-22 14:43:07 +02:00

4.9 KiB

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, and Git, not Java or the Android SDK.

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.

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.

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:

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.