From d856478a5e8e1923bf3a8bd50b60fa85248c1284 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:13:20 +0100 Subject: [PATCH 01/14] copy jobs from platformDeploy.yml to deploy.yml --- .github/workflows/deploy.yml | 480 +++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6b1b72f1f901..efa069782078 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,7 +4,487 @@ on: push: branches: [staging, production] +env: + SHOULD_DEPLOY_PRODUCTION: ${{ github.event.action == 'released' }} + +concurrency: + group: ${{ github.workflow }}-${{ github.event.action }} + cancel-in-progress: true + jobs: + validateActor: + runs-on: ubuntu-latest + outputs: + IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }} + steps: + - name: Check if user is deployer + id: isUserDeployer + run: | + if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then + echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT" + else + echo "IS_DEPLOYER=false" >> "$GITHUB_OUTPUT" + fi + env: + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + + # Note: we're updating the checklist before running the deploys and assuming that it will succeed on at least one platform + deployChecklist: + name: Create or update deploy checklist + uses: ./.github/workflows/createDeployChecklist.yml + if: ${{ github.event.action != 'released' }} + needs: validateActor + secrets: inherit + + android: + # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly + name: Build and deploy Android + needs: validateActor + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} + runs-on: ubuntu-latest-xl + steps: + - 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 Java + uses: actions/setup-java@v4 + with: + distribution: 'oracle' + java-version: '17' + + - name: Setup Ruby + uses: ruby/setup-ruby@v1.190.0 + with: + 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: Decrypt json key + run: cd android/app && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output android-fastlane-json-key.json android-fastlane-json-key.json.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" + + - name: Run Fastlane + run: bundle exec fastlane android ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} + env: + RUBYOPT: '-rostruct' + MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }} + MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} + VERSION: ${{ env.VERSION_CODE }} + + - name: Upload Android build to Browser Stack + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@./android/app/build/outputs/bundle/productionRelease/app-production-release.aab" + env: + BROWSERSTACK: ${{ secrets.BROWSERSTACK }} + + - name: Upload Android sourcemaps to GitHub Release + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: gh release upload ${{ github.event.release.tag_name }} android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map#android-sourcemap-${{ github.event.release.tag_name }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload Android build to GitHub Release + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: gh release upload ${{ github.event.release.tag_name }} android/app/build/outputs/bundle/productionRelease/app-production-release.aab + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Warn deployers if Android production deploy failed + if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#deployer', + attachments: [{ + color: "#DB4545", + pretext: ``, + text: `💥 Android production deploy failed. Please manually submit ${{ github.event.release.tag_name }} in the . 💥`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + desktop: + # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly + name: Build and deploy Desktop + needs: validateActor + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} + runs-on: macos-14-large + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: ./.github/actions/composite/setupNode + + - 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: Build desktop app + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run desktop-build + else + npm run desktop-build-staging + 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 }} + GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }} + + - name: Upload desktop sourcemaps to GitHub Release + run: gh release upload ${{ github.event.release.tag_name }} desktop/dist/www/merged-source-map.js.map#desktop-sourcemap-${{ github.event.release.tag_name }} --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload desktop build to GitHub Release + run: gh release upload ${{ github.event.release.tag_name }} desktop-build/NewExpensify.dmg --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + iOS: + # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly + name: Build and deploy iOS + needs: validateActor + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} + env: + DEVELOPER_DIR: /Applications/Xcode_15.2.0.app/Contents/Developer + runs-on: macos-13-xlarge + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure MapBox SDK + run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }} + + - name: Setup Node + id: setup-node + uses: ./.github/actions/composite/setupNode + + - name: Setup Ruby + uses: ruby/setup-ruby@v1.190.0 + with: + bundler-cache: true + + - name: Cache Pod dependencies + uses: actions/cache@v4 + id: pods-cache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-cache-${{ hashFiles('ios/Podfile.lock', 'firebase.json') }} + + - 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-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847 + if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true' || steps.setup-node.outputs.cache-hit != 'true' + with: + timeout_minutes: 10 + max_attempts: 5 + command: scripts/pod-install.sh + + - 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: Decrypt App Store Connect API key + run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output ios-fastlane-json-key.json ios-fastlane-json-key.json.gpg + env: + LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + + - name: Set iOS version in ENV + run: echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> "$GITHUB_ENV" + + - name: Run Fastlane + run: bundle exec fastlane ios ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} + env: + APPLE_CONTACT_EMAIL: ${{ secrets.APPLE_CONTACT_EMAIL }} + APPLE_CONTACT_PHONE: ${{ secrets.APPLE_CONTACT_PHONE }} + APPLE_DEMO_EMAIL: ${{ secrets.APPLE_DEMO_EMAIL }} + APPLE_DEMO_PASSWORD: ${{ secrets.APPLE_DEMO_PASSWORD }} + VERSION: ${{ env.IOS_VERSION }} + + - name: Upload iOS build to Browser Stack + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@/Users/runner/work/App/App/New Expensify.ipa" + env: + BROWSERSTACK: ${{ secrets.BROWSERSTACK }} + + - name: Upload iOS sourcemaps to GitHub Release + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: gh release upload ${{ github.event.release.tag_name }} main.jsbundle.map#ios-sourcemap-${{ github.event.release.tag_name }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload iOS build to GitHub Release + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: gh release upload ${{ github.event.release.tag_name }} /Users/runner/work/App/App/New\ Expensify.ipa + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Warn deployers if iOS production deploy failed + if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#deployer', + attachments: [{ + color: "#DB4545", + pretext: ``, + text: `💥 iOS production deploy failed. Please manually submit ${{ env.IOS_VERSION }} in the . 💥`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + web: + # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly + name: Build and deploy Web + needs: validateActor + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} + runs-on: ubuntu-latest-xl + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: ./.github/actions/composite/setupNode + + - name: Setup Cloudflare CLI + run: pip3 install cloudflare==2.19.0 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Build web + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run build + else + npm run build-staging + fi + + - name: Build storybook docs + continue-on-error: true + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run storybook-build + else + npm run storybook-build-staging + fi + + - name: Deploy to S3 + run: | + aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist ${{ env.S3_URL }}/ + aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{ env.S3_URL }}/.well-known/apple-app-site-association + aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{env.S3_URL }}/apple-app-site-association + env: + S3_URL: s3://${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging-' || '' }}expensify-cash + + - name: Purge Cloudflare cache + run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging.' || '' }}new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache + env: + CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} + + - name: Verify staging deploy + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: | + sleep 5 + DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://staging.new.expensify.com/version.json | jq -r '.version')" + if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." + exit 1 + fi + + - name: Verify production deploy + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: | + sleep 5 + DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://new.expensify.com/version.json | jq -r '.version')" + if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." + exit 1 + fi + + - name: Upload web sourcemaps to GitHub Release + run: gh release upload ${{ github.event.release.tag_name }} dist/merged-source-map.js.map#web-sourcemap-${{ github.event.release.tag_name }} --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload web build to GitHub Release + run: | + tar -czvf webBuild.tar.gz dist + zip -r webBuild.zip dist + gh release upload ${{ github.event.release.tag_name }} webBuild.tar.gz webBuild.zip --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + postSlackMessageOnFailure: + name: Post a Slack message when any platform fails to build or deploy + runs-on: ubuntu-latest + if: ${{ failure() }} + needs: [android, desktop, iOS, web] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Post Slack message on failure + uses: ./.github/actions/composite/announceFailedWorkflowInSlack + with: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + # Build a version of iOS and Android HybridApp if we are deploying to staging + hybridApp: + runs-on: ubuntu-latest + needs: validateActor + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) && github.event.action != 'released' }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: 'Deploy HybridApp' + run: gh workflow run --repo Expensify/Mobile-Deploy deploy.yml -f force_build=true -f build_version="$(npm run print-version --silent)" + env: + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + + postSlackMessageOnSuccess: + name: Post a Slack message when all platforms deploy successfully + runs-on: ubuntu-latest + if: ${{ success() }} + needs: [android, desktop, iOS, web] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set version + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + + - name: 'Announces the deploy in the #announce Slack room' + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#announce', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + - name: 'Announces the deploy in the #deployer Slack room' + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#deployer', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + - name: 'Announces a production deploy in the #expensify-open-source Slack room' + uses: 8398a7/action-slack@v3 + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + with: + status: custom + custom_payload: | + { + channel: '#expensify-open-source', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + postGithubComment: + name: Post a GitHub comment when platforms are done building and deploying + runs-on: ubuntu-latest + if: ${{ !cancelled() }} + needs: [android, desktop, iOS, web] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: ./.github/actions/composite/setupNode + + - name: Set version + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + + - name: Get Release Pull Request List + id: getReleasePRList + uses: ./.github/actions/javascript/getDeployPullRequestList + with: + TAG: ${{ env.VERSION }} + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + + - name: Comment on issues + uses: ./.github/actions/javascript/markPullRequestsAsDeployed + with: + PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} + IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + DEPLOY_VERSION: ${{ env.VERSION }} + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + ANDROID: ${{ needs.android.result }} + DESKTOP: ${{ needs.desktop.result }} + IOS: ${{ needs.iOS.result }} + WEB: ${{ needs.web.result }} + deployStaging: runs-on: ubuntu-latest if: github.ref == 'refs/heads/staging' From 4bf80e688e136ad80c7aaa914e63433647744a93 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:16:52 +0100 Subject: [PATCH 02/14] Make necessary changes to Combine deploy.yml and platformDeploy.yml --- .github/workflows/deploy.yml | 214 ++++++++++++++++++++++++++--------- 1 file changed, 160 insertions(+), 54 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index efa069782078..c49d56cedb0e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,10 +5,10 @@ on: branches: [staging, production] env: - SHOULD_DEPLOY_PRODUCTION: ${{ github.event.action == 'released' }} + SHOULD_DEPLOY_PRODUCTION: ${{ github.ref == 'refs/heads/production' }} concurrency: - group: ${{ github.workflow }}-${{ github.event.action }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -32,7 +32,7 @@ jobs: deployChecklist: name: Create or update deploy checklist uses: ./.github/workflows/createDeployChecklist.yml - if: ${{ github.event.action != 'released' }} + if: !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) needs: validateActor secrets: inherit @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - + - name: Configure MapBox SDK run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }} @@ -90,17 +90,22 @@ jobs: env: BROWSERSTACK: ${{ secrets.BROWSERSTACK }} - - name: Upload Android sourcemaps to GitHub Release + - name: Upload Android sourcemaps artifact if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map#android-sourcemap-${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ github.token }} + uses: actions/upload-artifact@v4 + with: + name: android-sourcemaps + path: ./android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map - - name: Upload Android build to GitHub Release + - name: Upload Android build artifact if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} android/app/build/outputs/bundle/productionRelease/app-production-release.aab - env: - GITHUB_TOKEN: ${{ github.token }} + uses: actions/upload-artifact@v4 + with: + name: android-build + path: ./android/app/build/outputs/bundle/productionRelease/app-production-release.aab + + - name: Set current App version in Env + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - name: Warn deployers if Android production deploy failed if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -113,7 +118,7 @@ jobs: attachments: [{ color: "#DB4545", pretext: ``, - text: `💥 Android production deploy failed. Please manually submit ${{ github.event.release.tag_name }} in the . 💥`, + text: `💥 Android production deploy failed. Please manually submit ${{ env.VERSION }} in the . 💥`, }] } env: @@ -154,15 +159,17 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }} - - name: Upload desktop sourcemaps to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} desktop/dist/www/merged-source-map.js.map#desktop-sourcemap-${{ github.event.release.tag_name }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Upload desktop sourcemaps artifact + uses: actions/upload-artifact@v4 + with: + name: desktop-sourcemaps + path: ./desktop/dist/www/merged-source-map.js.map - - name: Upload desktop build to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} desktop-build/NewExpensify.dmg --clobber - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Upload desktop build artifact + uses: actions/upload-artifact@v4 + with: + name: desktop-build + path: ./desktop-build/NewExpensify.dmg iOS: # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly @@ -227,8 +234,11 @@ jobs: env: LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + - name: Set current App version in Env + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + - name: Set iOS version in ENV - run: echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> "$GITHUB_ENV" + run: echo "IOS_VERSION=$(echo '${{ env.VERSION }}' | tr '-' '.')" >> "$GITHUB_ENV" - name: Run Fastlane run: bundle exec fastlane ios ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} @@ -245,17 +255,19 @@ jobs: env: BROWSERSTACK: ${{ secrets.BROWSERSTACK }} - - name: Upload iOS sourcemaps to GitHub Release + - name: Upload iOS sourcemaps artifact if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} main.jsbundle.map#ios-sourcemap-${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ github.token }} + uses: actions/upload-artifact@v4 + with: + name: ios-sourcemaps + path: ./main.jsbundle.map - - name: Upload iOS build to GitHub Release - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} /Users/runner/work/App/App/New\ Expensify.ipa - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Upload iOS build artifact + if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + uses: actions/upload-artifact@v4 + with: + name: ios-build + path: ./Users/runner/work/App/App/New\ Expensify.ipa - name: Warn deployers if iOS production deploy failed if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -328,13 +340,16 @@ jobs: env: CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} + - name: Set current App version in Env + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + - name: Verify staging deploy if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} run: | sleep 5 DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://staging.new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." + if [[ '${{ env.VERSION }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ env.VERSION }}. Something went wrong..." exit 1 fi @@ -343,23 +358,33 @@ jobs: run: | sleep 5 DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." + if [[ '${{ env.VERSION }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ env.VERSION }}. Something went wrong..." exit 1 fi - - name: Upload web sourcemaps to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} dist/merged-source-map.js.map#web-sourcemap-${{ github.event.release.tag_name }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Upload web sourcemaps artifact + uses: actions/upload-artifact@v4 + with: + name: web-sourcemaps + path: ./dist/merged-source-map.js.map - - name: Upload web build to GitHub Release + - name: Compress web build .tar.gz and .zip run: | tar -czvf webBuild.tar.gz dist zip -r webBuild.zip dist - gh release upload ${{ github.event.release.tag_name }} webBuild.tar.gz webBuild.zip --clobber - env: - GITHUB_TOKEN: ${{ github.token }} + + - name: Upload .tar.gz web build artifact + uses: actions/upload-artifact@v4 + with: + name: web-build-tar-gz + path: ./webBuild.tar.gz + + - name: Upload .zip web build artifact + uses: actions/upload-artifact@v4 + with: + name: web-build-zip + path: ./webBuild.zip postSlackMessageOnFailure: name: Post a Slack message when any platform fails to build or deploy @@ -379,7 +404,7 @@ jobs: hybridApp: runs-on: ubuntu-latest needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) && github.event.action != 'released' }} + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) && github.ref == 'refs/heads/staging' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -398,7 +423,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set version + - name: Set current App version in Env run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - name: 'Announces the deploy in the #announce Slack room' @@ -462,7 +487,7 @@ jobs: - name: Setup Node uses: ./.github/actions/composite/setupNode - - name: Set version + - name: Set current App version in Env run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - name: Get Release Pull Request List @@ -485,9 +510,29 @@ jobs: IOS: ${{ needs.iOS.result }} WEB: ${{ needs.web.result }} - deployStaging: + check-deployment-success: + runs-on: ubuntu-latest + outputs: + IS_DEPLOYED: ${{ steps.check-success.outputs.IS_DEPLOYED }} + needs: [android, desktop, iOS, web] + steps: + - name: Check deployment success on at least one platform + id: check-success + run: | + success="false" + if [ "${{ needs.android.result }}" == 'success' ] || \ + [ "${{ needs.iOS.result }}" == 'success' ] || \ + [ "${{ needs.desktop.result }}" == 'success' ] || \ + [ "${{ needs.web.result }}" == 'success' ]; then + success="true" + fi + echo "IS_DEPLOYED=$success" >> $GITHUB_ENV + echo "::set-output name=IS_DEPLOYED::$success" + + createPrerelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' + if: github.ref == 'refs/heads/staging' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' + needs: [android, desktop, iOS, web, check-deployment-success] steps: - name: Checkout staging branch uses: actions/checkout@v4 @@ -506,11 +551,54 @@ jobs: - name: Get current app version run: echo "STAGING_VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - name: 🚀 Create prerelease to trigger staging deploy 🚀 + - name: Download all workflow run artifacts + uses: actions/download-artifact@v4 + + - name: 🚀 Create prerelease 🚀 run: gh release create ${{ env.STAGING_VERSION }} --title ${{ env.STAGING_VERSION }} --generate-notes --prerelease --target staging env: GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }} + - name: Upload Android sourcemaps to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./android-sourcemaps/index.android.bundle.map#android-sourcemap-${{ env.STAGING_VERSION }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload Android build to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./android-build/app-production-release.aab + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload desktop sourcemaps to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload desktop build to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./desktop-build/NewExpensify.dmg + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload iOS sourcemaps to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./ios-sourcemaps/main.jsbundle.map#ios-sourcemap-${{ env.STAGING_VERSION }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload iOS build to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./ios-build/New\ Expensify.ipa + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload web sourcemaps to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload web build to GitHub Release + run: gh release upload ${{ env.STAGING_VERSION }} ./web-build-tar-gz/webBuild.tar.gz ./web-build-tar-gz/webBuild.zip + env: + GITHUB_TOKEN: ${{ github.token }} + - name: Warn deployers if staging deploy failed if: ${{ failure() }} uses: 8398a7/action-slack@v3 @@ -529,9 +617,10 @@ jobs: GITHUB_TOKEN: ${{ github.token }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - deployProduction: + finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' + if: github.ref == 'refs/heads/staging' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' + needs: [android, desktop, iOS, web, check-deployment-success] steps: - uses: actions/checkout@v4 name: Checkout @@ -547,10 +636,27 @@ jobs: OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} - - name: Get current app version - run: echo "PRODUCTION_VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + - name: Upload web sourcemaps to GitHub Release + run: gh release upload ${{ env.PRODUCTION_VERSION }} ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.PRODUCTION_VERSION }} --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload web build to GitHub Release + run: gh release upload ${{ env.PRODUCTION_VERSION }} ./web-build-tar-gz/webBuild.tar.gz ./web-build-tar-gz/webBuild.zip --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload desktop sourcemaps to GitHub Release + run: gh release upload ${{ env.PRODUCTION_VERSION }} ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.PRODUCTION_VERSION }} --clobber + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Upload desktop build to GitHub Release + run: gh release upload ${{ env.PRODUCTION_VERSION }} ./desktop-build/NewExpensify.dmg --clobber + env: + GITHUB_TOKEN: ${{ github.token }} - - name: 🚀 Edit the release to be no longer a prerelease to deploy production 🚀 + - name: 🚀 Edit the release to be no longer a prerelease 🚀 run: | LATEST_RELEASE="$(gh release list --exclude-pre-releases --json tagName,isLatest --jq '.[] | select(.isLatest) | .tagName')" gh api --method POST /repos/Expensify/App/releases/generate-notes -f "tag_name=${{ env.PRODUCTION_VERSION }}" -f "previous_tag_name=$LATEST_RELEASE" >> releaseNotes.md From 4d61ae79c47bbbbdffe6670a642933ea43309bb5 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:11:31 +0100 Subject: [PATCH 03/14] remove platformDeploy.yml file and modify it's usages --- .../awaitStagingDeploys.ts | 2 +- .../javascript/awaitStagingDeploys/index.js | 2 +- .../getDeployPullRequestList.ts | 22 +- .../getDeployPullRequestList/index.js | 16 +- .../scripts/validateActionsAndWorkflows.sh | 2 +- .github/workflows/platformDeploy.yml | 487 ------------------ tests/unit/awaitStagingDeploysTest.ts | 30 +- 7 files changed, 52 insertions(+), 509 deletions(-) delete mode 100644 .github/workflows/platformDeploy.yml diff --git a/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.ts b/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.ts index 96bb17a14354..e18019144e4e 100644 --- a/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.ts +++ b/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.ts @@ -18,7 +18,7 @@ function run() { GitHubUtils.octokit.actions.listWorkflowRuns({ owner: CONST.GITHUB_OWNER, repo: CONST.APP_REPO, - workflow_id: 'platformDeploy.yml', + workflow_id: 'deploy.yml', event: 'push', branch: tag, }), diff --git a/.github/actions/javascript/awaitStagingDeploys/index.js b/.github/actions/javascript/awaitStagingDeploys/index.js index 7bdbafc0b722..561cc980a4e5 100644 --- a/.github/actions/javascript/awaitStagingDeploys/index.js +++ b/.github/actions/javascript/awaitStagingDeploys/index.js @@ -12138,7 +12138,7 @@ function run() { GithubUtils_1.default.octokit.actions.listWorkflowRuns({ owner: CONST_1.default.GITHUB_OWNER, repo: CONST_1.default.APP_REPO, - workflow_id: 'platformDeploy.yml', + workflow_id: 'deploy.yml', event: 'push', branch: tag, }), diff --git a/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts b/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts index da946b78a056..5d5dbc7e2f29 100644 --- a/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts +++ b/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts @@ -35,7 +35,7 @@ async function isReleaseValidBaseForEnvironment(releaseTag: string, isProduction } /** - * Was a given platformDeploy workflow run successful on at least one platform? + * Was a given deploy workflow run successful on at least one platform? */ async function wasDeploySuccessful(runID: number) { const jobsForWorkflowRun = ( @@ -82,7 +82,7 @@ async function run() { console.log(`Looking for PRs deployed to ${deployEnv} in ${inputTag}...`); - const completedDeploys = ( + const platformDeploys = ( await GithubUtils.octokit.actions.listWorkflowRuns({ owner: github.context.repo.owner, repo: github.context.repo.repo, @@ -95,6 +95,24 @@ async function run() { // because if a build fails on even one platform, then it will have the status 'failure' .filter((workflowRun) => workflowRun.conclusion !== 'cancelled'); + const deploys = ( + await GithubUtils.octokit.actions.listWorkflowRuns({ + owner: github.context.repo.owner, + repo: github.context.repo.repo, + // eslint-disable-next-line @typescript-eslint/naming-convention + workflow_id: 'deploy.yml', + status: 'completed', + }) + ).data.workflow_runs + // Note: we filter out cancelled runs instead of looking only for success runs + // because if a build fails on even one platform, then it will have the status 'failure' + .filter((workflowRun) => workflowRun.conclusion !== 'cancelled'); + + // W've combined platformDeploy.yml and deploy.yml + // TODO: Remove this once there are successful staging and production deploys using the new deploy.yml workflow + const completedDeploys = [...deploys, ...platformDeploys]; + completedDeploys.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); + // Find the most recent deploy workflow targeting the correct environment, for which at least one of the build jobs finished successfully let lastSuccessfulDeploy = completedDeploys.shift(); diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index 300cb1edc0ed..58cc364c2fae 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -11526,7 +11526,7 @@ async function isReleaseValidBaseForEnvironment(releaseTag, isProductionDeploy) return !isPrerelease; } /** - * Was a given platformDeploy workflow run successful on at least one platform? + * Was a given deploy workflow run successful on at least one platform? */ async function wasDeploySuccessful(runID) { const jobsForWorkflowRun = (await GithubUtils_1.default.octokit.actions.listJobsForWorkflowRun({ @@ -11566,7 +11566,7 @@ async function run() { const isProductionDeploy = !!(0, ActionUtils_1.getJSONInput)('IS_PRODUCTION_DEPLOY', { required: false }, false); const deployEnv = isProductionDeploy ? 'production' : 'staging'; console.log(`Looking for PRs deployed to ${deployEnv} in ${inputTag}...`); - const completedDeploys = (await GithubUtils_1.default.octokit.actions.listWorkflowRuns({ + const platformDeploys = (await GithubUtils_1.default.octokit.actions.listWorkflowRuns({ owner: github.context.repo.owner, repo: github.context.repo.repo, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -11576,6 +11576,18 @@ async function run() { // Note: we filter out cancelled runs instead of looking only for success runs // because if a build fails on even one platform, then it will have the status 'failure' .filter((workflowRun) => workflowRun.conclusion !== 'cancelled'); + const deploys = (await GithubUtils_1.default.octokit.actions.listWorkflowRuns({ + owner: github.context.repo.owner, + repo: github.context.repo.repo, + // eslint-disable-next-line @typescript-eslint/naming-convention + workflow_id: 'deploy.yml', + status: 'completed', + })).data.workflow_runs + // Note: we filter out cancelled runs instead of looking only for success runs + // because if a build fails on even one platform, then it will have the status 'failure' + .filter((workflowRun) => workflowRun.conclusion !== 'cancelled'); + // W've combined platformDeploy.yml and deploy.yml, deploys are the most recent ones + const completedDeploys = [...deploys, ...platformDeploys]; // Find the most recent deploy workflow targeting the correct environment, for which at least one of the build jobs finished successfully let lastSuccessfulDeploy = completedDeploys.shift(); if (!lastSuccessfulDeploy) { diff --git a/.github/scripts/validateActionsAndWorkflows.sh b/.github/scripts/validateActionsAndWorkflows.sh index 07348a302f20..fadb39c88e45 100755 --- a/.github/scripts/validateActionsAndWorkflows.sh +++ b/.github/scripts/validateActionsAndWorkflows.sh @@ -45,7 +45,7 @@ for ((i=0; i < ${#WORKFLOWS[@]}; i++)); do # Skip linting e2e workflow due to bug here: https://github.com/SchemaStore/schemastore/issues/2579 if [[ "$WORKFLOW" == './workflows/e2ePerformanceTests.yml' || "$WORKFLOW" == './workflows/testBuild.yml' - || "$WORKFLOW" == './workflows/platformDeploy.yml' ]]; then + || "$WORKFLOW" == './workflows/deploy.yml' ]]; then continue fi diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml deleted file mode 100644 index bacab79998f9..000000000000 --- a/.github/workflows/platformDeploy.yml +++ /dev/null @@ -1,487 +0,0 @@ -name: Build and deploy android, desktop, iOS, and web clients - -# This workflow is run when a release or prerelease is created -on: - release: - types: [prereleased, released] - -env: - SHOULD_DEPLOY_PRODUCTION: ${{ github.event.action == 'released' }} - -concurrency: - group: ${{ github.workflow }}-${{ github.event.action }} - cancel-in-progress: true - -jobs: - validateActor: - runs-on: ubuntu-latest - outputs: - IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }} - steps: - - name: Check if user is deployer - id: isUserDeployer - run: | - if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then - echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT" - else - echo "IS_DEPLOYER=false" >> "$GITHUB_OUTPUT" - fi - env: - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - - # Note: we're updating the checklist before running the deploys and assuming that it will succeed on at least one platform - deployChecklist: - name: Create or update deploy checklist - uses: ./.github/workflows/createDeployChecklist.yml - if: ${{ github.event.action != 'released' }} - needs: validateActor - secrets: inherit - - android: - # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly - name: Build and deploy Android - needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} - runs-on: ubuntu-latest-xl - steps: - - 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 Java - uses: actions/setup-java@v4 - with: - distribution: 'oracle' - java-version: '17' - - - name: Setup Ruby - uses: ruby/setup-ruby@v1.190.0 - with: - 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: Decrypt json key - run: cd android/app && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output android-fastlane-json-key.json android-fastlane-json-key.json.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" - - - name: Run Fastlane - run: bundle exec fastlane android ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} - env: - RUBYOPT: '-rostruct' - MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }} - MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} - VERSION: ${{ env.VERSION_CODE }} - - - name: Upload Android build to Browser Stack - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@./android/app/build/outputs/bundle/productionRelease/app-production-release.aab" - env: - BROWSERSTACK: ${{ secrets.BROWSERSTACK }} - - - name: Upload Android sourcemaps to GitHub Release - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map#android-sourcemap-${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload Android build to GitHub Release - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} android/app/build/outputs/bundle/productionRelease/app-production-release.aab - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Warn deployers if Android production deploy failed - if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#deployer', - attachments: [{ - color: "#DB4545", - pretext: ``, - text: `💥 Android production deploy failed. Please manually submit ${{ github.event.release.tag_name }} in the . 💥`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - desktop: - # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly - name: Build and deploy Desktop - needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} - runs-on: macos-14-large - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/composite/setupNode - - - 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: Build desktop app - run: | - if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then - npm run desktop-build - else - npm run desktop-build-staging - 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 }} - GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }} - - - name: Upload desktop sourcemaps to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} desktop/dist/www/merged-source-map.js.map#desktop-sourcemap-${{ github.event.release.tag_name }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload desktop build to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} desktop-build/NewExpensify.dmg --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - iOS: - # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly - name: Build and deploy iOS - needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} - env: - DEVELOPER_DIR: /Applications/Xcode_15.2.0.app/Contents/Developer - runs-on: macos-13-xlarge - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Configure MapBox SDK - run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }} - - - name: Setup Node - id: setup-node - uses: ./.github/actions/composite/setupNode - - - name: Setup Ruby - uses: ruby/setup-ruby@v1.190.0 - with: - bundler-cache: true - - - name: Cache Pod dependencies - uses: actions/cache@v4 - id: pods-cache - with: - path: ios/Pods - key: ${{ runner.os }}-pods-cache-${{ hashFiles('ios/Podfile.lock', 'firebase.json') }} - - - 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-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847 - if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true' || steps.setup-node.outputs.cache-hit != 'true' - with: - timeout_minutes: 10 - max_attempts: 5 - command: scripts/pod-install.sh - - - 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: Decrypt App Store Connect API key - run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output ios-fastlane-json-key.json ios-fastlane-json-key.json.gpg - env: - LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} - - - name: Set iOS version in ENV - run: echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> "$GITHUB_ENV" - - - name: Run Fastlane - run: bundle exec fastlane ios ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} - env: - APPLE_CONTACT_EMAIL: ${{ secrets.APPLE_CONTACT_EMAIL }} - APPLE_CONTACT_PHONE: ${{ secrets.APPLE_CONTACT_PHONE }} - APPLE_DEMO_EMAIL: ${{ secrets.APPLE_DEMO_EMAIL }} - APPLE_DEMO_PASSWORD: ${{ secrets.APPLE_DEMO_PASSWORD }} - VERSION: ${{ env.IOS_VERSION }} - - - name: Upload iOS build to Browser Stack - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@/Users/runner/work/App/App/New Expensify.ipa" - env: - BROWSERSTACK: ${{ secrets.BROWSERSTACK }} - - - name: Upload iOS sourcemaps to GitHub Release - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} main.jsbundle.map#ios-sourcemap-${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload iOS build to GitHub Release - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: gh release upload ${{ github.event.release.tag_name }} /Users/runner/work/App/App/New\ Expensify.ipa - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Warn deployers if iOS production deploy failed - if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#deployer', - attachments: [{ - color: "#DB4545", - pretext: ``, - text: `💥 iOS production deploy failed. Please manually submit ${{ env.IOS_VERSION }} in the . 💥`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - web: - # WARNING: getDeployPullRequestList depends on this job name. do not change job name without adjusting that action accordingly - name: Build and deploy Web - needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} - runs-on: ubuntu-latest-xl - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/composite/setupNode - - - name: Setup Cloudflare CLI - run: pip3 install cloudflare==2.19.0 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-1 - - - name: Build web - run: | - if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then - npm run build - else - npm run build-staging - fi - - - name: Build storybook docs - continue-on-error: true - run: | - if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then - npm run storybook-build - else - npm run storybook-build-staging - fi - - - name: Deploy to S3 - run: | - aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist ${{ env.S3_URL }}/ - aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{ env.S3_URL }}/.well-known/apple-app-site-association - aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{env.S3_URL }}/apple-app-site-association - env: - S3_URL: s3://${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging-' || '' }}expensify-cash - - - name: Purge Cloudflare cache - run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging.' || '' }}new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache - env: - CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} - - - name: Verify staging deploy - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: | - sleep 5 - DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://staging.new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." - exit 1 - fi - - - name: Verify production deploy - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: | - sleep 5 - DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ github.event.release.tag_name }}. Something went wrong..." - exit 1 - fi - - - name: Upload web sourcemaps to GitHub Release - run: gh release upload ${{ github.event.release.tag_name }} dist/merged-source-map.js.map#web-sourcemap-${{ github.event.release.tag_name }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload web build to GitHub Release - run: | - tar -czvf webBuild.tar.gz dist - zip -r webBuild.zip dist - gh release upload ${{ github.event.release.tag_name }} webBuild.tar.gz webBuild.zip --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - postSlackMessageOnFailure: - name: Post a Slack message when any platform fails to build or deploy - runs-on: ubuntu-latest - if: ${{ failure() }} - needs: [android, desktop, iOS, web] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Post Slack message on failure - uses: ./.github/actions/composite/announceFailedWorkflowInSlack - with: - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} - - # Build a version of iOS and Android HybridApp if we are deploying to staging - hybridApp: - runs-on: ubuntu-latest - needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) && github.event.action != 'released' }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: 'Deploy HybridApp' - run: gh workflow run --repo Expensify/Mobile-Deploy deploy.yml -f force_build=true -f build_version="$(npm run print-version --silent)" - env: - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - - postSlackMessageOnSuccess: - name: Post a Slack message when all platforms deploy successfully - runs-on: ubuntu-latest - if: ${{ success() }} - needs: [android, desktop, iOS, web] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set version - run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - - name: 'Announces the deploy in the #announce Slack room' - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#announce', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - - name: 'Announces the deploy in the #deployer Slack room' - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#deployer', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - - name: 'Announces a production deploy in the #expensify-open-source Slack room' - uses: 8398a7/action-slack@v3 - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - with: - status: custom - custom_payload: | - { - channel: '#expensify-open-source', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - postGithubComment: - name: Post a GitHub comment when platforms are done building and deploying - runs-on: ubuntu-latest - if: ${{ !cancelled() }} - needs: [android, desktop, iOS, web] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/composite/setupNode - - - name: Set version - run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - - name: Get Release Pull Request List - id: getReleasePRList - uses: ./.github/actions/javascript/getDeployPullRequestList - with: - TAG: ${{ env.VERSION }} - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - - - name: Comment on issues - uses: ./.github/actions/javascript/markPullRequestsAsDeployed - with: - PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} - IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - DEPLOY_VERSION: ${{ env.VERSION }} - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - ANDROID: ${{ needs.android.result }} - DESKTOP: ${{ needs.desktop.result }} - IOS: ${{ needs.iOS.result }} - WEB: ${{ needs.web.result }} diff --git a/tests/unit/awaitStagingDeploysTest.ts b/tests/unit/awaitStagingDeploysTest.ts index 64d79c9faf94..4d3384f11959 100644 --- a/tests/unit/awaitStagingDeploysTest.ts +++ b/tests/unit/awaitStagingDeploysTest.ts @@ -33,8 +33,8 @@ type MockedFunctionListResponse = jest.MockedFunction<() => Promise { const defaultReturn = Promise.resolve({data: {workflow_runs: []}}); @@ -44,11 +44,11 @@ const mockListWorkflowRuns = jest.fn().mockImplementation((args: Workflow) => { } if (args.branch !== undefined) { - return mockListPlatformDeploysForTag(); + return mockListDeploysForTag(); } - if (args.workflow_id === 'platformDeploy.yml') { - return mockListPlatformDeploys(); + if (args.workflow_id === 'deploy.yml') { + return mockListDeploys(); } if (args.workflow_id === 'preDeploy.yml') { @@ -89,7 +89,7 @@ describe('awaitStagingDeploys', () => { mockGetInput.mockImplementation(() => undefined); // First ping - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW, INCOMPLETE_WORKFLOW, INCOMPLETE_WORKFLOW], }, @@ -101,7 +101,7 @@ describe('awaitStagingDeploys', () => { }); // Second ping - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW, COMPLETED_WORKFLOW, INCOMPLETE_WORKFLOW], }, @@ -113,7 +113,7 @@ describe('awaitStagingDeploys', () => { }); // Third ping - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW, COMPLETED_WORKFLOW, COMPLETED_WORKFLOW], }, @@ -125,7 +125,7 @@ describe('awaitStagingDeploys', () => { }); // Fourth ping - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW, COMPLETED_WORKFLOW, COMPLETED_WORKFLOW], }, @@ -149,12 +149,12 @@ describe('awaitStagingDeploys', () => { mockGetInput.mockImplementation(() => 'my-tag'); // First ping - mockListPlatformDeploysForTag.mockResolvedValueOnce({ + mockListDeploysForTag.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW], }, }); - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW, INCOMPLETE_WORKFLOW], }, @@ -166,12 +166,12 @@ describe('awaitStagingDeploys', () => { }); // Second ping - mockListPlatformDeploysForTag.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW], }, }); - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW, COMPLETED_WORKFLOW], }, @@ -183,12 +183,12 @@ describe('awaitStagingDeploys', () => { }); // Third ping - mockListPlatformDeploysForTag.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW], }, }); - mockListPlatformDeploys.mockResolvedValueOnce({ + mockListDeploys.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW, COMPLETED_WORKFLOW, INCOMPLETE_WORKFLOW], }, From ed72e2d8fd04bf4921158ec62b7575cb31c3d841 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:24:37 +0100 Subject: [PATCH 04/14] correct absolute path --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c49d56cedb0e..25bde7def7e7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -267,7 +267,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: ios-build - path: ./Users/runner/work/App/App/New\ Expensify.ipa + path: /Users/runner/work/App/App/New\ Expensify.ipa - name: Warn deployers if iOS production deploy failed if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} From 338dade37900ea2c4f484af163ae05db7c910f22 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:25:25 +0100 Subject: [PATCH 05/14] correctly set env.PRODUCTION_VERSION --- .github/workflows/deploy.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 25bde7def7e7..9f3345f3be79 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -636,6 +636,9 @@ jobs: OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} + - name: Get current app version + run: echo "PRODUCTION_VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + - name: Upload web sourcemaps to GitHub Release run: gh release upload ${{ env.PRODUCTION_VERSION }} ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.PRODUCTION_VERSION }} --clobber env: From 1bd8fe11c502134f74eb4c4735292d6edca9ef46 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:27:34 +0100 Subject: [PATCH 06/14] build gh actions --- .github/actions/javascript/getDeployPullRequestList/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index 58cc364c2fae..3faaeb28f548 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -11586,8 +11586,10 @@ async function run() { // Note: we filter out cancelled runs instead of looking only for success runs // because if a build fails on even one platform, then it will have the status 'failure' .filter((workflowRun) => workflowRun.conclusion !== 'cancelled'); - // W've combined platformDeploy.yml and deploy.yml, deploys are the most recent ones + // W've combined platformDeploy.yml and deploy.yml + // TODO: Remove this once there are successful staging and production deploys using the new deploy.yml workflow const completedDeploys = [...deploys, ...platformDeploys]; + completedDeploys.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); // Find the most recent deploy workflow targeting the correct environment, for which at least one of the build jobs finished successfully let lastSuccessfulDeploy = completedDeploys.shift(); if (!lastSuccessfulDeploy) { From e0be56db6cfdd2de9991df9190176b2b12384759 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:58:45 +0100 Subject: [PATCH 07/14] correct branch name --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9f3345f3be79..bafe6064d020 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -619,7 +619,7 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' + if: github.ref == 'refs/heads/production' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' needs: [android, desktop, iOS, web, check-deployment-success] steps: - uses: actions/checkout@v4 From 302242376a8e353fd96f3deac72ca0cedaaa9800 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:10:00 +0100 Subject: [PATCH 08/14] Fix lint errors --- .github/workflows/deploy.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bafe6064d020..954bee410b60 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: deployChecklist: name: Create or update deploy checklist uses: ./.github/workflows/createDeployChecklist.yml - if: !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) + if: github.ref == 'refs/heads/staging' needs: validateActor secrets: inherit @@ -520,18 +520,17 @@ jobs: id: check-success run: | success="false" - if [ "${{ needs.android.result }}" == 'success' ] || \ - [ "${{ needs.iOS.result }}" == 'success' ] || \ - [ "${{ needs.desktop.result }}" == 'success' ] || \ - [ "${{ needs.web.result }}" == 'success' ]; then + if [ "${{ needs.android.result }}" == "success" ] || \ + [ "${{ needs.iOS.result }}" == "success" ] || \ + [ "${{ needs.desktop.result }}" == "success" ] || \ + [ "${{ needs.web.result }}" == "success" ]; then success="true" fi - echo "IS_DEPLOYED=$success" >> $GITHUB_ENV - echo "::set-output name=IS_DEPLOYED::$success" + echo "IS_DEPLOYED=\"$success\"" >> "$GITHUB_OUTPUT" createPrerelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' + if: github.ref == 'refs/heads/staging' && needs.check-deployment-success.outputs.IS_DEPLOYED == 'true' needs: [android, desktop, iOS, web, check-deployment-success] steps: - name: Checkout staging branch @@ -619,7 +618,7 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' && ${{ needs.check-deployment-success.outputs.IS_DEPLOYED }} == 'true' + if: github.ref == 'refs/heads/production' && needs.check-deployment-success.outputs.IS_DEPLOYED == 'true' needs: [android, desktop, iOS, web, check-deployment-success] steps: - uses: actions/checkout@v4 From e38a58ea2ba90cd6b23d13e110269a2734256c22 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:16:18 +0100 Subject: [PATCH 09/14] Fix failing test --- tests/unit/awaitStagingDeploysTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/awaitStagingDeploysTest.ts b/tests/unit/awaitStagingDeploysTest.ts index 4d3384f11959..26ce2778de40 100644 --- a/tests/unit/awaitStagingDeploysTest.ts +++ b/tests/unit/awaitStagingDeploysTest.ts @@ -166,7 +166,7 @@ describe('awaitStagingDeploys', () => { }); // Second ping - mockListDeploys.mockResolvedValueOnce({ + mockListDeploysForTag.mockResolvedValueOnce({ data: { workflow_runs: [INCOMPLETE_WORKFLOW], }, @@ -183,7 +183,7 @@ describe('awaitStagingDeploys', () => { }); // Third ping - mockListDeploys.mockResolvedValueOnce({ + mockListDeploysForTag.mockResolvedValueOnce({ data: { workflow_runs: [COMPLETED_WORKFLOW], }, From 960b3a4be99d69f0f7a6a97b832d8bddc0f444a0 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:00:00 +0100 Subject: [PATCH 10/14] Re-order jobs --- .github/workflows/deploy.yml | 206 +++++++++++++++++------------------ 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 954bee410b60..612e910191b3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -414,110 +414,14 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - postSlackMessageOnSuccess: - name: Post a Slack message when all platforms deploy successfully - runs-on: ubuntu-latest - if: ${{ success() }} - needs: [android, desktop, iOS, web] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set current App version in Env - run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - - name: 'Announces the deploy in the #announce Slack room' - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#announce', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - - name: 'Announces the deploy in the #deployer Slack room' - uses: 8398a7/action-slack@v3 - with: - status: custom - custom_payload: | - { - channel: '#deployer', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - - name: 'Announces a production deploy in the #expensify-open-source Slack room' - uses: 8398a7/action-slack@v3 - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - with: - status: custom - custom_payload: | - { - channel: '#expensify-open-source', - attachments: [{ - color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, - }] - } - env: - GITHUB_TOKEN: ${{ github.token }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} - - postGithubComment: - name: Post a GitHub comment when platforms are done building and deploying - runs-on: ubuntu-latest - if: ${{ !cancelled() }} - needs: [android, desktop, iOS, web] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/composite/setupNode - - - name: Set current App version in Env - run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - - name: Get Release Pull Request List - id: getReleasePRList - uses: ./.github/actions/javascript/getDeployPullRequestList - with: - TAG: ${{ env.VERSION }} - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - - - name: Comment on issues - uses: ./.github/actions/javascript/markPullRequestsAsDeployed - with: - PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} - IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - DEPLOY_VERSION: ${{ env.VERSION }} - GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - ANDROID: ${{ needs.android.result }} - DESKTOP: ${{ needs.desktop.result }} - IOS: ${{ needs.iOS.result }} - WEB: ${{ needs.web.result }} - - check-deployment-success: + checkDeploymentSuccess: runs-on: ubuntu-latest outputs: - IS_DEPLOYED: ${{ steps.check-success.outputs.IS_DEPLOYED }} + IS_DEPLOYED: ${{ steps.checkDeploymentSuccess.outputs.IS_DEPLOYED }} needs: [android, desktop, iOS, web] steps: - name: Check deployment success on at least one platform - id: check-success + id: checkDeploymentSuccess run: | success="false" if [ "${{ needs.android.result }}" == "success" ] || \ @@ -530,8 +434,8 @@ jobs: createPrerelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' && needs.check-deployment-success.outputs.IS_DEPLOYED == 'true' - needs: [android, desktop, iOS, web, check-deployment-success] + if: github.ref == 'refs/heads/staging' && needs.checkDeploymentSuccess.outputs.IS_DEPLOYED == 'true' + needs: [checkDeploymentSuccess] steps: - name: Checkout staging branch uses: actions/checkout@v4 @@ -618,8 +522,8 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' && needs.check-deployment-success.outputs.IS_DEPLOYED == 'true' - needs: [android, desktop, iOS, web, check-deployment-success] + if: github.ref == 'refs/heads/production' && needs.checkDeploymentSuccess.outputs.IS_DEPLOYED == 'true' + needs: [checkDeploymentSuccess] steps: - uses: actions/checkout@v4 name: Checkout @@ -683,3 +587,99 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + postSlackMessageOnSuccess: + name: Post a Slack message when all platforms deploy successfully + runs-on: ubuntu-latest + if: ${{ success() }} + needs: [createPrerelease, finalizeRelease] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set current App version in Env + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + + - name: 'Announces the deploy in the #announce Slack room' + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#announce', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + - name: 'Announces the deploy in the #deployer Slack room' + uses: 8398a7/action-slack@v3 + with: + status: custom + custom_payload: | + { + channel: '#deployer', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + - name: 'Announces a production deploy in the #expensify-open-source Slack room' + uses: 8398a7/action-slack@v3 + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + with: + status: custom + custom_payload: | + { + channel: '#expensify-open-source', + attachments: [{ + color: 'good', + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, + }] + } + env: + GITHUB_TOKEN: ${{ github.token }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + postGithubComment: + name: Post a GitHub comment when platforms are done building and deploying + runs-on: ubuntu-latest + if: ${{ !cancelled() }} + needs: [createPrerelease, finalizeRelease] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: ./.github/actions/composite/setupNode + + - name: Set current App version in Env + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + + - name: Get Release Pull Request List + id: getReleasePRList + uses: ./.github/actions/javascript/getDeployPullRequestList + with: + TAG: ${{ env.VERSION }} + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + + - name: Comment on issues + uses: ./.github/actions/javascript/markPullRequestsAsDeployed + with: + PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} + IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + DEPLOY_VERSION: ${{ env.VERSION }} + GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + ANDROID: ${{ needs.android.result }} + DESKTOP: ${{ needs.desktop.result }} + IOS: ${{ needs.iOS.result }} + WEB: ${{ needs.web.result }} From 626142b30910f57ff4b2c9cffd53c21c75526124 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:14:25 +0100 Subject: [PATCH 11/14] Correct conditions --- .github/workflows/deploy.yml | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 612e910191b3..7777ea50d4d6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -417,24 +417,33 @@ jobs: checkDeploymentSuccess: runs-on: ubuntu-latest outputs: - IS_DEPLOYED: ${{ steps.checkDeploymentSuccess.outputs.IS_DEPLOYED }} + IS_AT_LEAST_ONE_PLATFORM_DEPLOYED: ${{ steps.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED }} + IS_ALL_PLATFORMS_DEPLOYED: ${{ steps.checkDeploymentSuccess.outputs.IS_ALL_PLATFORMS_DEPLOYED }} needs: [android, desktop, iOS, web] steps: - name: Check deployment success on at least one platform id: checkDeploymentSuccess run: | - success="false" + isAtLeastOnePlatformDeployed="false" + isAllPlatformsDeployed="false" if [ "${{ needs.android.result }}" == "success" ] || \ [ "${{ needs.iOS.result }}" == "success" ] || \ [ "${{ needs.desktop.result }}" == "success" ] || \ [ "${{ needs.web.result }}" == "success" ]; then - success="true" + isAtLeastOnePlatformDeployed="true" fi - echo "IS_DEPLOYED=\"$success\"" >> "$GITHUB_OUTPUT" + if [ "${{ needs.android.result }}" == "success" ] && \ + [ "${{ needs.iOS.result }}" == "success" ] && \ + [ "${{ needs.desktop.result }}" == "success" ] && \ + [ "${{ needs.web.result }}" == "success" ]; then + isAllPlatformsDeployed="true" + fi + echo "IS_AT_LEAST_ONE_PLATFORM_DEPLOYED=\"$isAtLeastOnePlatformDeployed\"" >> "$GITHUB_OUTPUT" + echo "IS_ALL_PLATFORMS_DEPLOYED=\"$isAllPlatformsDeployed\"" >> "$GITHUB_OUTPUT" createPrerelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' && needs.checkDeploymentSuccess.outputs.IS_DEPLOYED == 'true' + if: github.ref == 'refs/heads/staging' && needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' needs: [checkDeploymentSuccess] steps: - name: Checkout staging branch @@ -522,7 +531,7 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' && needs.checkDeploymentSuccess.outputs.IS_DEPLOYED == 'true' + if: github.ref == 'refs/heads/production' && needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' needs: [checkDeploymentSuccess] steps: - uses: actions/checkout@v4 @@ -591,8 +600,8 @@ jobs: postSlackMessageOnSuccess: name: Post a Slack message when all platforms deploy successfully runs-on: ubuntu-latest - if: ${{ success() }} - needs: [createPrerelease, finalizeRelease] + if: needs.checkDeploymentSuccess.outputs.IS_ALL_PLATFORMS_DEPLOYED == 'true' + needs: [checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout uses: actions/checkout@v4 @@ -652,8 +661,8 @@ jobs: postGithubComment: name: Post a GitHub comment when platforms are done building and deploying runs-on: ubuntu-latest - if: ${{ !cancelled() }} - needs: [createPrerelease, finalizeRelease] + if: needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' + needs: [checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout uses: actions/checkout@v4 From 217a2e327f8d8809b7127ddfd6718be5657d94e9 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:24:41 +0100 Subject: [PATCH 12/14] Fix validate gh actions error --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7777ea50d4d6..f73ebe2f3778 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -662,7 +662,7 @@ jobs: name: Post a GitHub comment when platforms are done building and deploying runs-on: ubuntu-latest if: needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' - needs: [checkDeploymentSuccess, createPrerelease, finalizeRelease] + needs: [android, desktop, iOS, web, checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout uses: actions/checkout@v4 From bbb5722af13d7842d6796a1d30e3e5408abe272c Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 20:52:18 +0100 Subject: [PATCH 13/14] Address review comments --- .github/workflows/deploy.yml | 98 ++++++++++-------------------------- 1 file changed, 26 insertions(+), 72 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f73ebe2f3778..fc3f022f166b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -446,12 +446,6 @@ jobs: if: github.ref == 'refs/heads/staging' && needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' needs: [checkDeploymentSuccess] steps: - - name: Checkout staging branch - uses: actions/checkout@v4 - with: - ref: staging - token: ${{ secrets.OS_BOTIFY_TOKEN }} - - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify @@ -471,45 +465,20 @@ jobs: env: GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }} - - name: Upload Android sourcemaps to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./android-sourcemaps/index.android.bundle.map#android-sourcemap-${{ env.STAGING_VERSION }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload Android build to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./android-build/app-production-release.aab - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload desktop sourcemaps to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload desktop build to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./desktop-build/NewExpensify.dmg - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload iOS sourcemaps to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./ios-sourcemaps/main.jsbundle.map#ios-sourcemap-${{ env.STAGING_VERSION }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload iOS build to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./ios-build/New\ Expensify.ipa - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload web sourcemaps to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload web build to GitHub Release - run: gh release upload ${{ env.STAGING_VERSION }} ./web-build-tar-gz/webBuild.tar.gz ./web-build-tar-gz/webBuild.zip - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Upload artifacts to GitHub Release + run: | + gh release upload ${{ env.STAGING_VERSION }} \ + ./android-sourcemaps/index.android.bundle.map#android-sourcemap-${{ env.STAGING_VERSION }} \ + ./android-build/app-production-release.aab \ + ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} \ + ./desktop-build/NewExpensify.dmg \ + ./ios-sourcemaps/main.jsbundle.map#ios-sourcemap-${{ env.STAGING_VERSION }} \ + ./ios-build/New\ Expensify.ipa \ + ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} \ + ./web-build-tar-gz/webBuild.tar.gz \ + ./web-build-zip/webBuild.zip + env: + GITHUB_TOKEN: ${{ github.token }} - name: Warn deployers if staging deploy failed if: ${{ failure() }} @@ -531,15 +500,9 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' && needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' + if: github.ref == 'refs/heads/production' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) needs: [checkDeploymentSuccess] steps: - - uses: actions/checkout@v4 - name: Checkout - with: - ref: production - token: ${{ secrets.OS_BOTIFY_TOKEN }} - - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify @@ -551,25 +514,16 @@ jobs: - name: Get current app version run: echo "PRODUCTION_VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - name: Upload web sourcemaps to GitHub Release - run: gh release upload ${{ env.PRODUCTION_VERSION }} ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.PRODUCTION_VERSION }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload web build to GitHub Release - run: gh release upload ${{ env.PRODUCTION_VERSION }} ./web-build-tar-gz/webBuild.tar.gz ./web-build-tar-gz/webBuild.zip --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload desktop sourcemaps to GitHub Release - run: gh release upload ${{ env.PRODUCTION_VERSION }} ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.PRODUCTION_VERSION }} --clobber - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Upload desktop build to GitHub Release - run: gh release upload ${{ env.PRODUCTION_VERSION }} ./desktop-build/NewExpensify.dmg --clobber + - name: Upload artifacts to GitHub Release + run: | + gh release upload ${{ env.STAGING_VERSION }} \ + ./desktop-sourcemaps/merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} \ + ./desktop-build/NewExpensify.dmg \ + ./web-sourcemaps/merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} \ + ./web-build-tar-gz/webBuild.tar.gz \ + ./web-build-zip/webBuild.zip env: - GITHUB_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} - name: 🚀 Edit the release to be no longer a prerelease 🚀 run: | @@ -659,9 +613,9 @@ jobs: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} postGithubComment: - name: Post a GitHub comment when platforms are done building and deploying + name: Post a GitHub comments on all deployed PRs when platforms are done building and deploying runs-on: ubuntu-latest - if: needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' + if: fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) needs: [android, desktop, iOS, web, checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout From 951919d39a368bed8a6c73566b3f79c9b95fc14f Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:30:08 +0100 Subject: [PATCH 14/14] address review comments --- .github/workflows/deploy.yml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fc3f022f166b..ad6a1da0deaa 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: deployChecklist: name: Create or update deploy checklist uses: ./.github/workflows/createDeployChecklist.yml - if: github.ref == 'refs/heads/staging' + if: ${{ github.ref == 'refs/heads/staging' }} needs: validateActor secrets: inherit @@ -443,9 +443,17 @@ jobs: createPrerelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/staging' && needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED == 'true' + if: ${{ github.ref == 'refs/heads/staging' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) }} needs: [checkDeploymentSuccess] steps: + # The command "gh release create" also creates and pushes a tag for the version if one does not already exist, + # So we need to checkout the staging branch and create that tag from the staging branch. + - name: Checkout staging branch + uses: actions/checkout@v4 + with: + ref: staging + token: ${{ secrets.OS_BOTIFY_TOKEN }} + - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify @@ -500,9 +508,15 @@ jobs: finalizeRelease: runs-on: ubuntu-latest - if: github.ref == 'refs/heads/production' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) + if: ${{ github.ref == 'refs/heads/production' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) }} needs: [checkDeploymentSuccess] steps: + - uses: actions/checkout@v4 + name: Checkout + with: + ref: production + token: ${{ secrets.OS_BOTIFY_TOKEN }} + - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify @@ -554,7 +568,7 @@ jobs: postSlackMessageOnSuccess: name: Post a Slack message when all platforms deploy successfully runs-on: ubuntu-latest - if: needs.checkDeploymentSuccess.outputs.IS_ALL_PLATFORMS_DEPLOYED == 'true' + if: ${{ fromJSON(needs.checkDeploymentSuccess.outputs.IS_ALL_PLATFORMS_DEPLOYED) }} needs: [checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout @@ -615,7 +629,7 @@ jobs: postGithubComment: name: Post a GitHub comments on all deployed PRs when platforms are done building and deploying runs-on: ubuntu-latest - if: fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) + if: ${{ fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) }} needs: [android, desktop, iOS, web, checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout