name: Release run-name: Release ${{ github.ref_name }} on: push: tags: - "v*" concurrency: group: release cancel-in-progress: false permissions: contents: read jobs: build: runs-on: ubuntu-26.04 timeout-minutes: 60 permissions: contents: read outputs: version-code: ${{ steps.build.outputs.version-code }} steps: - uses: actions/checkout@v7 with: persist-credentials: false - name: Check tag matches versionName run: | version=$(grep -oP 'versionName = "\K[^"]+' app/build.gradle.kts) case "$GITHUB_REF_NAME" in "v$version" | "v$version"-*) ;; *) echo "tag $GITHUB_REF_NAME does not match versionName $version" >&2 exit 1 ;; esac - id: build uses: ./.github/actions/build with: gradle-args: ":app:assembleRelease :app:bundleRelease --no-daemon" sign: "true" keystore-base64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }} keyproperties-base64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }} keystore-password: ${{ secrets.SUBTRACKS_UPLOAD_STORE_PASSWORD }} key-password: ${{ secrets.SUBTRACKS_UPLOAD_KEY_PASSWORD }} - name: Export release certificate env: KEYSTORE_BASE64: ${{ secrets.SUBTRACKS_KEYSTORE_BASE64 }} KEYPROPERTIES_BASE64: ${{ secrets.SUBTRACKS_KEYPROPERTIES_BASE64 }} KEYSTORE_PASSWORD: ${{ secrets.SUBTRACKS_UPLOAD_STORE_PASSWORD }} run: | umask 077 trap 'rm -f "$RUNNER_TEMP/keystore"' EXIT echo "$KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/keystore" alias=$(printf '%s' "$KEYPROPERTIES_BASE64" | base64 -d | sed -n 's/^keyAlias=//p' | tr -d '\r') nix develop --command keytool -exportcert -rfc -keystore "$RUNNER_TEMP/keystore" -alias "$alias" -storepass "$KEYSTORE_PASSWORD" -file app/build/outputs/release-certificate.pem - uses: actions/upload-artifact@v7 with: name: release path: app/build/outputs publish: needs: build runs-on: ubuntu-26.04 timeout-minutes: 60 permissions: contents: write steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: actions/download-artifact@v8 with: name: release path: dist - uses: ./.github/actions/nix - name: Detect stable tag id: stable run: | if [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "value=true" >> "$GITHUB_OUTPUT" else echo "value=false" >> "$GITHUB_OUTPUT" fi - name: Check release notes exist run: | test -f "metadata/en-US/changelogs/${{ needs.build.outputs.version-code }}.txt" test -f "docs/releases/$GITHUB_REF_NAME.md" - name: Write Play service account if: steps.stable.outputs.value == 'true' env: PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }} run: | umask 077 printf '%s' "$PLAY_SERVICE_ACCOUNT_JSON" > "$RUNNER_TEMP/play.json" - name: Upload to Google Play if: steps.stable.outputs.value == 'true' run: | nix develop .#release --command fastlane supply \ --aab dist/bundle/release/app-release.aab \ --package_name com.subtracks \ --track "${{ vars.PLAY_TRACK || 'internal' }}" \ --json_key "$RUNNER_TEMP/play.json" \ --mapping dist/mapping/release/mapping.txt - name: Remove Play service account if: always() run: rm -f "$RUNNER_TEMP/play.json" - name: Checksums and signature id: checksums run: | cp dist/apk/release/app-release.apk subtracks.apk cp dist/bundle/release/app-release.aab subtracks.aab gzip -n -9 -c dist/mapping/release/mapping.txt > mapping.txt.gz sha256sum subtracks.apk subtracks.aab > SHA256SUMS echo "Artifact SHA-256:" sha256sum subtracks.apk subtracks.aab echo "APK signature:" certs=$(nix develop --command bash -c '"$ANDROID_HOME/build-tools/37.0.0/apksigner" verify --print-certs subtracks.apk') printf '%s\n' "$certs" fingerprint=$(printf '%s\n' "$certs" | sed -n 's/.*certificate SHA-256 digest: //p' | head -1 | tr '[:lower:]' '[:upper:]' | sed 's/\(..\)/\1:/g; s/:$//') echo "fingerprint=$fingerprint" >> "$GITHUB_OUTPUT" - name: Create GitHub release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | args=(--verify-tag --title "$GITHUB_REF_NAME" --notes-file "docs/releases/$GITHUB_REF_NAME.md") if [ "${{ steps.stable.outputs.value }}" != "true" ]; then args+=(--prerelease) fi gh release create "$GITHUB_REF_NAME" subtracks.apk subtracks.aab SHA256SUMS dist/release-certificate.pem mapping.txt.gz "${args[@]}"