ci(release): update release workflow to tag based versioning (#2838)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich
2025-08-26 07:36:58 -05:00
committed by GitHub
parent 40395c7c69
commit 6b3f1236b1
4 changed files with 410 additions and 367 deletions

View File

@@ -2,76 +2,70 @@ name: Make Release
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to build from'
required: true
default: 'main' # Or your most common release branch
type: string
create_github_release:
description: 'Create a GitHub Release (and upload assets)'
required: true
default: true
type: boolean
push:
tags:
- 'v*'
permissions: write-all # Needed for creating releases and uploading assets
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: read
id-token: write
attestations: write
jobs:
# Job to prepare common environment variables like version
prepare-release-info:
prepare-build-info:
runs-on: ubuntu-latest
outputs:
versionCode: ${{ steps.calculate_version_code.outputs.versionCode }}
versionNameBase: ${{ steps.get_version.outputs.versionNameBase }}
APP_VERSION_NAME: ${{ steps.get_version_name.outputs.APP_VERSION_NAME }}
APP_VERSION_CODE: ${{ steps.calculate_version_code.outputs.versionCode }}
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.branch }}
fetch-depth: 0
submodules: 'recursive'
fetch-depth: 0 # Needed for git rev-list
- name: Get `versionNameBase`
id: get_version
run: |
echo "versionNameBase=$(grep -oP 'VERSION_NAME_BASE = \"\K[^\"]+' ./buildSrc/src/main/kotlin/Configs.kt)" >> $GITHUB_OUTPUT
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'jetbrains'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
build-scan-publish: true
build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service'
build-scan-terms-of-use-agree: 'yes'
- name: Determine Version Name from Tag
id: get_version_name
run: echo "APP_VERSION_NAME=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
- name: Calculate Version Code
id: calculate_version_code
uses: ./.github/actions/calculate-version-code
# Job for F-Droid build
build-fdroid:
needs: prepare-release-info # Depends on version info
runs-on: ubuntu-latest
if: github.repository == 'meshtastic/Meshtastic-Android'
outputs:
apk_path: app/build/outputs/apk/fdroid/release/app-fdroid-release.apk
apk_name: fdroidRelease-${{ needs.prepare-release-info.outputs.versionNameBase }}-${{ needs.prepare-release-info.outputs.versionCode }}.apk
needs: prepare-build-info
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.branch }}
submodules: 'recursive'
fetch-depth: 0
- name: Load secrets (only keystore for F-Droid)
run: |
echo $KEYSTORE | base64 -di > ./app/$KEYSTORE_FILENAME
echo "$KEYSTORE_PROPERTIES" > ./keystore.properties
env:
KEYSTORE: ${{ secrets.KEYSTORE }}
KEYSTORE_FILENAME: ${{ secrets.KEYSTORE_FILENAME }}
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
submodules: 'recursive'
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'jetbrains'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
@@ -80,63 +74,47 @@ jobs:
build-scan-publish: true
build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service'
build-scan-terms-of-use-agree: 'yes'
add-job-summary: always
- name: Build F-Droid release
run: ./gradlew assembleFdroidRelease
- name: Load F-Droid secrets
env:
VERSION_CODE: ${{ needs.prepare-release-info.outputs.versionCode }}
KEYSTORE_BASE64: ${{ secrets.KEYSTORE }}
KEYSTORE_FILENAME_SECRET: ${{ secrets.KEYSTORE_FILENAME }}
KEYSTORE_PROPERTIES_SECRET: ${{ secrets.KEYSTORE_PROPERTIES }}
run: |
echo "Writing keystore file for F-Droid"
echo "$KEYSTORE_BASE64" | base64 --decode > ./app/$KEYSTORE_FILENAME_SECRET
echo "Writing keystore.properties for F-Droid"
echo "$KEYSTORE_PROPERTIES_SECRET" > ./keystore.properties
- name: Upload F-Droid APK artifact (for release job)
- name: Build F-Droid Release APK
run: |
./gradlew :app:assembleFdroidRelease --parallel --continue --scan
env:
VERSION_NAME: ${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}
VERSION_CODE: ${{ needs.prepare-build-info.outputs.APP_VERSION_CODE }}
- name: Upload F-Droid APK artifact
uses: actions/upload-artifact@v4
with:
name: fdroid-apk
path: app/build/outputs/apk/fdroid/release/app-fdroid-release.apk
retention-days: 1 # Keep for a short period as it will be uploaded to release
retention-days: 1
# Job for Play Store build
build-google:
needs: prepare-release-info # Depends on version info
runs-on: ubuntu-latest
if: github.repository == 'meshtastic/Meshtastic-Android'
outputs:
aab_path: app/build/outputs/bundle/googleRelease/app-google-release.aab
aab_name: googleRelease-${{ needs.prepare-release-info.outputs.versionNameBase }}-${{ needs.prepare-release-info.outputs.versionCode }}.aab
apk_path: app/build/outputs/apk/google/release/app-google-release.apk
apk_name: googleRelease-${{ needs.prepare-release-info.outputs.versionNameBase }}-${{ needs.prepare-release-info.outputs.versionCode }}.apk
needs: prepare-build-info
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.branch }}
submodules: 'recursive'
fetch-depth: 0
- name: Load secrets
run: |
rm -f ./app/google-services.json # Ensure clean state
echo $GSERVICES > ./app/google-services.json
echo $KEYSTORE | base64 -di > ./app/$KEYSTORE_FILENAME
echo "$KEYSTORE_PROPERTIES" > ./keystore.properties
echo "datadogApplicationId=$DATADOG_APPLICATION_ID" >> ./secrets.properties
echo "datadogClientToken=$DATADOG_CLIENT_TOKEN" >> ./secrets.properties
echo "MAPS_API_KEY=$GOOGLE_MAPS_API_KEY" >> ./secrets.properties
env:
GSERVICES: ${{ secrets.GSERVICES }}
KEYSTORE: ${{ secrets.KEYSTORE }}
KEYSTORE_FILENAME: ${{ secrets.KEYSTORE_FILENAME }}
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
DATADOG_APPLICATION_ID: ${{ secrets.DATADOG_APPLICATION_ID }}
DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }}
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
submodules: 'recursive'
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'jetbrains'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
@@ -145,132 +123,156 @@ jobs:
build-scan-publish: true
build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service'
build-scan-terms-of-use-agree: 'yes'
add-job-summary: always
- name: Build Play Store release
run: ./gradlew bundleGoogleRelease assembleGoogleRelease
- name: Load Google secrets
env:
VERSION_CODE: ${{ needs.prepare-release-info.outputs.versionCode }}
GSERVICES_BASE64: ${{ secrets.GSERVICES }}
KEYSTORE_BASE64: ${{ secrets.KEYSTORE }}
KEYSTORE_FILENAME_SECRET: ${{ secrets.KEYSTORE_FILENAME }}
KEYSTORE_PROPERTIES_SECRET: ${{ secrets.KEYSTORE_PROPERTIES }}
DATADOG_APPLICATION_ID_SECRET: ${{ secrets.DATADOG_APPLICATION_ID }}
DATADOG_CLIENT_TOKEN_SECRET: ${{ secrets.DATADOG_CLIENT_TOKEN }}
GOOGLE_MAPS_API_KEY_SECRET: ${{ secrets.GOOGLE_MAPS_API_KEY }}
run: |
echo "Writing google-services.json"
echo "$GSERVICES_BASE64" | base64 --decode > ./app/google-services.json
echo "Writing keystore file for Google"
echo "$KEYSTORE_BASE64" | base64 --decode > ./app/$KEYSTORE_FILENAME_SECRET
echo "Writing keystore.properties for Google"
echo "$KEYSTORE_PROPERTIES_SECRET" > ./keystore.properties
echo "Writing other secrets to secrets.properties"
echo "datadogApplicationId=$DATADOG_APPLICATION_ID_SECRET" >> ./secrets.properties
echo "datadogClientToken=$DATADOG_CLIENT_TOKEN_SECRET" >> ./secrets.properties
echo "MAPS_API_KEY=$GOOGLE_MAPS_API_KEY_SECRET" >> ./secrets.properties
- name: Upload Play Store AAB artifact (for release job)
- name: Build Google Release Artifacts (AAB and APK)
run: |
./gradlew :app:bundleGoogleRelease :app:assembleGoogleRelease --parallel --continue --scan
env:
VERSION_NAME: ${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}
VERSION_CODE: ${{ needs.prepare-build-info.outputs.APP_VERSION_CODE }}
- name: Upload Google AAB artifact
uses: actions/upload-artifact@v4
with:
name: google-aab
path: app/build/outputs/bundle/googleRelease/app-google-release.aab
retention-days: 1
- name: Upload Play Store APK artifact (for release job)
- name: Upload Google APK artifact
uses: actions/upload-artifact@v4
with:
name: google-apk
path: app/build/outputs/apk/google/release/app-google-release.apk
retention-days: 1
# Job to create GitHub release and upload assets (runs after builds if enabled)
create-github-release:
needs: [ prepare-release-info, build-fdroid, build-google ]
publish-release:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
attestations: write
# Only run this job if the input create_github_release is true
if: github.repository == 'meshtastic/Meshtastic-Android' && github.event.inputs.create_github_release == 'true'
needs: [prepare-build-info, build-fdroid, build-google]
outputs:
RELEASE_UPLOAD_URL: ${{ steps.create_gh_release.outputs.upload_url }}
CHANGELOG: ${{ steps.generate_changelog.outputs.changelog }}
APP_VERSION_NAME: ${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}
APP_VERSION_CODE: ${{ needs.prepare-build-info.outputs.APP_VERSION_CODE }}
steps:
- name: Set up version info
id: set_version_info
run: |
echo "versionCode=${{ needs.prepare-release-info.outputs.versionCode }}" >> $GITHUB_ENV
echo "versionNameBase=${{ needs.prepare-release-info.outputs.versionNameBase }}" >> $GITHUB_ENV
echo "versionNameFdroid=${{ needs.prepare-release-info.outputs.versionNameBase }} (${{ needs.prepare-release-info.outputs.versionCode }}) fdroid" >> $GITHUB_ENV
echo "versionNameGoogle=${{ needs.prepare-release-info.outputs.versionNameBase }} (${{ needs.prepare-release-info.outputs.versionCode }}) google" >> $GITHUB_ENV
- name: Create version_info.txt
run: |
echo -e "versionCode=${{ env.versionCode }}\nversionNameBase=${{ env.versionNameBase }}" > ./version_info.txt
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: 'recursive'
- name: Download F-Droid APK
uses: actions/download-artifact@v5
with:
name: fdroid-apk
path: ./fdroid-apk-download
path: ./build-artifacts/fdroid
- name: Download Google AAB
uses: actions/download-artifact@v5
with:
name: google-aab
path: ./google-aab-download
path: ./build-artifacts/google/bundle
- name: Download Google APK
uses: actions/download-artifact@v5
with:
name: google-apk
path: ./google-apk-download
path: ./build-artifacts/google/apk
- name: Create GitHub release
uses: actions/create-release@v1
id: create_release_step
- name: Generate Changelog
id: generate_changelog
uses: mikepenz/release-changelog-builder-action@v5
with:
configuration: ".github/changelog-config.json"
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
ignorePreReleases: true
failOnError: true
fetchViaCommits: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Play Store Release Notes
if: steps.generate_changelog.outputs.changelog != ''
run: |
mkdir -p play_store_release_notes/en-US
echo "${{ steps.generate_changelog.outputs.changelog }}" > play_store_release_notes/en-US/default.txt
echo "${{ steps.generate_changelog.outputs.changelog }}" > changelog.txt # Also create a root changelog.txt for GitHub release
- name: Create version_info.txt
run: |
echo "versionNameBase=${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}" > ./version_info.txt
echo "versionCode=${{ needs.prepare-build-info.outputs.APP_VERSION_CODE }}" >> ./version_info.txt
- name: Create GitHub Release
id: create_gh_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
body: ${{ steps.generate_changelog.outputs.changelog }}
files: |
./build-artifacts/google/bundle/app-google-release.aab
./build-artifacts/google/apk/app-google-release.apk
./build-artifacts/fdroid/app-fdroid-release.apk
./version_info.txt
./changelog.txt
draft: true
prerelease: true
release_name: Meshtastic Android ${{ env.versionNameBase }} (${{ env.versionCode }}) alpha
tag_name: v${{ env.versionNameBase }}
commitish: ${{ github.event.inputs.branch }}
body: |
Version: ${{ env.versionNameBase }} (${{ env.versionCode }})
F-Droid version name: `${{ env.versionNameFdroid }}`
Google Play version name: `${{ env.versionNameGoogle }}`
Autogenerated by GitHub Action. Please review and edit before publishing.
prerelease: ${{ contains(github.ref_name, '-internal') || contains(github.ref_name, '-closed') || contains(github.ref_name, '-open') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add F-Droid APK to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_step.outputs.upload_url }}
asset_path: ./fdroid-apk-download/app-fdroid-release.apk
asset_name: ${{ needs.build-fdroid.outputs.apk_name }}
asset_content_type: application/vnd.android.package-archive
- name: Add Play Store AAB to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_step.outputs.upload_url }}
asset_path: ./google-aab-download/app-google-release.aab
asset_name: ${{ needs.build-google.outputs.aab_name }}
asset_content_type: application/octet-stream
- name: Add Play Store APK to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_step.outputs.upload_url }}
asset_path: ./google-apk-download/app-google-release.apk
asset_name: ${{ needs.build-google.outputs.apk_name }}
asset_content_type: application/vnd.android.package-archive
- name: Add version_info.txt to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_step.outputs.upload_url }}
asset_path: ./version_info.txt
asset_name: version_info.txt
asset_content_type: text/plain
# Attest the build artifacts for supply chain security.
# See: https://github.com/meshtastic/Meshtastic-Android/attestations
- name: Attest Build Provenance
uses: actions/attest-build-provenance@v2
with:
subject-path: |
./google-apk-download/app-google-release.apk
./google-aab-download/app-google-release.aab
./fdroid-apk-download/app-fdroid-release.apk
./build-artifacts/google/bundle/app-google-release.aab
./build-artifacts/google/apk/app-google-release.apk
./build-artifacts/fdroid/app-fdroid-release.apk
- name: Determine Play Store Track
id: get_track
run: |
TAG_NAME="${{ github.ref_name }}"
if [[ "$TAG_NAME" == *"-internal"* ]]; then
echo "track=qa" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" == *"-closed"* ]]; then
echo "track=newalpha" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" == *"-open"* ]]; then
echo "track=beta" >> $GITHUB_OUTPUT
else
echo "track=production" >> $GITHUB_OUTPUT
fi
- name: Upload AAB to Google Play
if: success() && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
uses: r0adkll/upload-google-play@v1.0.19
with:
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_JSON_KEY }}
packageName: com.geeksville.mesh
releaseFiles: ./build-artifacts/google/bundle/app-google-release.aab
track: ${{ steps.get_track.outputs.track }}
status: 'draft'
whatsNewDirectory: ./play_store_release_notes/en-US/