cb5ce44bbe
- trigger: add branches: [dev, main] so analyze+test run on every push, not just release tags. Build job stays tag-gated via if: startsWith(github.ref, 'refs/tags/') - pin Flutter to 3.41.6 instead of floating :stable for reproducible release builds - concurrency: cancel in-progress non-tag runs - permissions: contents: read default, contents: write scoped to build - extract release publish logic to scripts/publish_apk_release.sh so it's testable locally (bash -x with env vars) and the YAML stays readable. Adds set -euo pipefail + curl -f so failures surface instead of getting swallowed by || echo "skipped" - drop the broken artifact upload step (silently swallowed errors)
112 lines
3.9 KiB
YAML
112 lines
3.9 KiB
YAML
# CI runs first; build only proceeds if all checks pass.
|
|
#
|
|
# Push to dev or main: flutter analyze + flutter test
|
|
# Tag v* (release): gates + signed APK build + attach to Forgejo Release
|
|
#
|
|
# To cut a release:
|
|
# Create a release via the Forgejo UI on main with a v* tag name.
|
|
# The tag push triggers this workflow; the build job attaches the APK.
|
|
#
|
|
# Note: JavaScript actions (actions/checkout, actions/upload-artifact) cannot run
|
|
# inside the Flutter container because it has no Node.js. All steps use shell
|
|
# commands directly instead.
|
|
#
|
|
# Required secrets (repo → Settings → Secrets → Actions):
|
|
# RELEASE_TOKEN — Forgejo PAT with write:repository scope
|
|
# RELEASE_KEYSTORE_BASE64 — base64 of the signing keystore
|
|
# RELEASE_KEYSTORE_PASSWORD — keystore + key password
|
|
# RELEASE_KEY_ALIAS — key alias within the keystore
|
|
name: CI & Build
|
|
|
|
on:
|
|
push:
|
|
branches: [dev, main]
|
|
tags: ["v*"]
|
|
|
|
# Cancel older runs on the same branch when a newer push lands. Tag runs
|
|
# are never cancelled so a release build can't kill itself mid-flight.
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
|
|
# Least-privilege default. The build job upgrades to contents: write
|
|
# so it can attach the APK to a Forgejo release.
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
analyze:
|
|
name: Analyze & test
|
|
runs-on: py3.12-node22
|
|
container:
|
|
# Pinned to a specific Flutter version for reproducible builds.
|
|
# Floating :stable means a random Flutter minor bump could change
|
|
# analyzer output or break the build without any commit landing.
|
|
# Bump this line (and verify locally with `flutter --version`)
|
|
# when you intentionally want a newer Flutter.
|
|
image: ghcr.io/cirruslabs/flutter:3.41.6
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git clone "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" .
|
|
git checkout "$GITHUB_SHA"
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Analyze
|
|
run: flutter analyze
|
|
|
|
- name: Test
|
|
run: flutter test
|
|
|
|
build:
|
|
name: Build release APK
|
|
needs: [analyze]
|
|
# Only tag pushes produce a signed release build. dev/main pushes
|
|
# run the gates above and stop there.
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
runs-on: py3.12-node22
|
|
container:
|
|
image: ghcr.io/cirruslabs/flutter:3.41.6
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git clone "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" .
|
|
git checkout "$GITHUB_SHA"
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Set up release signing
|
|
env:
|
|
KEYSTORE_B64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }}
|
|
STORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
|
|
KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}
|
|
run: |
|
|
echo "$KEYSTORE_B64" | base64 -d > android/app/release.jks
|
|
printf 'storePassword=%s\nkeyPassword=%s\nkeyAlias=%s\nstoreFile=release.jks\n' \
|
|
"$STORE_PASSWORD" "$STORE_PASSWORD" "$KEY_ALIAS" > android/key.properties
|
|
|
|
- name: Build release APK
|
|
run: |
|
|
# Derive version from the tag (e.g. v26.03.12 → name=26.03.12 number=260312)
|
|
TAG="${{ github.ref_name }}"
|
|
BUILD_NAME="${TAG#v}"
|
|
BUILD_NUMBER=$(echo "$BUILD_NAME" | tr -d '.')
|
|
flutter build apk --release \
|
|
--build-name="$BUILD_NAME" \
|
|
--build-number="$BUILD_NUMBER"
|
|
|
|
- name: Publish Forgejo release
|
|
# Release-publish logic lives in a shell script so it's
|
|
# testable locally (bash -x scripts/publish_apk_release.sh
|
|
# with env vars set) instead of trapped in YAML.
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
TAG: ${{ github.ref_name }}
|
|
APK: build/app/outputs/flutter-apk/app-release.apk
|
|
run: bash scripts/publish_apk_release.sh
|