ci(release): add build provenance and streamline release process (#3217)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
pull/3219/head
James Rich 2025-09-26 20:06:56 -05:00 zatwierdzone przez GitHub
rodzic a8b0327c41
commit ab18e424b1
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 104 dodań i 126 usunięć

Wyświetl plik

@ -28,13 +28,11 @@ jobs:
with:
fetch-depth: 0
submodules: 'recursive'
- 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:
@ -64,13 +62,11 @@ jobs:
with:
fetch-depth: 0
submodules: 'recursive'
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'jetbrains'
- name: Setup Gradle
if: contains(github.ref_name, '-internal')
uses: gradle/actions/setup-gradle@v4
@ -142,6 +138,14 @@ jobs:
path: app/build/outputs/apk/google/release/app-google-release.apk
retention-days: 1
- name: Attest Google artifacts provenance
if: contains(github.ref_name, '-internal')
uses: actions/attest-build-provenance@v3
with:
subject-path: |
app/build/outputs/bundle/googleRelease/app-google-release.aab
app/build/outputs/apk/google/release/app-google-release.apk
release-fdroid:
if: contains(github.ref_name, '-internal')
runs-on: ubuntu-latest
@ -152,13 +156,11 @@ jobs:
with:
fetch-depth: 0
submodules: 'recursive'
- 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:
@ -195,27 +197,74 @@ jobs:
path: app/build/outputs/apk/fdroid/release/app-fdroid-release.apk
retention-days: 1
create-github-release:
if: contains(github.ref_name, '-internal')
- name: Attest F-Droid APK provenance
uses: actions/attest-build-provenance@v3
with:
subject-path: app/build/outputs/apk/fdroid/release/app-fdroid-release.apk
create-internal-release:
runs-on: ubuntu-latest
needs: [release-google, release-fdroid]
needs: [prepare-build-info, release-google, release-fdroid]
if: contains(github.ref_name, '-internal')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v5
with:
path: ./artifacts
- name: Get artifact paths
id: artifact_paths
run: |
paths=""
if [ -f ./artifacts/google-aab/app-google-release.aab ]; then
paths="${paths} ./artifacts/google-aab/app-google-release.aab"
fi
if [ -f ./artifacts/google-apk/app-google-release.apk ]; then
paths="${paths} ./artifacts/google-apk/app-google-release.apk"
fi
if [ -f ./artifacts/fdroid-apk/app-fdroid-release.apk ]; then
paths="${paths} ./artifacts/fdroid-apk/app-fdroid-release.apk"
fi
echo "paths=${paths}" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
tag_name: v${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}
name: ${{ github.ref_name }}
generate_release_notes: true
files: |
./artifacts/google-aab/app-google-release.aab
./artifacts/google-apk/app-google-release.apk
./artifacts/fdroid-apk/app-fdroid-release.apk
files: ${{ steps.artifact_paths.outputs.paths }}
draft: true
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
promote-release:
runs-on: ubuntu-latest
needs: [prepare-build-info, release-google]
if: "!contains(github.ref_name, '-internal')"
steps:
- name: Determine Release Properties
id: release_properties
run: |
TAG_NAME="${{ github.ref_name }}"
if [[ "$TAG_NAME" == *"-closed"* ]]; then
echo "draft=false" >> $GITHUB_OUTPUT
echo "prerelease=true" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" == *"-open"* ]]; then
echo "draft=false" >> $GITHUB_OUTPUT
echo "prerelease=true" >> $GITHUB_OUTPUT
else
echo "draft=false" >> $GITHUB_OUTPUT
echo "prerelease=false" >> $GITHUB_OUTPUT
fi
- name: Update GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.prepare-build-info.outputs.APP_VERSION_NAME }}
name: ${{ github.ref_name }}
draft: ${{ steps.release_properties.outputs.draft }}
prerelease: ${{ steps.release_properties.outputs.prerelease }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Wyświetl plik

@ -1,129 +1,58 @@
# Meshtastic-Android Release Process
# Meshtastic-Android Release Process (Condensed)
This document outlines the steps for releasing a new version of the Meshtastic-Android application. The process is heavily automated using GitHub Actions and Fastlane, triggered by pushing a Git tag from a `release/*` branch.
This guide summarizes the steps for releasing a new version of Meshtastic-Android. The process is automated via GitHub Actions and Fastlane, triggered by pushing a Git tag from a `release/*` branch.
## High-Level Overview
## Overview
- **Tagging:** Push a tag (`vX.X.X[-track.Y]`) from a `release/*` branch to start the release workflow.
- **CI Automation:** Builds both flavors, uploads to Google Play (correct track), and creates/updates a draft GitHub release.
- **Changelog:** Release notes are auto-generated from PR labels via [`.github/release.yml`](.github/release.yml). Label PRs for accurate changelogs.
- **Draft Release:** All tags for the same base version (e.g., `v2.3.5`) update the same draft release. The release title uses the full tag (e.g., `v2.3.5-internal.1`).
The automation is designed to be safe, repeatable, and efficient. When a new tag matching the `v*` pattern is pushed from a release branch, the `release.yml` GitHub Action workflow will:
## Tagging & Tracks
- **Internal:** `vX.X.X-internal.Y`
- **Closed:** `vX.X.X-closed.Y`
- **Open:** `vX.X.X-open.Y`
- **Production:** `vX.X.X`
- Increment `.Y` for fixes/iterations.
1. **Determine Versioning:** A `versionName` is derived from the Git tag, and a unique, always-increasing `versionCode` is generated from the current timestamp.
2. **Build in Parallel:** Two jobs run simultaneously to build the `google` and `fdroid` flavors of the app.
3. **Deploy to Google Play:** The `google` build job uses Fastlane to automatically upload the Android App Bundle (AAB) to the correct track on the Google Play Console, based on the tag name.
4. **Create a Draft GitHub Release:** After both builds are complete, a final job gathers the artifacts (AAB, Google APK, and F-Droid APK) and creates a single, consolidated **draft** release on GitHub.
Finalizing and publishing the release on both GitHub and the Google Play Console are the only **manual steps**.
## Versioning and Tagging Strategy
The entire process is driven by your Git tagging strategy. Tags **must** start with `v` and should follow Semantic Versioning. Use the correct suffix for the desired release track:
* **Internal Track:** `vX.X.X-internal.Y` (e.g., `v2.3.5-internal.1`)
* **Closed Track:** `vX.X.X-closed.Y` (e.g., `v2.3.5-closed.1`)
* **Open Track:** `vX.X.X-open.Y` (e.g., `v2.3.5-open.1`)
* **Production Track:** `vX.X.X` (e.g., `v2.3.5`)
The `.Y` suffix is for iterations. If you find a bug in `v2.3.5-closed.1`, you would fix it on the release branch and tag the new commit as `v2.3.5-closed.2`.
## Core Release Workflow
The entire release process happens on a dedicated release branch, allowing `main` to remain open for new feature development.
### 1. Creating the Release Branch
First, create a `release/X.X.X` branch from a stable `main`. This branch is now "feature frozen." Only critical bug fixes should be added.
As a housekeeping step, it's recommended to update the `VERSION_NAME_BASE` in `build-logic/convention/src/main/kotlin/com/geeksville/mesh/buildlogic/Configs.kt` on this new branch. While the final release version is set by the Git tag in CI, this ensures local development builds have a sensible version name.
## Release Steps
1. **Branch:** Create `release/X.X.X` from `main`. Only critical fixes allowed.
2. **Tag & Push:** Tag the release commit and push (see below).
3. **CI:** Wait for CI to finish. Artifacts are uploaded, and a draft GitHub release is created/updated.
4. **Verify:** Check Google Play Console and GitHub draft release.
5. **Promote:** Tag the same commit for the next track as needed.
6. **Finalize:**
- **Production:** Publish the GitHub release, then promote in Google Play Console.
- **Other tracks:** Verify with testers.
7. **Merge:** After production, merge `release/X.X.X` back to `main` and delete the branch.
## Tagging Example
```bash
git checkout main
git pull origin main
git checkout -b release/2.3.5
# (Now, update the version in buildSrc, commit the change, and then push)
git push origin release/2.3.5
```
### 2. Testing and Iterating on a Track
Start by deploying to the `internal` track to begin testing.
**A. Create and Push a Tag:**
Tag a commit on the release branch to trigger the automation.
```bash
# Ensure you are on the release branch
git checkout release/2.3.5
# Tag for the "Internal" track
# On release branch
git tag v2.3.5-internal.1
git push origin v2.3.5-internal.1
```
**B. Monitor and Verify:**
Monitor the workflow in GitHub Actions. Once complete, verify the build in the Google Play Console and with your internal testers.
**C. Apply Fixes (If Necessary):**
If a bug is found, commit the fix to the release branch. Remember to also cherry-pick or merge this fix back to `main`. Then, create an iterated tag.
```bash
# Assuming you've committed a fix
# For fixes:
git tag v2.3.5-internal.2
git push origin v2.3.5-internal.2
```
This will upload a new, fixed build to the same `internal` track. Repeat this process until the build is stable.
### 3. Promoting to the Next Track
Once you are confident that a build is stable, you can "promote" it to a wider audience by tagging the **exact same commit** for the next track.
```bash
# The commit tagged as v2.3.5-internal.2 is stable and ready for the "Closed" track
# Promote:
git tag v2.3.5-closed.1
git push origin v2.3.5-closed.1
```
This triggers the workflow again, but this time it will send the build to the `NewAlpha` track for your closed testers. You can then continue the cycle of testing, fixing, and promoting all the way to production.
### 4. Finalizing the Release
After the final production release is complete and verified, open a Pull Request to merge the release branch back into `main`. This ensures any hotfixes applied during the release cycle are properly reviewed and integrated.
## Manual Checklist
- [ ] Verify build in Google Play Console
- [ ] Review and publish GitHub draft release (for production)
- [ ] Merge release branch to main after production
- [ ] Label PRs for changelog accuracy
* **Title:** `Release/2.3.5`
* **Base Branch:** `main`
* **Compare Branch:** `release/2.3.5`
## Build Attestations & Provenance
Once the PR is approved and merged, you can safely delete the release branch.
All release artifacts are accompanied by explicit GitHub build attestations (provenance). After each artifact is uploaded in the release workflow, a provenance attestation is generated using the `actions/attest-build-provenance` action. This provides cryptographic proof that the artifacts were built by our trusted GitHub Actions workflow, ensuring supply chain integrity and allowing users to verify the origin of each release.
## Manual Finalization Steps
- Attestations are generated immediately after each artifact upload in the workflow.
- You can view and verify provenance in the GitHub UI under each release asset.
- For more details, see [GitHub's documentation on build provenance](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#provenance-attestations).
### For Internal Releases
> **Note:** The GitHub release is always attached to the base version tag (e.g., `v2.3.5`). All track tags for the same version update the same draft release. Look for the draft under the base version tag.
* **Automated Action:** The AAB is uploaded to the `internal` track and is **rolled out to 100% of testers automatically**.
* **Your Manual Step:**
1. **Verify the build** in the Google Play Console and with your internal testers.
### For Closed Releases
* **Automated Action:** The AAB is uploaded to the `NewAlpha` track and is **rolled out to 100% of testers automatically**.
* **Your Manual Step:**
1. **Verify the build** in the Google Play Console and with your closed track testers.
### For Open Releases
* **Automated Action:** The AAB is uploaded to the `beta` track and begins a **staged rollout to 25% of your open track testers automatically**.
* **Your Manual Steps:**
1. **Verify the build** in the Google Play Console.
2. **(Optional)** Go to the GitHub "Releases" page, find the **draft release**, and publish it so your open track testers can see the official release notes.
### For Production Releases
* **Automated Action:**
* The AAB is uploaded to the `production` track in a **draft** state. It is **not** rolled out to any users.
* A corresponding **draft** release is created on GitHub with all build artifacts.
* **Your Manual Steps:**
1. **Publish on GitHub First:** Go to the GitHub "Releases" page and find the draft. Review the release notes and artifacts, then **Publish release**. This makes the release notes publicly visible.
2. **Promote on Google Play Second:** *After* publishing on GitHub, go to your Google Play Console. Find the draft release, review it, and then proceed to **start the rollout to production**.
## Monitoring the Release
After a release has been rolled out to users (especially for Open and Production), it is crucial to monitor its performance.
* **Google Play Console:** Keep a close eye on the **Vitals** section for your app. Pay special attention to the crash rate and ANR (Application Not Responding) rate. A sudden spike in these numbers is a strong indicator of a problem.
* **Datadog:** Check your Datadog dashboards for any unusual trends or new errors that may have been introduced with the release.
* **Crashlytics:** Review crash reports in Firebase Crashlytics to identify any new issues that users may be experiencing.
* **User Reviews:** Monitor user reviews on the Google Play Store for any negative feedback or reports of bugs.
* **Community Feedback:** Monitor Discord, GitHub Issues, and community forums for feedback from users who have received the update.
If you identify a critical issue, be prepared to halt the rollout in the Google Play Console and tag a new, fixed version.
> **Best Practice:** Always promote the last verified build from the previous track to the next track. Do not introduce new changes between tracks unless absolutely necessary. This ensures consistency, traceability, and minimizes risk.