Merge pull request #871 from permissionlesstech/watch-release-0.1.0

Prepare Wear 0.1.0 reproducible release
This commit is contained in:
callebtc 2026-08-11 18:14:29 +02:00 committed by GitHub
commit 1a0d8713e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 147 additions and 69 deletions

View File

@ -102,7 +102,7 @@ jobs:
"$RUNNER_TEMP/attestation-subjects/BITCHAT_SHA256SUMS.unsigned"
cp "$RUNNER_TEMP"/release-a/bitchat-android-*-unsigned.apk \
"$RUNNER_TEMP/attestation-subjects/"
cp "$RUNNER_TEMP/release-a/bitchat-android-release-unsigned.aab" \
cp "$RUNNER_TEMP"/release-a/bitchat-android-*-unsigned.aab \
"$RUNNER_TEMP/attestation-subjects/"
- name: Attest verified unsigned release

View File

@ -11,11 +11,10 @@ The central rule is:
No keystore or password is stored in GitHub, GitHub Actions, the repository,
release notes, or workflow artifacts.
This runbook currently releases only the phone app, `com.bitchat.droid`.
The `:wear` module is tested and dependency-locked in CI but is not included in
the canonical release artifact set. Do not publish its development-signed
outputs. Wear distribution requires a separate signing identity, reproducible
artifact contract, Play listing, and maintainer runbook.
This runbook releases both the phone and Wear OS apps under the shared Play
application ID `com.bitchat.droid`. Wear releases use the independent version
code range beginning at `1000000001`; every phone and Wear artifact uploaded to
one Play listing must have a unique version code.
For the technical trust model and third-party verification instructions, see
[Reproducible builds](reproducible-builds.md).
@ -28,7 +27,7 @@ For the technical trust model and third-party verification instructions, see
| Create tag | Maintainer machine | Signed `vX.Y.Z` tag |
| Build twice | GitHub Actions | Two identical unsigned APK/AAB builds |
| Promote build | GitHub Actions | Attested `verified-unsigned-release` artifact |
| Sign | Maintainer machine | Three installable APKs and one Play upload AAB |
| Sign | Maintainer machine | Four installable APKs and two Play upload AABs |
| Test Play build | Play Console internal track | Play-generated APKs tested before public rollout |
| Prepare release | Maintainer machine and GitHub draft | Checksummed public release assets |
| Publish | GitHub Releases and Play Console | Public GitHub release and promoted Play rollout |
@ -42,8 +41,8 @@ These are four separate signing identities:
2. **GitHub APK signature**: lets Android install and update the APKs published
on GitHub. Use the existing GitHub release key. Its certificate SHA-256 must
match `BITCHAT_GITHUB_RELEASE_CERT_SHA256` in `gradle.properties`.
3. **Play upload signature**: the maintainer signs the AAB with the Play upload
key so Play will accept it.
3. **Play upload signature**: the maintainer signs both AABs with the Play
upload key so Play will accept them.
4. **Play app signature**: Google generates device APKs and signs them with the
separate Play app-signing key.
@ -119,9 +118,10 @@ a command line, in a shell profile, or in a release-notes file.
## 1. Prepare and approve the release commit
1. Update `versionCode` and `versionName` in `app/build.gradle.kts`.
`versionCode` must be greater than every build previously uploaded to Play.
`versionName` must match the release tag without the leading `v`.
1. Update `versionCode` and `versionName` in `app/build.gradle.kts`. For a Wear
release, also update them in `wear/build.gradle.kts` using the reserved Wear
version-code range. Every code must be unique across both form factors.
The phone `versionName` must match the release tag without the leading `v`.
2. Merge all intended release changes into `main`.
3. Confirm required CI checks are green.
4. Complete the
@ -147,6 +147,7 @@ Set shell variables for the rest of the release:
export REPOSITORY=permissionlesstech/bitchat-android
export TAG=vX.Y.Z
export VERSION_CODE=NN
export WEAR_VERSION_CODE=1000000001
export RELEASE_DIR="release-${TAG#v}"
```
@ -156,6 +157,7 @@ Confirm the source version:
grep -nE 'versionCode|versionName' app/build.gradle.kts
test "$(sed -n 's/.*versionName = "\([^"]*\)".*/\1/p' app/build.gradle.kts)" = "${TAG#v}"
test "$(sed -n 's/.*versionCode = \([0-9][0-9]*\).*/\1/p' app/build.gradle.kts)" = "$VERSION_CODE"
test "$(sed -n 's/.*versionCode = \([0-9_][0-9_]*\).*/\1/p' wear/build.gradle.kts | tr -d _)" = "$WEAR_VERSION_CODE"
```
Stop if either `test` command fails.
@ -251,6 +253,8 @@ The directory must initially contain exactly these canonical files:
- `bitchat-android-x86-unsigned.apk`
- `bitchat-android-x86_64-unsigned.apk`
- `bitchat-android-release-unsigned.aab`
- `bitchat-android-wear-unsigned.apk`
- `bitchat-android-wear-release-unsigned.aab`
Verify the checksum manifest:
@ -328,6 +332,7 @@ It creates:
- `bitchat-android-arm64.apk`
- `bitchat-android-universal.apk`
- `bitchat-android-wear.apk`
- `bitchat-android-x86_64.apk`
The unsigned armv7 and x86 APKs remain available for reproducibility, but are
@ -337,7 +342,7 @@ If the helper stops after creating any signed file, do not continue or overwrite
files manually. Start again in a new directory downloaded from the same
successful workflow run.
## 6. Sign the Google Play AAB locally
## 6. Sign the Google Play AABs locally
Set the pinned JDK and Play upload-key locations, then load the passwords:
@ -361,18 +366,20 @@ Run:
tools/reproducible-builds/sign-play-bundle.sh "$RELEASE_DIR"
```
The helper creates `bitchat-android-play-upload.aab`, verifies its JAR
signature, proves that every non-signature payload entry matches the canonical
The helper creates `bitchat-android-play-upload.aab` and
`bitchat-android-wear-play-upload.aab`, verifies their JAR signatures, proves
that every non-signature payload entry matches the corresponding canonical
unsigned AAB, and updates `SHA256SUMS`.
This is the only file to upload to Play Console:
These are the only files to upload to Play Console:
```text
release-X.Y.Z/bitchat-android-play-upload.aab
release-X.Y.Z/bitchat-android-wear-play-upload.aab
```
Do not upload an APK or `bitchat-android-release-unsigned.aab` to Play. Do not
open Android Studio and rebuild the bundle.
Do not upload an APK or either `*-release-unsigned.aab` to Play. Do not open
Android Studio and rebuild the bundles.
Remove passwords from the environment after both signing steps:
@ -394,16 +401,20 @@ tools/reproducible-builds/prepare-github-release.sh "$RELEASE_DIR"
The helper verifies all checksums and renames the public build information and
checksum manifests. It refuses missing or pre-existing release files.
The final GitHub Release must contain all 13 files below:
The final GitHub Release must contain all 17 files below:
| Asset | Signed? | Why it is published |
|---|---:|---|
| `bitchat-android-arm64.apk` | APK release key | Primary direct-install APK |
| `bitchat-android-universal.apk` | APK release key | Fallback direct-install APK |
| `bitchat-android-x86_64.apk` | APK release key | x86_64 install APK |
| Five `bitchat-android-*-unsigned.apk` files | No | Reproducibility inputs for every ABI target |
| `bitchat-android-wear.apk` | APK release key | Wear OS direct-install APK |
| Five phone `bitchat-android-*-unsigned.apk` files | No | Reproducibility inputs for every phone ABI target |
| `bitchat-android-release-unsigned.aab` | No | Canonical reproducible Play input |
| `bitchat-android-play-upload.aab` | Play upload key | Exact bundle uploaded to Play |
| `bitchat-android-wear-unsigned.apk` | No | Canonical reproducible Wear install input |
| `bitchat-android-wear-release-unsigned.aab` | No | Canonical reproducible Wear Play input |
| `bitchat-android-wear-play-upload.aab` | Play upload key | Exact bundle uploaded to the Wear OS track |
| `BITCHAT_BUILDINFO.json` | GitHub attestation | Source commit and pinned toolchain |
| `BITCHAT_SHA256SUMS.unsigned` | GitHub attestation | Original canonical CI manifest |
| `BITCHAT_SHA256SUMS` | No detached signature | SHA-256 for every published asset |
@ -432,12 +443,13 @@ Create a local release-notes file. At minimum it must contain:
## Bitchat Android vX.Y.Z
- Version code: NN
- Wear version: 0.1.0 (code 1000000001)
- Source tag: vX.Y.Z
- GitHub APK signing certificate SHA-256: FINGERPRINT
- Play upload certificate SHA-256: FINGERPRINT
- Play app-signing certificate SHA-256: FINGERPRINT
Checksums, canonical unsigned APK/AAB inputs, the exact Play upload AAB, and
Checksums, canonical unsigned APK/AAB inputs, the exact Play upload AABs, and
build information are attached. See `docs/reproducible-builds.md` for public
verification instructions.
@ -474,7 +486,7 @@ gh release view "$TAG" --repo "$REPOSITORY" --web
Keep it as a draft until the Play internal-track checks below pass.
## 9. Upload and test the AAB in Google Play
## 9. Upload and test the AABs in Google Play
1. Open Play Console and select `com.bitchat.droid`.
2. Open **Test and release > Testing > Internal testing**.
@ -495,16 +507,23 @@ Keep it as a draft until the Play internal-track checks below pass.
10. In **Setup > App integrity**, confirm the Play app-signing certificate
SHA-256 is the value recorded in the GitHub release notes.
Promote this same tested Play release from internal testing to production.
Do not rebuild or upload a second AAB for production. Use a staged production
rollout when appropriate.
For the initial Wear release, open **Test and release > Advanced settings >
Form factors**, add Wear OS, upload the required Wear screenshot, and use the
dedicated **Wear OS only** test track. Upload exactly
`bitchat-android-wear-play-upload.aab`, confirm version code `1000000001`, and
complete the Wear OS opt-in and review flow. Promote the already-tested Wear
artifact on its dedicated track; do not add it to the mobile track.
Promote these same tested Play releases from their test tracks to their
respective production tracks. Do not rebuild or upload replacement AABs for
production. Use staged production rollouts when appropriate.
Google signs the device APKs with the Play app-signing key, so Play-delivered
APKs will not be byte-identical to the GitHub APKs. That is expected.
## 10. Publish GitHub and promote Play
After the internal Play build passes and the GitHub draft has all 13 assets:
After both Play test builds pass and the GitHub draft has all 17 assets:
```bash
gh release edit "$TAG" \
@ -539,7 +558,7 @@ tools/reproducible-builds/verify-github-release.sh "$TAG"
Also verify:
- the GitHub release is marked **Latest**;
- the three signed APKs install and show the expected version;
- the four signed APKs install and show the expected version;
- the Play listing shows the intended production version and rollout state;
- a Play-installed build is signed by the app-signing certificate recorded in
the release notes; and
@ -572,10 +591,10 @@ Also verify:
- [ ] `verified-unsigned-release` downloaded by run ID
- [ ] Checksums, source commit, and attestations verified
- [ ] GitHub APKs signed locally with the pinned certificate
- [ ] Play AAB signed locally with the registered upload key
- [ ] `BITCHAT_SHA256SUMS` verifies all 13 release assets
- [ ] Phone and Wear Play AABs signed locally with the registered upload key
- [ ] `BITCHAT_SHA256SUMS` verifies all 17 release assets
- [ ] GitHub draft created with certificate fingerprints and all assets
- [ ] Exact signed AAB uploaded to and tested on Play internal track
- [ ] Exact signed phone and Wear AABs uploaded to and tested on their tracks
- [ ] GitHub Release published
- [ ] Same tested Play release promoted to production
- [ ] Public GitHub and Play verification completed
@ -586,3 +605,5 @@ Also verify:
- [GitHub CLI: create a release](https://cli.github.com/manual/gh_release_create)
- [Google Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756)
- [Play Console App bundle explorer](https://support.google.com/googleplay/android-developer/answer/9859152)
- [Package and distribute Wear OS apps](https://developer.android.com/training/wearables/packaging)
- [Manage form-factor releases on dedicated tracks](https://support.google.com/googleplay/android-developer/answer/13295490)

View File

@ -1,16 +1,14 @@
# Reproducible builds
Bitchat's canonical phone-app release build produces byte-for-byte reproducible
unsigned APKs and an unsigned Android App Bundle (AAB). CI builds the release
Bitchat's canonical release build produces byte-for-byte reproducible unsigned
phone and Wear OS APKs and Android App Bundles (AABs). CI builds the release
twice in independent jobs and exposes a verified release artifact only when
every canonical byte matches. The `:wear` module is tested and
dependency-locked but is outside this phone artifact contract until a separate
Wear release and signing process is defined.
every canonical byte matches.
Signing remains local: no keystore or signing password is stored in or exposed
to GitHub Actions. Anyone can reproduce the unsigned artifacts; maintainers
download the verified CI output, sign the selected GitHub APKs and Play upload
AAB locally, then manually publish those exact files.
AABs locally, then manually publish those exact files.
Maintainers should use the complete
[Android maintainer release guide](maintainer-release-guide.md) for the
@ -71,6 +69,8 @@ The output contains:
- unsigned APKs for arm64, armv7, x86, x86_64, and universal installs
- `bitchat-android-release-unsigned.aab`
- `bitchat-android-wear-unsigned.apk`
- `bitchat-android-wear-release-unsigned.aab`
- `BUILDINFO.json`
- `SHA256SUMS.unsigned`
@ -104,13 +104,13 @@ tools/reproducible-builds/verify-github-release.sh vX.Y.Z
That command:
1. downloads all release APKs, the AAB, build information, and checksum files;
1. downloads all release APKs, AABs, build information, and checksum files;
2. verifies the canonical unsigned build's GitHub artifact-attestation subjects
against this repository;
3. verifies `BITCHAT_SHA256SUMS`;
4. checks that the local source commit is the release commit;
5. rebuilds in the pinned container; and
6. byte-compares every unsigned APK, the unsigned AAB, build information, and
6. byte-compares every unsigned APK, both unsigned AABs, build information, and
the unsigned checksum manifest.
To verify the published checksums and attestations without rebuilding:
@ -154,8 +154,8 @@ gh attestation verify bitchat-android-universal-unsigned.apk \
Google Play App Signing changes the verification boundary:
- maintainers upload a signed AAB using the upload key;
- Google Play generates optimized, device-specific APK splits from that AAB;
- maintainers upload signed phone and Wear AABs using the upload key;
- Google Play generates optimized, device-specific APK splits from those AABs;
- Google signs the delivered APKs with the app-signing key.
Consequently, a Play-delivered APK is not expected to be byte-identical to the
@ -163,8 +163,8 @@ GitHub universal APK or to a locally built APK. Use this procedure instead:
1. In Play Console, open **Test and release > App bundle explorer**, select the
release/version code, and download the original app bundle if that option is
available to your account. Compare its unsigned payload with the reproduced
`bitchat-android-release-unsigned.aab`:
available to your account. Compare its unsigned payload with the matching
reproduced phone or Wear AAB:
```bash
tools/reproducible-builds/compare-archive-payloads.sh \
@ -204,9 +204,10 @@ maintainers to retain the uploaded AAB, publish its digest and provenance, and
record the Play version code and app-signing certificate fingerprint alongside
the release.
The GitHub workflow builds and attests the canonical unsigned AAB. A maintainer
locally creates `bitchat-android-play-upload.aab` from that exact file and
uploads it manually to Google Play.
The GitHub workflow builds and attests both canonical unsigned AABs. A
maintainer locally creates `bitchat-android-play-upload.aab` and
`bitchat-android-wear-play-upload.aab` from those exact files and uploads them
manually to Google Play.
## Maintainer release process

View File

@ -56,11 +56,20 @@ cd "$PROJECT_ROOT"
aab_source="$PROJECT_ROOT/app/build/outputs/bundle/release/app-release.aab"
if [ ! -f "$aab_source" ]; then
echo "error: expected release AAB not found" >&2
echo "error: expected phone release AAB not found" >&2
exit 1
fi
cp "$aab_source" "$OUTPUT_DIR/bitchat-android-release-unsigned.aab"
./gradlew "${gradle_args[@]}" :wear:clean :wear:bundleRelease
wear_aab_source="$PROJECT_ROOT/wear/build/outputs/bundle/release/wear-release.aab"
if [ ! -f "$wear_aab_source" ]; then
echo "error: expected Wear release AAB not found" >&2
exit 1
fi
cp "$wear_aab_source" "$OUTPUT_DIR/bitchat-android-wear-release-unsigned.aab"
# AGP cannot build split APKs and an app bundle from the same intermediates.
./gradlew "${gradle_args[@]}" :app:clean :app:assembleRelease
@ -81,6 +90,15 @@ for source_name in "${!apk_names[@]}"; do
cp "$source_path" "$OUTPUT_DIR/${apk_names[$source_name]}"
done
./gradlew "${gradle_args[@]}" :wear:clean :wear:assembleRelease
wear_apk_source="$PROJECT_ROOT/wear/build/outputs/apk/release/wear-release-unsigned.apk"
if [ ! -f "$wear_apk_source" ]; then
echo "error: expected Wear release APK not found" >&2
exit 1
fi
cp "$wear_apk_source" "$OUTPUT_DIR/bitchat-android-wear-unsigned.apk"
source_commit="${BITCHAT_SOURCE_COMMIT:-$(git -C "$PROJECT_ROOT" rev-parse HEAD)}"
if ! [[ "$source_commit" =~ ^([0-9a-f]{40}|[0-9a-f]{64})$ ]]; then
echo "error: source commit must be a full Git object ID" >&2
@ -109,6 +127,7 @@ EOF
sha256sum BUILDINFO.json
sha256sum bitchat-android-*-unsigned.apk
sha256sum bitchat-android-release-unsigned.aab
sha256sum bitchat-android-wear-release-unsigned.aab
} | sort -k2 > SHA256SUMS.unsigned
)

View File

@ -12,6 +12,8 @@ artifacts=(
bitchat-android-armv7-unsigned.apk
bitchat-android-release-unsigned.aab
bitchat-android-universal-unsigned.apk
bitchat-android-wear-release-unsigned.aab
bitchat-android-wear-unsigned.apk
bitchat-android-x86-unsigned.apk
bitchat-android-x86_64-unsigned.apk
)

View File

@ -30,6 +30,10 @@ required=(
bitchat-android-release-unsigned.aab
bitchat-android-universal-unsigned.apk
bitchat-android-universal.apk
bitchat-android-wear-play-upload.aab
bitchat-android-wear-release-unsigned.aab
bitchat-android-wear-unsigned.apk
bitchat-android-wear.apk
bitchat-android-x86-unsigned.apk
bitchat-android-x86_64-unsigned.apk
bitchat-android-x86_64.apk
@ -53,6 +57,8 @@ for artifact_path in "$RELEASE_DIR"/*; do
bitchat-android-armv7-unsigned.apk|\
bitchat-android-play-upload.aab|bitchat-android-release-unsigned.aab|\
bitchat-android-universal-unsigned.apk|bitchat-android-universal.apk|\
bitchat-android-wear-play-upload.aab|bitchat-android-wear-release-unsigned.aab|\
bitchat-android-wear-unsigned.apk|bitchat-android-wear.apk|\
bitchat-android-x86-unsigned.apk|\
bitchat-android-x86_64-unsigned.apk|bitchat-android-x86_64.apk)
;;

View File

@ -48,13 +48,6 @@ fi
"${SHA256[@]}" -c SHA256SUMS.unsigned
)
UNSIGNED_AAB="$RELEASE_DIR/bitchat-android-release-unsigned.aab"
SIGNED_AAB="$RELEASE_DIR/bitchat-android-play-upload.aab"
if [ -e "$SIGNED_AAB" ]; then
echo "error: signed Play upload AAB already exists" >&2
exit 1
fi
TEMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TEMP_DIR"' EXIT
STOREPASS_FILE="$TEMP_DIR/storepass"
@ -63,17 +56,40 @@ printf '%s\n' "$BITCHAT_PLAY_KEYSTORE_PASSWORD" > "$STOREPASS_FILE"
printf '%s\n' "$BITCHAT_PLAY_KEY_PASSWORD" > "$KEYPASS_FILE"
chmod 600 "$STOREPASS_FILE" "$KEYPASS_FILE"
"$JARSIGNER" \
-keystore "$KEYSTORE" \
-storepass:file "$STOREPASS_FILE" \
-keypass:file "$KEYPASS_FILE" \
-digestalg SHA-256 \
-signedjar "$SIGNED_AAB" \
"$UNSIGNED_AAB" \
"$BITCHAT_PLAY_UPLOAD_KEY_ALIAS"
unsigned_names=(
"bitchat-android-release-unsigned.aab"
"bitchat-android-wear-release-unsigned.aab"
)
signed_names=(
"bitchat-android-play-upload.aab"
"bitchat-android-wear-play-upload.aab"
)
"$JARSIGNER" -verify "$SIGNED_AAB" >/dev/null
"$SCRIPT_DIR/compare-archive-payloads.sh" "$UNSIGNED_AAB" "$SIGNED_AAB"
for ((index = 0; index < ${#unsigned_names[@]}; index++)); do
unsigned_aab="$RELEASE_DIR/${unsigned_names[$index]}"
signed_aab="$RELEASE_DIR/${signed_names[$index]}"
if [ ! -f "$unsigned_aab" ]; then
echo "error: unsigned Play AAB not found: ${unsigned_names[$index]}" >&2
exit 1
fi
if [ -e "$signed_aab" ]; then
echo "error: signed Play upload AAB already exists: ${signed_names[$index]}" >&2
exit 1
fi
"$JARSIGNER" \
-keystore "$KEYSTORE" \
-storepass:file "$STOREPASS_FILE" \
-keypass:file "$KEYPASS_FILE" \
-digestalg SHA-256 \
-signedjar "$signed_aab" \
"$unsigned_aab" \
"$BITCHAT_PLAY_UPLOAD_KEY_ALIAS"
"$JARSIGNER" -verify "$signed_aab" >/dev/null
"$SCRIPT_DIR/compare-archive-payloads.sh" "$unsigned_aab" "$signed_aab"
done
(
cd "$RELEASE_DIR"
@ -86,4 +102,4 @@ chmod 600 "$STOREPASS_FILE" "$KEYPASS_FILE"
} | sort -k2 > SHA256SUMS
)
echo "Verified unsigned AAB was signed locally with the Play upload key and checksummed."
echo "Verified unsigned phone and Wear AABs were signed locally with the Play upload key and checksummed."

View File

@ -68,11 +68,13 @@ export BITCHAT_GITHUB_KEY_PASSWORD
unsigned_names=(
"bitchat-android-arm64-unsigned.apk"
"bitchat-android-universal-unsigned.apk"
"bitchat-android-wear-unsigned.apk"
"bitchat-android-x86_64-unsigned.apk"
)
signed_names=(
"bitchat-android-arm64.apk"
"bitchat-android-universal.apk"
"bitchat-android-wear.apk"
"bitchat-android-x86_64.apk"
)

View File

@ -50,6 +50,8 @@ attested_artifacts=(
bitchat-android-armv7-unsigned.apk
bitchat-android-release-unsigned.aab
bitchat-android-universal-unsigned.apk
bitchat-android-wear-release-unsigned.aab
bitchat-android-wear-unsigned.apk
bitchat-android-x86-unsigned.apk
bitchat-android-x86_64-unsigned.apk
)

View File

@ -9,14 +9,17 @@ plugins {
android {
namespace = "com.bitchat.watch"
compileSdk = libs.versions.compileSdk.get().toInt()
buildToolsVersion = libs.versions.buildTools.get()
defaultConfig {
applicationId = "com.bitchat.watch"
applicationId = "com.bitchat.droid"
minSdk = 33 // Wear OS 4 (Pixel Watch 1+): the S+ Bluetooth permissions the app
// declares only exist from API 31, and API 30 would additionally require location
// for BLE scan results, which the app deliberately refuses.
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
// Wear releases use a separate high range because Play requires every artifact in
// one application ID to have a unique version code across all form factors.
versionCode = 1_000_000_001
versionName = "0.1.0"
vectorDrawables {
@ -24,6 +27,11 @@ android {
}
}
dependenciesInfo {
includeInApk = false
includeInBundle = false
}
buildTypes {
release {
isMinifyEnabled = true
@ -32,9 +40,9 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
// Sign with the debug key so release builds can be installed over the
// debug app during development (same signature = seamless upgrade).
signingConfig = signingConfigs.getByName("debug")
vcsInfo {
include = false
}
}
}
@ -158,6 +166,7 @@ tasks.matching { it.name.contains("UnitTest", ignoreCase = true) }.configureEach
}
kotlin {
jvmToolchain(21)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}