build: new architecture, fix sentry (again), ios build cache, fix husky #1214
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Fastlane | |
on: | |
push: | |
tags: | |
- "v*" | |
pull_request: | |
types: | |
- opened | |
- reopened | |
- synchronize | |
workflow_dispatch: # allow manual run | |
inputs: | |
push_to_testflight: | |
type: boolean | |
description: Upload to TestFlight | |
required: true | |
default: false | |
push_to_playstore: | |
type: choice | |
description: Push to PlayStore | |
options: | |
- 'false' | |
- internal | |
- beta | |
- production | |
required: true | |
version: | |
type: string | |
description: App version (vXX.YY.ZZ) | |
required: true | |
default: LATEST | |
build_piece: | |
type: string | |
description: Build piece (last 2 digits of build_no) | |
required: true | |
create_release: | |
type: boolean | |
description: Create release | |
required: true | |
default: false | |
jobs: | |
configure: | |
name: Configure | |
runs-on: ubuntu-latest | |
outputs: | |
version: ${{ steps.configure.outputs.version }} | |
build_no: ${{ steps.configure.outputs.build_no }} | |
push_to_testflight: ${{ steps.configure.outputs.push_to_testflight }} | |
push_to_playstore: ${{ steps.configure.outputs.push_to_playstore }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Get version from tag (new release) | |
id: tag_version | |
run: echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT | |
if: | | |
github.event_name == 'push' && | |
github.event.repository.full_name == github.repository && | |
github.ref_type == 'tag' | |
- name: Get version from last release | |
id: last_release | |
uses: pozetroninc/github-action-get-latest-release@master | |
with: | |
repository: ${{ github.repository }} | |
excludes: draft | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Gather workflow info | |
id: configure | |
run: | | |
VERSION="" | |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
# On pull_request event, no need to publish | |
PUSH_TESTFLIGHT=false | |
PUSH_PLAYSTORE=false | |
elif [[ "${{ steps.tag_version.outputs.version }}" != "" ]]; then | |
# On tag push (release), we're in production | |
PUSH_TESTFLIGHT=true | |
PUSH_PLAYSTORE="${{ vars.PLAYSTORE_RELEASE_TRACK }}" | |
VERSION="${{ steps.tag_version.outputs.version }}" | |
BUILD_PIECE=90 | |
elif [[ "${{ github.event.inputs.version }}" != "" ]]; then | |
# On repo manual dispatch | |
PUSH_TESTFLIGHT="${{ github.event.inputs.push_to_testflight }}" | |
PUSH_PLAYSTORE="${{ github.event.inputs.push_to_playstore }}" | |
if [[ "${{ github.event.inputs.version }}" == "LATEST" && "${{ steps.last_release.outputs.release }}" != "" ]]; then | |
VERSION="${{ steps.last_release.outputs.release }}" | |
else | |
VERSION="${{ github.event.inputs.version }}" | |
fi | |
BUILD_PIECE="${{ github.event.inputs.build_piece }}" | |
elif [[ "${{ steps.last_release.outputs.release }}" != "" ]]; then | |
# we're supposed to be on push on main (e.g. pr merge) here | |
PUSH_TESTFLIGHT=true | |
PUSH_PLAYSTORE=beta | |
VERSION="${{ steps.last_release.outputs.release }}" | |
BUILD_PIECE=$(git rev-list $VERSION.. --count) | |
else | |
echo "UNHANDLED EVENT. CANNOT CONFIG SAFELY." | |
exit 1 | |
fi | |
if [[ "$BUILD_PIECE" != "" && ! "$BUILD_PIECE" =~ ^[0-9]{1,2}$ ]]; then | |
echo "INVALID BUILD PIECE FORMAT: $BUILD_PIECE" | |
exit 1 | |
fi | |
if [[ "$VERSION" =~ ^v([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,2})$ ]]; then | |
MAJOR=${BASH_REMATCH[1]} | |
MINOR=${BASH_REMATCH[2]} | |
SUBV=${BASH_REMATCH[3]} | |
BUILD_NO=$(( MAJOR*1000000 + MINOR*10000 + SUBV*100 + BUILD_PIECE )) | |
echo "build_no=$BUILD_NO" >> $GITHUB_OUTPUT | |
echo "version=$MAJOR.$MINOR.$SUBV" >> $GITHUB_OUTPUT | |
elif [[ "$VERSION" != "" ]]; then | |
echo "INVALID VERSION FORMAT: $VERSION" | |
exit 2 | |
fi | |
echo "push_to_playstore=$PUSH_PLAYSTORE" >> $GITHUB_OUTPUT | |
echo "push_to_testflight=$PUSH_TESTFLIGHT" >> $GITHUB_OUTPUT | |
echo "CONFIGURED:" | |
cat $GITHUB_OUTPUT | |
- name: Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: .nvmrc | |
- name: Cache node modules | |
uses: actions/cache@v4 | |
with: | |
path: ./node_modules | |
key: ${{ runner.os }}-npm-${{ hashFiles('./package-lock.json') }} | |
- name: Setup .npmrc | |
run: printf '@polito:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}\n' > .npmrc | |
- name: Install npm dependencies | |
run: npm install | |
build-android: | |
name: ${{ needs.configure.outputs.push_to_playstore == 'false' && 'Build' || 'Build & Deploy' }} Android | |
needs: configure | |
runs-on: ubuntu-latest | |
env: | |
LANG: en_US.UTF-8 | |
CI: 'true' | |
BUILD_NO: ${{ needs.configure.outputs.build_no }} | |
APP_VERSION: ${{ needs.configure.outputs.version }} | |
SUPPLY_GOOGLE_JSON_PATH: './pc-api-secret.json' | |
KEYSTORE_PW: ${{ secrets.ANDROID_KEYSTORE_PW }} | |
KEYSTORE_PATH: './keystore.jks' | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set .env | |
run: | |
echo "MAPBOX_TOKEN=${{ secrets.MAPBOX_TOKEN }}" >> .env | |
- name: Set local.properties | |
run: | |
echo "MAPBOX_DOWNLOADS_TOKEN=${{ secrets.MAPBOX_TOKEN }}" >> android/local.properties | |
- name: Gradle Wrapper Validation | |
uses: gradle/actions/wrapper-validation@v3 | |
- name: Setup Ruby | |
uses: ruby/setup-ruby@v1 | |
with: | |
bundler-cache: true # runs 'bundle install' and caches installed gems automatically | |
- name: Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: .nvmrc | |
- name: Cache node modules | |
uses: actions/cache@v4 | |
with: | |
path: ./node_modules | |
key: ${{ runner.os }}-npm-${{ hashFiles('./package-lock.json') }} | |
- name: Cache Gradle artifacts | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
restore-keys: ${{ runner.os }}-gradle- | |
- name: Setup .npmrc | |
run: printf '@polito:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}\n' > .npmrc | |
- name: Enforce version | |
run: npm version "$APP_VERSION" --no-git-tag-version | |
- name: Install npm dependencies | |
run: npm install | |
- name: Prepare fastlane | |
working-directory: ./android | |
run: | | |
echo "${{ secrets.SUPPLY_GOOGLE_JSON_SECRET }}" | base64 -d > ${SUPPLY_GOOGLE_JSON_PATH} | |
echo "${{ secrets.ANDROID_KEYSTORE_B64 }}" | base64 -d > ${KEYSTORE_PATH} | |
chmod 600 ${KEYSTORE_PATH} ${SUPPLY_GOOGLE_JSON_PATH} | |
- name: Fastlane VERIFY lane | |
if: needs.configure.outputs.push_to_playstore == 'false' | |
working-directory: ./android | |
run: bundle exec fastlane verify | |
- name: Fastlane RELEASE lane | |
if: contains(fromJSON('["internal", "beta", "production"]'), needs.configure.outputs.push_to_playstore) | |
working-directory: ./android | |
env: | |
STORE_TRACK: ${{ needs.configure.outputs.push_to_playstore }} | |
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} | |
SENTRY_ORG: ${{ vars.SENTRY_ORG }} | |
run: bundle exec fastlane release | |
- name: Fastlane APK lane | |
if: | | |
github.event_name == 'push' && | |
github.ref_type == 'tag' | |
run: bundle exec fastlane apk | |
working-directory: ./android | |
- name: Upload Artifacts | |
if: | | |
github.event_name == 'push' && | |
github.ref_type == 'tag' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: android-release | |
path: android/app/build/outputs/apk/release/*.apk | |
build-ios: | |
name: ${{ needs.configure.outputs.push_to_testflight == 'false' && 'Build' || 'Build & Deploy' }} iOS | |
env: | |
LANG: en_US.UTF-8 | |
CI: 'true' | |
BUILD_NO: ${{ needs.configure.outputs.build_no }} | |
APP_VERSION: ${{ needs.configure.outputs.version }} | |
MATCH_PASSWORD: ${{ secrets.FASTLANE_MATCH_KEY }} | |
MATCH_GIT_PRIVATE_KEY: "./github_access.pk" | |
FASTLANE_USERNAME: ${{ secrets.FASTLANE_POLI_MOBILE_USER }} | |
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_POLI_MOBILE_PW }} | |
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_DEV_PW }} | |
SUPPLY_GOOGLE_SERVICE_INFO_PLIST_PATH: "./GoogleService-Info.plist" | |
needs: configure | |
runs-on: [macos-latest] | |
steps: | |
- name: Select Xcode | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: '15' | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup build cache | |
uses: hendrikmuhs/[email protected] | |
- name: Set .env | |
run: | |
echo "MAPBOX_TOKEN=${{ secrets.MAPBOX_TOKEN }}" >> .env | |
- name: Set .netrc | |
run: | | |
echo "machine api.mapbox.com | |
login mapbox | |
password ${{ secrets.MAPBOX_TOKEN }} | |
" > ~/.netrc | |
chmod 600 ~/.netrc | |
- name: Setup Ruby | |
uses: ruby/setup-ruby@v1 | |
with: | |
bundler-cache: true # runs 'bundle install' and caches installed gems automatically | |
- name: Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: .nvmrc | |
- name: Cache node modules | |
uses: actions/cache@v4 | |
with: | |
path: ./node_modules | |
key: ${{ runner.os }}-npm-${{ hashFiles('./package-lock.json') }} | |
- name: Setup .npmrc | |
run: printf '@polito:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}\n' > .npmrc | |
- name: Enforce version | |
run: npm version "$APP_VERSION" --no-git-tag-version | |
- name: Cache pods | |
uses: actions/cache@v4 | |
with: | |
path: ./ios/Pods | |
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} | |
- name: Install npm dependencies | |
run: npm install | |
- name: Prepare fastlane | |
working-directory: ./ios | |
run: | | |
echo "${{ secrets.MATCH_GIT_AUTH_PK }}" > ${MATCH_GIT_PRIVATE_KEY} | |
chmod 600 ${MATCH_GIT_PRIVATE_KEY} | |
echo "${{ secrets.SUPPLY_GOOGLE_SERVICE_INFO_PLIST }}" | base64 -d > ${SUPPLY_GOOGLE_SERVICE_INFO_PLIST_PATH} | |
chmod 600 ${MATCH_GIT_PRIVATE_KEY} ${SUPPLY_GOOGLE_SERVICE_INFO_PLIST_PATH} | |
- name: Fastlane VERIFY lane | |
if: needs.configure.outputs.push_to_testflight == 'false' | |
working-directory: ./ios | |
run: | | |
bundle exec fastlane verify | |
- name: Fastlane RELEASE lane | |
if: needs.configure.outputs.push_to_testflight == 'true' | |
working-directory: ./ios | |
env: | |
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} | |
SENTRY_ORG: ${{ vars.SENTRY_ORG }} | |
run: | | |
bundle exec fastlane release | |
create-release: | |
name: Create GitHub Release | |
permissions: | |
contents: write | |
if: | | |
github.event.repository.full_name == github.repository && | |
( | |
(github.event_name == 'push' && github.ref_type == 'tag') || | |
github.event.inputs.create_release == 'true' | |
) | |
needs: [build-android, build-ios] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Gather artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: android-release | |
path: ./android-release | |
- name: Create release | |
uses: ncipollo/release-action@v1 | |
with: | |
generateReleaseNotes: true | |
skipIfReleaseExists: true | |
artifacts: ./android-release/*.apk |