Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Better deploy workflows :D #22821

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b0a85be
Create validateBuildEnvironment action
roryabraham Jul 13, 2023
f60e42a
Create buildAndroid.yml
roryabraham Jul 13, 2023
4e0bcef
Update Android fastlane tracks to separate builds and uploads
roryabraham Jul 13, 2023
699cebe
Update iOS fastlane tracks to separate builds and uploads
roryabraham Jul 13, 2023
b03abd8
Output APK_PATH and AAB_PATH from fastlane
roryabraham Jul 13, 2023
9c6b45c
Run android fastlane build and upload artifacts
roryabraham Jul 13, 2023
a8cdae9
Delete validateBuildEnvironment action
roryabraham Jul 13, 2023
430a355
Upload android sourcemaps
roryabraham Jul 13, 2023
c81c8c0
Post to slack if android build fails
roryabraham Jul 13, 2023
2ee0c35
Add buildIOS workflow
roryabraham Jul 13, 2023
793b63b
Output IPA_PATH from fastlane
roryabraham Jul 13, 2023
6d0e6e6
Create buildWeb job
roryabraham Jul 13, 2023
88b885e
Create buildDesktop.yml workflow
roryabraham Jul 13, 2023
a2387d2
Add concurrency groups for all build workflows
roryabraham Jul 13, 2023
d64df1a
Create deployAndroid.yml workflow
roryabraham Jul 13, 2023
8ed234b
Merge branch 'main' into Rory-BetterDeploys
roryabraham Jul 15, 2023
6426f4c
Merge branch 'main' into Rory-BetterDeploys
roryabraham Feb 16, 2024
58d36f8
Update buildAndroid.yml workflow
roryabraham Feb 16, 2024
5486e6f
Upload Fastfile to separate build and upload for Android
roryabraham Feb 16, 2024
2588adc
Extract config_ios_credentials utility
roryabraham Feb 16, 2024
acd3275
Quit buildAndroid early if any step fails
roryabraham Feb 16, 2024
5396edd
Setup iOS build workflow
roryabraham Feb 16, 2024
9a8c683
Setup separate lanes for iOS build and upload
roryabraham Feb 16, 2024
cba753f
Better lane names
roryabraham Feb 16, 2024
6021b99
Upload web build job
roryabraham Feb 16, 2024
d517216
Setup desktop build job
roryabraham Feb 16, 2024
d78d315
Update platformDeploy to use new workflow for Android
roryabraham Feb 16, 2024
5a5b03a
Fix typo
roryabraham Feb 16, 2024
80dec88
Update callable deployAndroid workflow
roryabraham Feb 16, 2024
41005da
Use deployAndroid callable workflow instead of inlining it in platfor…
roryabraham Feb 16, 2024
4d32984
Add TODO
roryabraham Feb 16, 2024
e6fd3c6
Merge branch 'main' into Rory-BetterDeploys
roryabraham Apr 19, 2024
5d79392
Merge branch 'main' into Rory-BetterDeploys
roryabraham Apr 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .github/workflows/buildAndroid.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: Build Android app

on:
workflow_call:
inputs:
BUILD_TYPE:
description: The environment to build for. Must be one of ("release", "ad-hoc", "e2e", "e2eDelta")
required: true
type: string
PR_NUMBER:
description: For AdHoc builds, the pull request being built from
required: false
type: number

concurrency:
group: build-android-${{ inputs.BUILD_TYPE }}
# TODO: cancel in-progress adhoc/e2e builds based on ref. Maybe pass in cancel-in-progress as an input?
cancel-in-progress: ${{ inputs.BUILD_TYPE == 'release' }}

jobs:
buildAndroid:
name: Build Android app
runs-on: ubuntu-latest-xl
steps:
- name: Validate build type
id: validateBuildType
run: |
if [[ ${{ contains(fromJSON('["release", "ad-hoc", "e2e", "e2eDelta"]'), inputs.BUILD_TYPE) }} == 'true' ]]; then
echo "Build type ${{ inputs.BUILD_TYPE }} is valid for Android"
else
echo "Build type ${{ inputs.BUILD_TYPE }} is not valid for Android."
exit 1
fi

- uses: actions/checkout@v4

- name: Configure MapBox SDK
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}

- name: Setup Node
uses: ./.github/actions/composite/setupNode

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: 17

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '2.7'
bundler-cache: true

- name: Decrypt keystore
run: cd android/app && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output my-upload-key.keystore my-upload-key.keystore.gpg
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}

- name: Set version in ENV
run: |
echo "VERSION_CODE=$(grep -o 'versionCode\s\+[0-9]\+' android/app/build.gradle | awk '{ print $2 }')" >> "$GITHUB_ENV"
echo "NPM_VERSION=$(< package.json jq -r .version)" >> "$GITHUB_ENV"

- name: Create .env.adhoc file based on staging and add PULL_REQUEST_NUMBER env to it
if: inputs.BUILD_TYPE == 'ad-hoc'
run: |
cp .env.staging .env.adhoc
sed -i 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc
echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc

- name: Run Fastlane build
id: build
run: |
if [[ ${{ inputs.BUILD_TYPE }} == "release" ]]; then
bundle exec fastlane android build_release
elif [[ ${{ inputs.BUILD_TYPE }} == "ad-hoc" ]]; then
bundle exec fastlane android build_adhoc
elif [[ ${{ inputs.BUILD_TYPE }} == "e2e" ]]; then
bundle exec fastlane android build_e2e
else
bundle exec fastlane android build_e2e_delta
fi

- name: Upload APK as workflow artifact
uses: actions/upload-artifact@v4
with:
name: android-${{ inputs.BUILD_TYPE }}-${{ github.ref }}.apk
# Note: this output comes from inside the Fastfile
path: ${{ steps.build.outputs.APK_PATH }}

- name: Upload AAB as workflow artifact
if: inputs.BUILD_TYPE == 'release'
uses: actions/upload-artifact@v4
with:
name: android-${{ inputs.BUILD_TYPE }}-${{ github.ref }}.aab
# Note: this output comes from inside the Fastfile
path: ${{ steps.build.outputs.AAB_PATH }}

- name: Archive Android sourcemaps
uses: actions/upload-artifact@v4
with:
name: android-${{ inputs.BUILD_TYPE }}-sourcemap-${{ github.ref }}
path: android/app/build/generated/sourcemaps/react/release/*.map

- name: Post a message in slack if the build fails
if: failure()
uses: ./.github/actions/composite/announceFailedWorkflowInSlack
with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
82 changes: 82 additions & 0 deletions .github/workflows/buildDesktop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Build desktop app

on:
workflow_call:
inputs:
BUILD_TYPE:
description: The environment to build for. Must be one of ("staging", "production", "ad-hoc")
required: true
type: string

concurrency:
group: build-android-${{ inputs.BUILD_TYPE }}
# TODO: Fix cancel-in-progress
cancel-in-progress: ${{ inputs.BUILD_TYPE == "ad-hoc" }}

jobs:
buildWeb:
name: Build desktop app
runs-on: ubuntu-latest-xl
steps:
- name: Validate build type
id: validateBuildType
run: |
if [[ ${{ contains(fromJSON('["staging", "production", "ad-hoc"]'), inputs.BUILD_TYPE) }} == 'true' ]]; then
echo "Build type ${{ inputs.BUILD_TYPE }} is valid for desktop."
else
echo "Build type ${{ inputs.BUILD_TYPE }} is not valid for desktop."
exit 1
fi

- name: Checkout
uses: actions/checkout@v4

- name: Create .env.adhoc file based on staging
if: inputs.BUILD_TYPE == 'ad-hoc'
run: |
cp .env.staging .env.adhoc
sed -i 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc
echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc

- name: Decrypt Developer ID Certificate
run: cd desktop && gpg --quiet --batch --yes --decrypt --passphrase="$DEVELOPER_ID_SECRET_PASSPHRASE" --output developer_id.p12 developer_id.p12.gpg
env:
DEVELOPER_ID_SECRET_PASSPHRASE: ${{ secrets.DEVELOPER_ID_SECRET_PASSPHRASE }}

- name: Setup Node
uses: ./.github/actions/composite/setupNode

- name: Configure AWS Credentials
uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main
with:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Run desktop build
run: |
if [[ ${{ inputs.BUILD_TYPE }} == 'ad-hoc' ]]; then
npm run desktop-build-adhoc -- --publish never
elif [[ ${{ inputs.BUILD_TYPE }} == 'staging' ]]; then
npm run desktop-build-staging -- --publish never
else
npm run desktop-build -- --publish never
fi
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Upload DMG as a workflow artifact
uses: actions/upload-artifact@v4
with:
name: NewExpensify.dmg
path: desktop-build/NewExpensify.dmg

- name: Post a message in slack if the build fails
if: failure()
uses: ./.github/actions/composite/announceFailedWorkflowInSlack
with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
108 changes: 108 additions & 0 deletions .github/workflows/buildIOS.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Build iOS App

on:
workflow_call:
inputs:
BUILD_TYPE:
description: The environment to build for. Must be one of ("release", "ad-hoc")
required: true
type: string

concurrency:
group: build-ios-${{ inputs.BUILD_TYPE }}
cancel-in-progress: ${{ inputs.BUILD_TYPE == 'release' }}

jobs:
buildIOS:
name: Build iOS app
runs-on: macos-13-xlarge
env:
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer
steps:
- name: Validate build type
id: validateBuildType
run: |
if [[ ${{ contains(fromJSON('["release", "ad-hoc"]'), inputs.BUILD_TYPE) }} == 'true' ]]; then
echo "Environment ${{ inputs.BUILD_TYPE }} is valid for iOS"
else
echo "Environment ${{ inputs.BUILD_TYPE }} is not valid for iOS."
exit 1
fi

- name: Checkout
uses: actions/checkout@v4

- name: Configure MapBox SDK
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}

- name: Setup Node
uses: ./.github/actions/composite/setupNode

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '2.7'
bundler-cache: true

- name: Cache Pod dependencies
uses: actions/cache@v4
id: pods-cache
with:
path: ios/Pods
key: pods-cache-${{ hashFiles('ios/Podfile.lock') }}
restore-keys: pods-cache-

- name: Compare Podfile.lock and Manifest.lock
id: compare-podfile-and-manifest
run: echo "IS_PODFILE_SAME_AS_MANIFEST=${{ hashFiles('ios/Podfile.lock') == hashFiles('ios/Pods/Manifest.lock') }}" >> "$GITHUB_OUTPUT"

- name: Install cocoapods
uses: nick-invision/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847
if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true'
with:
timeout_minutes: 10
max_attempts: 5
command: cd ios && bundle exec pod install

- name: Decrypt AppStore profile
run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AppStore.mobileprovision NewApp_AppStore.mobileprovision.gpg
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}

- name: Decrypt AppStore Notification Service profile
run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AppStore_Notification_Service.mobileprovision NewApp_AppStore_Notification_Service.mobileprovision.gpg
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}

- name: Decrypt certificate
run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output Certificates.p12 Certificates.p12.gpg
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}

- name: Run Fastlane build
id: build
run: |
if [[ ${{ inputs.BUILD_TYPE }} == "release" ]]; then
bundle exec fastlane ios build_release
else
bundle exec fastlane ios build_adhoc
fi

- name: Upload API as workflow artifact
uses: actions/upload-artifact@v4
with:
name: ios-${{ inputs.BUILD_TYPE }}-${{ github.ref }}.api
# Note: this output comes from inside the Fastfile
path: ${{ steps.build.outputs.IPA_PATH }}

- name: Upload iOS sourcemaps
uses: actions/upload-artifact@v3
with:
name: ios-${{ inputs.BUILD_TYPE }}-sourcemap-${{ github.ref }}
path: main.jsbundle.map

- name: Post a message in slack if the build fails
if: failure()
uses: ./.github/actions/composite/announceFailedWorkflowInSlack
with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
64 changes: 64 additions & 0 deletions .github/workflows/buildWeb.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Build web app

on:
workflow_call:
inputs:
BUILD_TYPE:
description: The environment to build for. Must be one of ("staging", "production", "ad-hoc")
required: true
type: string

concurrency:
group: build-web-${{ inputs.BUILD_TYPE }}
# TODO: Fix cancel-in-progess
cancel-in-progress: ${{ inputs.BUILD_TYPE == "ad-hoc" }}

jobs:
buildWeb:
name: Build web app
runs-on: ubuntu-latest-xl
steps:
- name: Validate build type
id: validateBuildType
run: |
if [[ ${{ contains(fromJSON('["staging", "production", "ad-hoc"]'), inputs.BUILD_TYPE) }} == 'true' ]]; then
echo "Build type ${{ inputs.BUILD_TYPE }} is valid for web."
else
echo "Build type ${{ inputs.BUILD_TYPE }} is not valid for web."
exit 1
fi

- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: ./.github/actions/composite/setupNode

- name: Create .env.adhoc file based on staging
if: inputs.BUILD_TYPE == 'ad-hoc'
run: |
cp .env.staging .env.adhoc
sed -i 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc
echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc

- name: Run web build
run: |
if [[ ${{ inputs.BUILD_TYPE }} == 'ad-hoc' ]]; then
npm run build-adhoc
elif [[ ${{ inputs.BUILD_TYPE }} == 'staging' ]]; then
npm run build-staging
else
npm run build
fi

- name: Upload web build as workflow artifact
uses: actions/upload-artifact@v4
with:
name: web-${{ inputs.BUILD_TYPE }}-${{ github.ref }}
path: ./dist

- name: Post a message in slack if the build fails
if: failure()
uses: ./.github/actions/composite/announceFailedWorkflowInSlack
with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
Loading
Loading