feat: add reusable Flutter build actions for android, ios, macos, windows, and linux
Update README Actions Table / update-readme (push) Successful in 7s
Update README Actions Table / update-readme (push) Successful in 7s
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
name: 'Flutter Build Android'
|
||||
description: 'Configures Android keystore signing, builds release AAB/APK artifacts, and optionally deploys to Google Play Console and Shorebird.'
|
||||
inputs:
|
||||
working_directory:
|
||||
description: 'Path to the Flutter app package directory (e.g., packages/hfw_flutter or .)'
|
||||
required: false
|
||||
default: '.'
|
||||
build_aab:
|
||||
description: 'Whether to build an Android App Bundle (.aab)'
|
||||
required: false
|
||||
default: 'true'
|
||||
build_apk:
|
||||
description: 'Whether to build a release APK (.apk)'
|
||||
required: false
|
||||
default: 'false'
|
||||
build_args:
|
||||
description: 'Extra arguments passed to flutter build appbundle / apk (e.g., --dart-define=...)'
|
||||
required: false
|
||||
default: ''
|
||||
artifact_prefix:
|
||||
description: 'Optional prefix for copied versioned artifacts in output_dir (e.g., hfw-android -> hfw-android-v1.0.0.apk)'
|
||||
required: false
|
||||
default: ''
|
||||
output_dir:
|
||||
description: 'Directory to copy versioned artifacts into when artifact_prefix is set'
|
||||
required: false
|
||||
default: 'artifacts'
|
||||
keystore_base64:
|
||||
description: 'Base64-encoded Android release keystore file'
|
||||
required: false
|
||||
default: ''
|
||||
key_alias:
|
||||
description: 'Android signing key alias'
|
||||
required: false
|
||||
default: ''
|
||||
key_password:
|
||||
description: 'Android signing key password'
|
||||
required: false
|
||||
default: ''
|
||||
store_password:
|
||||
description: 'Android keystore password'
|
||||
required: false
|
||||
default: ''
|
||||
google_play_service_account_json:
|
||||
description: 'Google Play service account JSON content for Play Store upload'
|
||||
required: false
|
||||
default: ''
|
||||
google_play_service_account_file:
|
||||
description: 'Fallback path to Google Play service account JSON file (relative to repo root)'
|
||||
required: false
|
||||
default: ''
|
||||
google_play_track:
|
||||
description: 'Google Play track to deploy to (internal, alpha, beta, production)'
|
||||
required: false
|
||||
default: 'beta'
|
||||
google_play_status:
|
||||
description: 'Google Play release status (completed, draft, inProgress, halted)'
|
||||
required: false
|
||||
default: 'completed'
|
||||
google_play_script:
|
||||
description: 'Path to the Dart Google Play upload script (relative to repo root)'
|
||||
required: false
|
||||
default: 'scripts/upload_play_store.dart'
|
||||
shorebird_token:
|
||||
description: 'Shorebird token for optional Shorebird release'
|
||||
required: false
|
||||
default: ''
|
||||
shorebird_artifact:
|
||||
description: 'Shorebird artifact type (apk or aab)'
|
||||
required: false
|
||||
default: 'apk'
|
||||
|
||||
outputs:
|
||||
version:
|
||||
description: 'Resolved package version from pubspec.yaml'
|
||||
value: ${{ steps.build.outputs.version }}
|
||||
aab_path:
|
||||
description: 'Path to the built AAB file'
|
||||
value: ${{ steps.build.outputs.aab_path }}
|
||||
apk_path:
|
||||
description: 'Path to the built APK file'
|
||||
value: ${{ steps.build.outputs.apk_path }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Configure Android Signing Keystore
|
||||
shell: bash
|
||||
env:
|
||||
WORK_DIR: ${{ inputs.working_directory }}
|
||||
KEYSTORE_BASE64: ${{ inputs.keystore_base64 }}
|
||||
KEY_ALIAS: ${{ inputs.key_alias }}
|
||||
KEY_PASSWORD: ${{ inputs.key_password }}
|
||||
STORE_PASSWORD: ${{ inputs.store_password }}
|
||||
run: |
|
||||
if [ -n "$KEYSTORE_BASE64" ]; then
|
||||
echo "Decoding Android Keystore..."
|
||||
mkdir -p "$WORK_DIR/android/app"
|
||||
echo "$KEYSTORE_BASE64" | base64 --decode > "$WORK_DIR/android/app/release.keystore"
|
||||
printf "storePassword=%s\nkeyPassword=%s\nkeyAlias=%s\nstoreFile=release.keystore\n" \
|
||||
"$STORE_PASSWORD" "$KEY_PASSWORD" "$KEY_ALIAS" > "$WORK_DIR/android/key.properties"
|
||||
echo "Configured $WORK_DIR/android/key.properties"
|
||||
else
|
||||
echo "Notice: keystore_base64 not configured. Building unsigned / default debug signing."
|
||||
fi
|
||||
|
||||
- name: Build Android Release Artifacts
|
||||
id: build
|
||||
shell: bash
|
||||
env:
|
||||
WORK_DIR: ${{ inputs.working_directory }}
|
||||
BUILD_AAB: ${{ inputs.build_aab }}
|
||||
BUILD_APK: ${{ inputs.build_apk }}
|
||||
BUILD_ARGS: ${{ inputs.build_args }}
|
||||
ARTIFACT_PREFIX: ${{ inputs.artifact_prefix }}
|
||||
OUTPUT_DIR: ${{ inputs.output_dir }}
|
||||
run: |
|
||||
ROOT_DIR="$(pwd)"
|
||||
VERSION=$(grep '^version: ' "$WORK_DIR/pubspec.yaml" | head -n 1 | cut -d ' ' -f 2 | tr -d '\r')
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
if [ "$BUILD_AAB" = "true" ]; then
|
||||
echo "Building Android App Bundle (AAB)..."
|
||||
# shellcheck disable=SC2086
|
||||
flutter build appbundle --release $BUILD_ARGS
|
||||
fi
|
||||
|
||||
if [ "$BUILD_APK" = "true" ]; then
|
||||
echo "Building Android APK..."
|
||||
# shellcheck disable=SC2086
|
||||
flutter build apk --release $BUILD_ARGS
|
||||
fi
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
AAB_REL="$WORK_DIR/build/app/outputs/bundle/release/app-release.aab"
|
||||
APK_REL="$WORK_DIR/build/app/outputs/flutter-apk/app-release.apk"
|
||||
AAB_REL="${AAB_REL#./}"
|
||||
APK_REL="${APK_REL#./}"
|
||||
|
||||
if [ -n "$ARTIFACT_PREFIX" ]; then
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
if [ -f "$AAB_REL" ]; then
|
||||
cp "$AAB_REL" "$OUTPUT_DIR/${ARTIFACT_PREFIX}-v${VERSION}.aab"
|
||||
AAB_OUT="$OUTPUT_DIR/${ARTIFACT_PREFIX}-v${VERSION}.aab"
|
||||
fi
|
||||
if [ -f "$APK_REL" ]; then
|
||||
cp "$APK_REL" "$OUTPUT_DIR/${ARTIFACT_PREFIX}-v${VERSION}.apk"
|
||||
APK_OUT="$OUTPUT_DIR/${ARTIFACT_PREFIX}-v${VERSION}.apk"
|
||||
fi
|
||||
echo "Collected Android artifacts for version $VERSION in $OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
echo "aab_path=${AAB_OUT:-$AAB_REL}" >> "$GITHUB_OUTPUT"
|
||||
echo "apk_path=${APK_OUT:-$APK_REL}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload AAB to Google Play Console
|
||||
shell: bash
|
||||
env:
|
||||
WORK_DIR: ${{ inputs.working_directory }}
|
||||
PLAY_STORE_JSON: ${{ inputs.google_play_service_account_json }}
|
||||
PLAY_STORE_FILE: ${{ inputs.google_play_service_account_file }}
|
||||
PLAY_TRACK: ${{ inputs.google_play_track }}
|
||||
PLAY_STATUS: ${{ inputs.google_play_status }}
|
||||
PLAY_SCRIPT: ${{ inputs.google_play_script }}
|
||||
run: |
|
||||
AAB_FILE="$WORK_DIR/build/app/outputs/bundle/release/app-release.aab"
|
||||
AAB_FILE="${AAB_FILE#./}"
|
||||
if [ ! -f "$AAB_FILE" ]; then
|
||||
echo "No AAB file found at $AAB_FILE; skipping Google Play upload."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DEFAULT_SA_FILE="$WORK_DIR/android/app/google_play.json"
|
||||
DEFAULT_SA_FILE="${DEFAULT_SA_FILE#./}"
|
||||
SA_FILE="${PLAY_STORE_FILE:-$DEFAULT_SA_FILE}"
|
||||
|
||||
if [ -n "$PLAY_STORE_JSON" ] && [ -f "$PLAY_SCRIPT" ]; then
|
||||
echo "Google Play service account secret detected. Uploading AAB to track '$PLAY_TRACK'..."
|
||||
echo "$PLAY_STORE_JSON" > /tmp/google_play_service_account.json
|
||||
dart "$PLAY_SCRIPT" \
|
||||
--aab "$AAB_FILE" \
|
||||
--service-account /tmp/google_play_service_account.json \
|
||||
--track "$PLAY_TRACK" \
|
||||
--status "$PLAY_STATUS"
|
||||
rm -f /tmp/google_play_service_account.json
|
||||
elif [ -f "$SA_FILE" ] && [ -f "$PLAY_SCRIPT" ]; then
|
||||
echo "Using repository service account file ($SA_FILE) for Google Play upload to track '$PLAY_TRACK'..."
|
||||
dart "$PLAY_SCRIPT" \
|
||||
--aab "$AAB_FILE" \
|
||||
--service-account "$SA_FILE" \
|
||||
--track "$PLAY_TRACK" \
|
||||
--status "$PLAY_STATUS"
|
||||
else
|
||||
echo "Skipping Google Play upload (credentials or upload script not configured)."
|
||||
fi
|
||||
|
||||
- name: Release via Shorebird (Optional)
|
||||
if: inputs.shorebird_token != ''
|
||||
shell: bash
|
||||
env:
|
||||
WORK_DIR: ${{ inputs.working_directory }}
|
||||
SHOREBIRD_TOKEN: ${{ inputs.shorebird_token }}
|
||||
SHOREBIRD_ARTIFACT: ${{ inputs.shorebird_artifact }}
|
||||
run: |
|
||||
if [ -n "$SHOREBIRD_TOKEN" ]; then
|
||||
ROOT_DIR="$(pwd)"
|
||||
cd "$WORK_DIR"
|
||||
flutter pub global activate shorebird_cli
|
||||
shorebird release android --artifact="$SHOREBIRD_ARTIFACT"
|
||||
cd "$ROOT_DIR"
|
||||
fi
|
||||
Reference in New Issue
Block a user