diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2e366bf418f8..8c2fa63c5334 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,10 +28,12 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - createTag: + prep: needs: validateActor - if: ${{ github.ref == 'refs/heads/staging' }} + if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} runs-on: ubuntu-latest + outputs: + APP_VERSION: ${{ steps.getAppVersion.outputs.VERSION }} steps: - name: Checkout uses: actions/checkout@v4 @@ -46,9 +48,14 @@ jobs: OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} + - name: Get app version + id: getAppVersion + run: echo "VERSION=$(jq -r .version < package.json)" >> "$GITHUB_OUTPUT" + - name: Create and push tag + if: ${{ github.ref == 'refs/heads/staging' }} run: | - git tag "$(jq -r .version < package.json)" + git tag ${{ steps.getAppVersion.outputs.VERSION }} git push origin --tags # Note: we're updating the checklist before running the deploys and assuming that it will succeed on at least one platform @@ -56,14 +63,13 @@ jobs: name: Create or update deploy checklist uses: ./.github/workflows/createDeployChecklist.yml if: ${{ github.ref == 'refs/heads/staging' }} - needs: createTag + needs: prep 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) }} + needs: prep runs-on: ubuntu-latest-xl steps: - name: Checkout @@ -96,8 +102,9 @@ jobs: 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: Get Android native version + id: getAndroidVersion + run: echo "VERSION_CODE=$(grep -o 'versionCode\s\+[0-9]\+' android/app/build.gradle | awk '{ print $2 }')" >> "$GITHUB_OUTPUTS" - name: Run Fastlane run: bundle exec fastlane android ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} @@ -105,7 +112,7 @@ jobs: RUBYOPT: '-rostruct' MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }} MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} - VERSION: ${{ env.VERSION_CODE }} + VERSION: ${{ steps.getAndroidVersion.outputs.VERSION_CODE }} - name: Upload Android build to Browser Stack if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -141,7 +148,7 @@ jobs: attachments: [{ color: "#DB4545", pretext: ``, - text: `💥 Android production deploy failed. Please manually submit ${{ env.VERSION }} in the . 💥`, + text: `💥 Android production deploy failed. Please manually submit ${{ needs.prep.outputs.APP_VERSION }} in the . 💥`, }] } env: @@ -151,8 +158,7 @@ jobs: 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) }} + needs: prep runs-on: macos-14-large steps: - name: Checkout @@ -197,8 +203,7 @@ jobs: 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) }} + needs: prep env: DEVELOPER_DIR: /Applications/Xcode_15.2.0.app/Contents/Developer runs-on: macos-13-xlarge @@ -260,8 +265,9 @@ jobs: - 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 '${{ env.VERSION }}' | tr '-' '.')" >> "$GITHUB_ENV" + - name: Get iOS native version + id: getIOSVersion + run: echo "IOS_VERSION=$(echo '${{ needs.prep.outputs.APP_VERSION }}' | tr '-' '.')" >> "$GITHUB_OUTPUTS" - name: Run Fastlane run: bundle exec fastlane ios ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} @@ -270,7 +276,7 @@ jobs: 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 }} + VERSION: ${{ steps.getIOSVersion.outputs.IOS_VERSION }} - name: Upload iOS build to Browser Stack if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -303,7 +309,7 @@ jobs: attachments: [{ color: "#DB4545", pretext: ``, - text: `💥 iOS production deploy failed. Please manually submit ${{ env.IOS_VERSION }} in the . 💥`, + text: `💥 iOS production deploy failed. Please manually submit ${{ steps.getIOSVersion.outputs.IOS_VERSION }} in the . 💥`, }] } env: @@ -313,8 +319,7 @@ jobs: 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) }} + needs: prep runs-on: ubuntu-latest-xl steps: - name: Checkout @@ -371,8 +376,8 @@ jobs: run: | sleep 5 DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://staging.new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ env.VERSION }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ env.VERSION }}. Something went wrong..." + if [[ '${{ needs.prep.outputs.APP_VERSION }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ needs.prep.outputs.APP_VERSION }}. Something went wrong..." exit 1 fi @@ -381,8 +386,8 @@ jobs: run: | sleep 5 DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://new.expensify.com/version.json | jq -r '.version')" - if [[ '${{ env.VERSION }}' != "$DOWNLOADED_VERSION" ]]; then - echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ env.VERSION }}. Something went wrong..." + if [[ '${{ needs.prep.outputs.APP_VERSION }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version $DOWNLOADED_VERSION does not match local version ${{ needs.prep.outputs.APP_VERSION }}. Something went wrong..." exit 1 fi @@ -426,8 +431,8 @@ jobs: # 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.ref == 'refs/heads/staging' }} + needs: prep + if: ${{ github.ref == 'refs/heads/staging' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -468,23 +473,17 @@ jobs: createPrerelease: runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/staging' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) }} - needs: [checkDeploymentSuccess] + needs: [prep, checkDeploymentSuccess] steps: - - name: Checkout staging branch - uses: actions/checkout@v4 - - - name: Get current app version - run: echo "STAGING_VERSION=$(jq -r .version < package.json)" >> "$GITHUB_ENV" - - 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 + gh release create ${{ needs.prep.outputs.APP_VERSION }} --title ${{ needs.prep.outputs.APP_VERSION }} --generate-notes --prerelease --target staging RETRIES=0 MAX_RETRIES=10 - until [[ $(gh release view ${{ env.STAGING_VERSION }}) || $RETRIES -ge $MAX_RETRIES ]]; do + until [[ $(gh release view ${{ needs.prep.outputs.APP_VERSION }}) || $RETRIES -ge $MAX_RETRIES ]]; do echo "release not found, retrying $((MAX_RETRIES - RETRIES++)) times" sleep 1 done @@ -498,14 +497,14 @@ jobs: - name: Upload artifacts to GitHub Release run: | - gh release upload ${{ env.STAGING_VERSION }} \ - ./android-sourcemaps-artifact/index.android.bundle.map#android-sourcemap-${{ env.STAGING_VERSION }} \ + gh release upload ${{ needs.prep.outputs.APP_VERSION }} \ + ./android-sourcemaps-artifact/index.android.bundle.map#android-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./android-build-artifact/app-production-release.aab \ - ./desktop-sourcemaps-artifact/desktop-merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} \ + ./desktop-sourcemaps-artifact/desktop-merged-source-map.js.map#desktop-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./desktop-build-artifact/NewExpensify.dmg \ - ./ios-sourcemaps-artifact/main.jsbundle.map#ios-sourcemap-${{ env.STAGING_VERSION }} \ + ./ios-sourcemaps-artifact/main.jsbundle.map#ios-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./ios-build-artifact/New\ Expensify.ipa \ - ./web-sourcemaps-artifact/web-merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} \ + ./web-sourcemaps-artifact/web-merged-source-map.js.map#web-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./web-build-tar-gz-artifact/webBuild.tar.gz \ ./web-build-zip-artifact/webBuild.zip env: @@ -532,14 +531,8 @@ jobs: finalizeRelease: runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/production' && fromJSON(needs.checkDeploymentSuccess.outputs.IS_AT_LEAST_ONE_PLATFORM_DEPLOYED) }} - needs: [checkDeploymentSuccess] + needs: [prep, checkDeploymentSuccess] steps: - - name: Checkout production branch - uses: actions/checkout@v4 - - - name: Get current app version - run: echo "PRODUCTION_VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" - - name: Download all workflow run artifacts uses: actions/download-artifact@v4 @@ -550,10 +543,10 @@ jobs: - name: Upload artifacts to GitHub Release run: | - gh release upload ${{ env.STAGING_VERSION }} \ - ./desktop-sourcemaps-artifact/desktop-merged-source-map.js.map#desktop-sourcemap-${{ env.STAGING_VERSION }} \ + gh release upload ${{ needs.prep.outputs.APP_VERSION }} \ + ./desktop-sourcemaps-artifact/desktop-merged-source-map.js.map#desktop-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./desktop-build-artifact/NewExpensify.dmg \ - ./web-sourcemaps-artifact/web-merged-source-map.js.map#web-sourcemap-${{ env.STAGING_VERSION }} \ + ./web-sourcemaps-artifact/web-merged-source-map.js.map#web-sourcemap-${{ needs.prep.outputs.APP_VERSION }} \ ./web-build-tar-gz-artifact/webBuild.tar.gz \ ./web-build-zip-artifact/webBuild.zip env: @@ -562,8 +555,8 @@ jobs: - 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" | jq -r '.body' >> releaseNotes.md - gh release edit ${{ env.PRODUCTION_VERSION }} --prerelease=false --latest --notes-file releaseNotes.md + gh api --method POST /repos/Expensify/App/releases/generate-notes -f "tag_name=${{ needs.prep.outputs.APP_VERSION }}" -f "previous_tag_name=$LATEST_RELEASE" | jq -r '.body' >> releaseNotes.md + gh release edit ${{ needs.prep.outputs.APP_VERSION }} --prerelease=false --latest --notes-file releaseNotes.md env: GITHUB_TOKEN: ${{ github.token }} @@ -589,14 +582,8 @@ jobs: name: Post a Slack message when all platforms deploy successfully runs-on: ubuntu-latest if: ${{ fromJSON(needs.checkDeploymentSuccess.outputs.IS_ALL_PLATFORMS_DEPLOYED) }} - needs: [checkDeploymentSuccess, createPrerelease, finalizeRelease] + needs: [prep, checkDeploymentSuccess, 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: @@ -606,7 +593,7 @@ jobs: channel: '#announce', attachments: [{ color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, }] } env: @@ -622,7 +609,7 @@ jobs: channel: '#deployer', attachments: [{ color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'staging' }} 🎉️`, }] } env: @@ -639,7 +626,7 @@ jobs: channel: '#expensify-open-source', attachments: [{ color: 'good', - text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, + text: `🎉️ Successfully deployed ${process.env.AS_REPO} to production 🎉️`, }] } env: @@ -650,7 +637,7 @@ jobs: 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) }} - needs: [android, desktop, iOS, web, checkDeploymentSuccess, createPrerelease, finalizeRelease] + needs: [prep, android, desktop, iOS, web, checkDeploymentSuccess, createPrerelease, finalizeRelease] steps: - name: Checkout uses: actions/checkout@v4 @@ -658,14 +645,11 @@ jobs: - 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 }} + TAG: ${{ needs.prep.outputs.APP_VERSION }} GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -674,7 +658,7 @@ jobs: with: PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} IS_PRODUCTION_DEPLOY: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - DEPLOY_VERSION: ${{ env.VERSION }} + DEPLOY_VERSION: ${{ needs.prep.outputs.APP_VERSION }} GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} ANDROID: ${{ needs.android.result }} DESKTOP: ${{ needs.desktop.result }}