Skip to content

Instantly share code, notes, and snippets.

@ThomasAunvik
Created October 27, 2024 16:48
Show Gist options
  • Save ThomasAunvik/0404fcd92ac65c622eead47d727788ba to your computer and use it in GitHub Desktop.
Save ThomasAunvik/0404fcd92ac65c622eead47d727788ba to your computer and use it in GitHub Desktop.
Build Action
name: Build and Publish
on:
push:
branches:
- release
- staging
workflow_dispatch:
inputs:
version-code:
description: "Optional. Build number to use. Overrides default of GitHub run number."
required: false
type: number
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JAVA_VERSION: 17
GITHUB_ACTION_RUN_URL: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
DEPLOY_PRODUCTION: ${{ github.ref == 'refs/heads/release' }}
jobs:
build:
strategy:
fail-fast: false
matrix:
build: [web, appbundle, ipa]
include:
- build: web
os: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/release' && 'Production' || 'Staging' }}
args: --wasm --no-strip-wasm
- build: appbundle
os: ubuntu-latest
environment: Production
- build: ipa
os: macos-latest
environment: Production
args: --export-options-plist=ios/GithubActionsExportOptions.plist
environment: ${{ matrix.environment }}
name: Build ${{ matrix.build }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
lfs: true
- name: Cache Gradle files
uses: actions/cache@v4
if: ${{ matrix.build == 'appbundle' }}
with:
path: |
~/android/.gradle/caches
~/android/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', '**/libs.versions.toml') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Cache iOS Pod files
uses: actions/cache@v4
if: ${{ matrix.build == 'ipa' }}
with:
path: |
ios/Pods
ios/build/ios
key: ${{ runner.os }}-iospods-${{ hashFiles('ios/Podfile.lock', 'ios/Podfile') }}
restore-keys: |
${{ runner.os }}-iospods-
- name: Set up JDK 17
uses: actions/setup-java@v4
if: ${{ matrix.build == 'appbundle' }}
with:
distribution: 'temurin'
java-version: ${{ env.JAVA_VERSION }}
- name: Setup Android SDK
uses: android-actions/setup-android@v3
if: ${{ matrix.build == 'appbundle' }}
with:
accept-android-sdk-licenses: true
log-accepted-android-sdk-licenses: false
- name: Flutter Environment
uses: subosito/[email protected]
with:
channel: master
flutter-version-file: pubspec.yaml
cache: true
- name: Fetch Packages
run: |
flutter clean
flutter pub get
- uses: Azure/login@v2
if: ${{ matrix.build == 'appbundle' || matrix.build == 'ipa' }}
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# https://github.com/Azure/get-keyvault-secrets/issues/33#issuecomment-1219146161
- name: Android Secrets
id: androidvault
if: ${{ matrix.build == 'appbundle' }}
env:
VAULT_NAME: Vault
run: |
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name ANDROID-KEYSTORE-BASE64 --file android/app/keystore.b64.jks
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name ANDROID-GOOGLE-SERVICES --file android/app/google-services.json
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name ANDROID-KEY-PROPERTIES --file android/key.properties
cat android/app/keystore.b64.jks | base64 --decode > android/app/keystore.jks
- name: Generate Env
env:
APPENV_THINGY: ${{ vars.APPENV__THINGY }}
run: |
while IFS='=' read -r name value ; do
if [[ $name == 'APPENV_'* ]]; then
echo "$name=$value" >> .env
fi
done < <(env)
- name: Azure iOS Secrets
id: iosvault
if: ${{ matrix.build == 'ipa' }}
env:
VAULT_NAME: Vault
run: |
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name IOS-BUILD-CERTIFICATE --file $RUNNER_TEMP/build_certificate.b64.p12
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name IOS-BUILD-CERTIFICATE-PASSWORD --file $RUNNER_TEMP/build_certificate_pass.txt
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name IOS-MOBILE-PROVISIONING-PROFILE --file $RUNNER_TEMP/temp.b64.mobileprovision
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name IOS-GITHUB-KEYCHAIN-PASSWORD --file $RUNNER_TEMP/keychainpass.txt
az keyvault secret download --vault-name $VAULT_NAME --encoding utf-8 --name IOS-GOOGLE-SERVICE-INFO-PLIST --file ios/Runner/GoogleService-Info.plist
cat $RUNNER_TEMP/build_certificate.b64.p12 | base64 --decode > $RUNNER_TEMP/build_certificate.p12
cat $RUNNER_TEMP/temp.b64.mobileprovision | base64 --decode > $RUNNER_TEMP/build_pp.mobileprovision
- name: Install iOS Certificates
if: ${{ matrix.build == 'ipa' }}
run: |
IOS_GITHUB_KEYCHAIN_PASSWORD=$(cat $RUNNER_TEMP/keychainpass.txt)
IOS_BUILD_CERTIFICATE_PASSWORD=$(cat $RUNNER_TEMP/build_certificate_pass.txt)
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
# create temporary keychain
security create-keychain -p "$IOS_GITHUB_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$IOS_GITHUB_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$IOS_BUILD_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$IOS_GITHUB_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
security find-identity -v
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
ls -al ~/Library/MobileDevice/Provisioning\ Profiles
cat ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision
- name: iOS MapBox SDK Token
uses: extractions/netrc@v2
if: ${{ matrix.build == 'ipa' }}
with:
machine: api.mapbox.com
username: mapbox
password: ${{ secrets.MAPBOX_SDK_ACCESS_TOKEN }}
- name: Update iOS Pods
if: ${{ matrix.build == 'ipa' }}
working-directory: ios
run: |
flutter precache --ios
pod install
- name: Build ${{ matrix.build }}
run: |
DEFAULT_VERSION_CODE=$((1000+$GITHUB_RUN_NUMBER))
VERSION_CODE=${{ inputs.version-code || '$DEFAULT_VERSION_CODE' }}
flutter build ${{matrix.build}} ${{ matrix.args }} \
--release \
--build-number="$VERSION_CODE" \
--dart-define-from-file .env
- name: Archive IPA
uses: actions/upload-artifact@v4
if: ${{ matrix.build == 'ipa' }}
with:
name: ${{ matrix.build }}
path: build/ios/ipa/appname.ipa
- name: Archive Appbundle
uses: actions/upload-artifact@v4
if: ${{ matrix.build == 'appbundle' }}
with:
name: ${{ matrix.build }}
path: |
build/app/outputs/bundle/release/*.aab
build/app/outputs/mapping/release/mapping.txt
build/app/intermediates/merged_native_libs/release/mergeReleaseNativeLibs/out/lib
- name: Archive Web
uses: actions/upload-artifact@v4
if: ${{ matrix.build == 'web' }}
with:
name: ${{ matrix.build }}
path: |
staticwebapp.config.json
build/web
- name: Clean up keychain and provisioning profile
if: ${{ always() && matrix.build == 'ipa' }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision
deploy-web:
name: Deploy Web
environment: ${{ github.ref == 'refs/heads/release' && 'Production' || 'Staging' }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Download Web Artifact
uses: actions/download-artifact@v4
with:
name: web
path: artifact
- name: Display structure of downloaded files
run: ls -R
- name: Deploy Web
uses: Azure/static-web-apps-deploy@v1
id: builddeploy
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: artifact/build/web # App source code path
config_file_location: artifact
skip_app_build: true
production_branch: release
###### End of Repository/Build Configurations ######
deploy-android:
name: Deploy Android
environment: Production
runs-on: ubuntu-latest
needs: build
steps:
- name: Download Web Artifact
uses: actions/download-artifact@v4
with:
name: appbundle
path: artifact
- name: Display structure of downloaded files
run: ls -R
- name: Upload to Google Play
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.ANDROID_SERVICE_ACCOUNT }}
packageName: com.app.bundle
releaseFiles: artifact/outputs/bundle/release/*.aab
track: ${{ env.DEPLOY_PRODUCTION && 'production' || 'internal' }}
status: draft
mappingFile: artifact/outputs/mapping/release/mapping.txt
debugSymbols: artifact/intermediates/merged_native_libs/release/mergeReleaseNativeLibs/out/lib
deploy-ios:
name: Deploy iOS
environment: Production
runs-on: macos-latest
needs: build
steps:
- name: Download Web Artifact
uses: actions/download-artifact@v4
with:
name: ipa
path: artifact
- name: Display structure of downloaded files
run: ls -R
- name: Upload to TestFlight
uses: apple-actions/upload-testflight-build@v1
with:
app-path: 'artifact/appname.ipa'
issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}
api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment