build: bump versionName to 2.7.0 #33
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Tag-driven: push a tag like `v1.0.0+5` (versionName `+` versionCode) and this builds, | |
| # signs, and attaches the universal APKs to a GitHub release for that tag. | |
| # - versionCode (the integer after `+`) is what the in-app updater compares. | |
| # - versionName (before `+`) is display-only; change it freely. | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Parse version from tag | |
| id: ver | |
| run: | | |
| TAG="${GITHUB_REF_NAME}" # e.g. v1.0.0+5 or v1.0.0+5-rc1 (prerelease) | |
| NAME="${TAG#v}"; NAME="${NAME%%+*}" # 1.0.0 | |
| CODE="${TAG##*+}" # 5 or 5-rc1 | |
| # A '-suffix' on the versionCode marks a prerelease test build (e.g. v1.0.0+26-rc1). | |
| # The GitHub release is flagged prerelease, which the in-app updater never serves (it | |
| # reads /releases/latest and skips prereleases), so it can go to a single tester | |
| # without shipping to everyone. The suffix is stripped from the built versionCode. | |
| PRERELEASE=false | |
| if [[ "$CODE" == *-* ]]; then PRERELEASE=true; CODE="${CODE%%-*}"; fi | |
| if ! [[ "$CODE" =~ ^[0-9]+$ ]]; then | |
| echo "::error::Tag must be v<versionName>+<versionCode>[-suffix], e.g. v1.0.0+5 or v1.0.0+5-rc1 (got '$TAG')" | |
| exit 1 | |
| fi | |
| echo "name=$NAME" >> "$GITHUB_OUTPUT" | |
| echo "code=$CODE" >> "$GITHUB_OUTPUT" | |
| echo "prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT" | |
| echo "Building versionName=$NAME versionCode=$CODE prerelease=$PRERELEASE" | |
| - uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| # cache-provider: basic — see the note in ci.yml. Keeps caching on the open-source | |
| # implementation rather than v6's default commercial `gradle-actions-caching`. | |
| - uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-provider: basic | |
| - name: Decode release keystore | |
| env: | |
| KEYSTORE_BASE64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }} | |
| STORE_PASSWORD: ${{ secrets.RELEASE_STORE_PASSWORD }} | |
| KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} | |
| KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} | |
| run: | | |
| # Fail fast with a readable error when signing secrets aren't configured. | |
| # Actions injects EMPTY strings for missing secrets (so the Gradle env | |
| # fallbacks never apply), which otherwise surfaces much later as a cryptic | |
| # "Tag number over 30 is not supported" keystore parse failure. | |
| for s in KEYSTORE_BASE64 STORE_PASSWORD KEY_ALIAS KEY_PASSWORD; do | |
| if [ -z "${!s}" ]; then | |
| echo "::error::Repo secret RELEASE_$s is not set — configure the four RELEASE_* signing secrets before tagging a release." | |
| exit 1 | |
| fi | |
| done | |
| echo "$KEYSTORE_BASE64" | base64 --decode > "${{ github.workspace }}/app/release-ci.keystore" | |
| # Prove the decoded keystore is readable and holds the expected key before | |
| # spending minutes on the build. | |
| keytool -list -keystore "${{ github.workspace }}/app/release-ci.keystore" \ | |
| -storepass "$STORE_PASSWORD" -alias "$KEY_ALIAS" > /dev/null | |
| - name: Build signed release + debug universal APKs | |
| env: | |
| RELEASE_STORE_FILE: ${{ github.workspace }}/app/release-ci.keystore | |
| RELEASE_STORE_PASSWORD: ${{ secrets.RELEASE_STORE_PASSWORD }} | |
| RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} | |
| RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} | |
| run: | | |
| ./gradlew --no-daemon \ | |
| -PappVersionName=${{ steps.ver.outputs.name }} \ | |
| -PappVersionCode=${{ steps.ver.outputs.code }} \ | |
| :app:assembleRelease | |
| - name: Stage APK for upload | |
| id: stage | |
| run: | | |
| V="${{ steps.ver.outputs.name }}+${{ steps.ver.outputs.code }}" | |
| mkdir -p dist | |
| # Only the signed universal release APK is published — it's what the in-app updater | |
| # installs (must keep "universal" in the name so the updater's asset selector picks it). | |
| # End users get diagnostics from the in-app export, so no debug APK is distributed. | |
| cp app/build/outputs/apk/release/app-universal-release.apk "dist/pulseloop-${V}-universal.apk" | |
| ls -la dist | |
| - name: Create / update release and attach APKs | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: PulseLoop ${{ steps.ver.outputs.name }} (${{ steps.ver.outputs.code }}) | |
| prerelease: ${{ steps.ver.outputs.prerelease }} | |
| generate_release_notes: true | |
| files: dist/*.apk |