diff --git a/.circleci/config.yml b/.circleci/config.yml index 43d595c3e02..4320729ccce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -297,7 +297,7 @@ commands: - run: *update-fastlane-android - run: name: Fastlane Play Store Upload - command: bundle exec fastlane android beta official:<< parameters.official >> + command: bundle exec fastlane android beta_circle_ci official:<< parameters.official >> working_directory: android # EXPERIMENTAL ONLY @@ -314,7 +314,7 @@ commands: - run: *update-fastlane-android - run: name: Fastlane Play Store Upload - command: bundle exec fastlane android internal_app_sharing + command: bundle exec fastlane android internal_app_sharing_circle_ci working_directory: android # EXPERIMENTAL ONLY @@ -332,7 +332,7 @@ commands: - run: *update-fastlane-android - run: name: Fastlane Play Store Upload - command: bundle exec fastlane android production + command: bundle exec fastlane android production_circle_ci working_directory: android upload-to-testflight: @@ -354,7 +354,7 @@ commands: name: Fastlane Tesflight Upload command: | echo $APP_STORE_CONNECT_API_KEY_BASE64 | base64 --decode > ./fastlane/app_store_connect_api_key.p8 - bundle exec fastlane ios beta official:<< parameters.official >> + bundle exec fastlane ios beta_circle_ci official:<< parameters.official >> working_directory: ios - save_cache: *save-gems-cache @@ -714,14 +714,4 @@ workflows: requires: - android-hold-google-play-beta-official - # Android Automatic Experimental - - android-automatic-build-experimental: - filters: - branches: - only: - - develop - requires: - - lint-testunit - - android-google-play-production-experimental: - requires: - - android-automatic-build-experimental + diff --git a/.github/actions/generate-version-code/action.yml b/.github/actions/generate-version-code/action.yml index 2e6262e52c7..13f203e8d27 100644 --- a/.github/actions/generate-version-code/action.yml +++ b/.github/actions/generate-version-code/action.yml @@ -1,6 +1,38 @@ name: Generate Version Code description: Generates version code from GitHub run number +inputs: + official: + type: boolean + required: true + os: + type: string + required: true + FASTLANE_GOOGLE_SERVICE_ACCOUNT: + type: string + required: true + APP_STORE_CONNECT_API_KEY_BASE64: + type: string + required: true + MATCH_KEYCHAIN_NAME: + type: string + required: false + MATCH_KEYCHAIN_PASSWORD: + type: string + required: false + MATCH_PASSWORD: + type: string + required: false + APP_STORE_CONNECT_API_KEY_ID: + type: string + required: false + APP_STORE_CONNECT_API_KEY_ISSUER_ID: + type: string + required: false + FASTLANE_REPO_PAT: + type: string + required: false + outputs: VERSIONCODE: description: "Generated version code" @@ -9,16 +41,73 @@ outputs: runs: using: "composite" steps: + - name: Set up Xcode + if: ${{ inputs.os == 'ios' }} + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.2' + + - name: Set up Ruby and Bundler + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7.7 + bundler-cache: true + + - name: Install Fastlane + if: ${{ inputs.os == 'android' }} + working-directory: android + run: | + bundle install --path gems + shell: bash + + - name: Store the Google service account key + if: ${{ inputs.os == 'android' }} + working-directory: android + run: | + echo "${{ inputs.FASTLANE_GOOGLE_SERVICE_ACCOUNT }}" | base64 --decode > service_account.json + shell: bash + + - name: Decode p8 + if: ${{ inputs.os == 'ios' }} + run: | + echo ${{ inputs.APP_STORE_CONNECT_API_KEY_BASE64 }} | base64 --decode > ./ios/fastlane/app_store_connect_api_key.p8 + shell: bash + + - name: Compute VERSIONCODE (iOS) + id: compute-versioncode-ios + if: ${{ inputs.os == 'ios' }} + shell: bash + run: | + VERSIONCODE=$(bundle exec fastlane ios get_testflight_version | grep 'VERSIONCODE=' | cut -d '=' -f2) + echo "LATEST_VERSIONCODE=$VERSIONCODE" >> $GITHUB_OUTPUT + working-directory: ios + env: + MATCH_KEYCHAIN_NAME: ${{ inputs.MATCH_KEYCHAIN_NAME }} + MATCH_KEYCHAIN_PASSWORD: ${{ inputs.MATCH_KEYCHAIN_PASSWORD }} + MATCH_PASSWORD: ${{ inputs.MATCH_PASSWORD }} + APP_STORE_CONNECT_API_KEY_ID: ${{ inputs.APP_STORE_CONNECT_API_KEY_ID }} + APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ inputs.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + FASTLANE_REPO_PAT: ${{ inputs.FASTLANE_REPO_PAT }} + + - name: Compute VERSIONCODE (Android) + id: compute-versioncode-android + if: ${{ inputs.os == 'android' }} + shell: bash + run: | + VERSIONCODE=$(bundle exec fastlane android version_code | grep 'VERSIONCODE=' | cut -d '=' -f2) + echo "LATEST_VERSIONCODE=$VERSIONCODE" >> $GITHUB_OUTPUT + working-directory: android + - name: Compute VERSIONCODE id: compute shell: bash - env: - GITHUB_RUN_NUMBER: ${{ github.run_number }} run: | - # This offset is from CircleCI after we migrated to Github Actions in order to have sequential builds + VERSION_IOS="${{ steps.compute-versioncode-ios.outputs.LATEST_VERSIONCODE }}" + VERSION_ANDROID="${{ steps.compute-versioncode-android.outputs.LATEST_VERSIONCODE }}" - OFFSET=87750 - VERSIONCODE=$((OFFSET + GITHUB_RUN_NUMBER)) + LATEST_VERSIONCODE="${VERSION_IOS:-$VERSION_ANDROID}" + + VERSIONCODE=$((LATEST_VERSIONCODE + 1)) echo "VERSIONCODE=$VERSIONCODE" >> $GITHUB_OUTPUT echo "### 📦 Version Code Generated" >> $GITHUB_STEP_SUMMARY diff --git a/.github/actions/upload-android/action.yml b/.github/actions/upload-android/action.yml index ea5bccb4517..afca338624e 100644 --- a/.github/actions/upload-android/action.yml +++ b/.github/actions/upload-android/action.yml @@ -13,6 +13,10 @@ inputs: VERSIONCODE: description: 'Version code for build' required: true + trigger: + description: 'Trigger for build' + required: true + default: pr runs: using: "composite" @@ -52,10 +56,20 @@ runs: - name: Fastlane Play Store Upload working-directory: android run: | - bundle exec fastlane android beta official:${{ inputs.type == 'official' }} + if [[ ${{ inputs.trigger }} == "pr" ]]; then + bundle exec fastlane android beta official:${{ inputs.type == 'official' }} + fi + if [[ ${{ inputs.trigger }} == "develop" ]] && [[ ${{ inputs.type }} == 'experimental' ]]; then + bundle exec fastlane android experimental_production + fi + if [[ ${{ inputs.trigger }} == "develop" ]] && [[ ${{ inputs.type }} == 'official' ]]; then + bundle exec fastlane android official_open_testing + fi + shell: bash - name: Leave a comment on PR + if: ${{ inputs.trigger == 'pr' }} env: GH_TOKEN: ${{ inputs.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/actions/upload-internal-android/action.yml b/.github/actions/upload-internal-android/action.yml index a872c5db8db..77f00d8fee4 100644 --- a/.github/actions/upload-internal-android/action.yml +++ b/.github/actions/upload-internal-android/action.yml @@ -13,7 +13,11 @@ inputs: VERSIONCODE: description: 'Version code for build' required: true - + trigger: + description: 'Trigger for build' + required: false + default: pr + runs: using: "composite" steps: @@ -75,6 +79,7 @@ runs: shell: bash - name: Share Internal App Sharing Link + if: ${{ inputs.trigger == 'pr' }} env: GH_TOKEN: ${{ inputs.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/actions/upload-ios/action.yml b/.github/actions/upload-ios/action.yml index cd183dad2a4..477151aab1c 100644 --- a/.github/actions/upload-ios/action.yml +++ b/.github/actions/upload-ios/action.yml @@ -28,6 +28,10 @@ inputs: GITHUB_TOKEN: description: 'GitHub token for commenting' required: true + trigger: + description: 'Trigger for build' + required: false + default: pr runs: using: "composite" @@ -138,6 +142,7 @@ runs: shell: bash - name: Comment on PR with TestFlight Info + if: ${{ inputs.trigger == 'pr' }} env: GH_TOKEN: ${{ inputs.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 69ba410e2d8..60e8d2fef17 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -6,11 +6,16 @@ on: type: type: string required: true + trigger: + type: string + required: false + default: pr jobs: build-hold: name: Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: experimental_android_build steps: - run: echo "Waiting for manual approval..." @@ -19,7 +24,7 @@ jobs: name: Build runs-on: ubuntu-latest needs: [build-hold] - if: ${{ inputs.type == 'experimental' }} + if: ${{ inputs.type == 'experimental' && (always() && (needs.build-hold.result == 'success' || needs.build-hold.result == 'skipped')) }} outputs: VERSIONCODE: ${{ steps.version.outputs.VERSIONCODE }} steps: @@ -32,9 +37,14 @@ jobs: - name: Generate Version Code id: version uses: ./.github/actions/generate-version-code + with: + official: false + os: android + FASTLANE_GOOGLE_SERVICE_ACCOUNT: ${{ secrets.FASTLANE_GOOGLE_SERVICE_ACCOUNT }} - name: Build Android uses: ./.github/actions/build-android + timeout-minutes: 40 with: type: 'experimental' BUGSNAG_KEY: ${{ secrets.BUGSNAG_KEY }} @@ -49,6 +59,7 @@ jobs: name: Upload Hold runs-on: ubuntu-latest needs: [build-android] + if: ${{ inputs.trigger == 'pr' }} environment: upload_experimental_android steps: - run: echo "Waiting for manual approval..." @@ -56,8 +67,8 @@ jobs: upload-android: name: Upload runs-on: ubuntu-latest - needs: [upload-hold] - if: ${{ inputs.type == 'experimental' }} + needs: [upload-hold, build-android] + if: ${{ inputs.type == 'experimental' && (always() && (needs.upload-hold.result == 'success' || needs.upload-hold.result == 'skipped') && needs.build-android.result == 'success') }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -69,6 +80,7 @@ jobs: uses: ./.github/actions/upload-android with: type: experimental + trigger: ${{ inputs.trigger }} FASTLANE_GOOGLE_SERVICE_ACCOUNT: ${{ secrets.FASTLANE_GOOGLE_SERVICE_ACCOUNT }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSIONCODE: ${{ needs.build-android.outputs.VERSIONCODE }} @@ -77,7 +89,7 @@ jobs: name: Internal Sharing runs-on: ubuntu-latest needs: [build-android] - if: ${{ inputs.type == 'experimental' }} + if: ${{ inputs.type == 'experimental' && inputs.trigger == 'pr' }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -91,4 +103,4 @@ jobs: type: experimental FASTLANE_GOOGLE_SERVICE_ACCOUNT: ${{ secrets.FASTLANE_GOOGLE_SERVICE_ACCOUNT }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VERSIONCODE: ${{ needs.build-android.outputs.VERSIONCODE }} + VERSIONCODE: ${{ needs.build-android.outputs.VERSIONCODE }} \ No newline at end of file diff --git a/.github/workflows/build-develop.yml b/.github/workflows/build-develop.yml new file mode 100644 index 00000000000..48ffc62e564 --- /dev/null +++ b/.github/workflows/build-develop.yml @@ -0,0 +1,55 @@ +name: Build Develop + +permissions: + contents: read + +on: + push: + branches: + - 'develop' + +jobs: + run-eslint-and-test: + name: ESLint and Test + if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} + uses: ./.github/workflows/eslint.yml + + android-build-experimental-store: + name: Build Android Experimental + if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} + uses: ./.github/workflows/build-android.yml + needs: [run-eslint-and-test] + secrets: inherit + with: + type: experimental + trigger: develop + + android-build-official-store: + name: Build Android Official + if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} + uses: ./.github/workflows/build-official-android.yml + needs: [run-eslint-and-test] + secrets: inherit + with: + type: official + trigger: develop + + ios-build-experimental-store: + name: Build iOS Experimental + if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} + uses: ./.github/workflows/build-ios.yml + needs: [run-eslint-and-test] + secrets: inherit + with: + type: experimental + trigger: develop + + ios-build-official-store: + name: Build iOS Official + if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} + uses: ./.github/workflows/build-official-ios.yml + needs: [run-eslint-and-test] + secrets: inherit + with: + type: official + trigger: develop \ No newline at end of file diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml index d8e8bd7072b..ba4985429d3 100644 --- a/.github/workflows/build-ios.yml +++ b/.github/workflows/build-ios.yml @@ -6,11 +6,16 @@ on: type: type: string required: true + trigger: + type: string + required: false + default: pr jobs: build-hold: name: Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: experimental_ios_build steps: - run: echo "Waiting for manual approval..." @@ -19,7 +24,7 @@ jobs: name: Build runs-on: macos-15 needs: [build-hold] - if: ${{ inputs.type == 'experimental' }} + if: ${{ inputs.type == 'experimental' && (always() && (needs.build-hold.result == 'success' || needs.build-hold.result == 'skipped')) }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -30,9 +35,20 @@ jobs: - name: Generate Version Code id: version uses: ./.github/actions/generate-version-code + with: + official: false + os: ios + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} + MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} + APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + FASTLANE_REPO_PAT: ${{ secrets.FASTLANE_REPO_PAT }} - name: Build iOS uses: ./.github/actions/build-ios + timeout-minutes: 40 with: type: experimental MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} @@ -49,7 +65,7 @@ jobs: name: Upload runs-on: macos-15 needs: [build-ios] - if: ${{ inputs.type == 'experimental' }} + if: ${{ inputs.type == 'experimental' && (always() && (needs.build-ios.result == 'success')) }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -61,6 +77,7 @@ jobs: uses: ./.github/actions/upload-ios with: type: experimental + trigger: ${{ inputs.trigger }} MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} diff --git a/.github/workflows/build-official-android.yml b/.github/workflows/build-official-android.yml index e9795a07592..c035d515a89 100644 --- a/.github/workflows/build-official-android.yml +++ b/.github/workflows/build-official-android.yml @@ -6,11 +6,16 @@ on: type: type: string required: true + trigger: + type: string + required: false + default: pr jobs: build-hold: name: Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: official_android_build steps: - run: echo "Waiting for manual approval..." @@ -19,7 +24,7 @@ jobs: name: Build runs-on: ubuntu-latest needs: build-hold - if: ${{ inputs.type == 'official' }} + if: ${{ inputs.type == 'official' && (always() && (needs.build-hold.result == 'success' || needs.build-hold.result == 'skipped')) }} outputs: VERSIONCODE: ${{ steps.version.outputs.VERSIONCODE }} steps: @@ -32,9 +37,14 @@ jobs: - name: Generate Version Code id: version uses: ./.github/actions/generate-version-code + with: + official: true + os: android + FASTLANE_GOOGLE_SERVICE_ACCOUNT: ${{ secrets.FASTLANE_GOOGLE_SERVICE_ACCOUNT }} - name: Build Android uses: ./.github/actions/build-android + timeout-minutes: 40 with: type: official GOOGLE_SERVICES_ANDROID: ${{ secrets.GOOGLE_SERVICES_ANDROID }} @@ -48,6 +58,7 @@ jobs: upload-hold: name: Upload Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: upload_official_android needs: [build-android] steps: @@ -57,7 +68,7 @@ jobs: name: Upload runs-on: ubuntu-latest needs: [upload-hold] - if: ${{ inputs.type == 'official' }} + if: ${{ inputs.type == 'official' && (always() && (needs.upload-hold.result == 'success' || needs.upload-hold.result == 'skipped')) }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -66,6 +77,7 @@ jobs: uses: ./.github/actions/upload-android with: type: official + trigger: ${{ inputs.trigger }} FASTLANE_GOOGLE_SERVICE_ACCOUNT: ${{ secrets.FASTLANE_GOOGLE_SERVICE_ACCOUNT }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSIONCODE: ${{ needs.build-android.outputs.VERSIONCODE }} @@ -74,7 +86,7 @@ jobs: name: Internal Sharing runs-on: ubuntu-latest needs: [build-android] - if: ${{ inputs.type == 'official' }} + if: ${{ inputs.type == 'official' && inputs.trigger == 'pr' }} steps: - name: Checkout Repository uses: actions/checkout@v4 diff --git a/.github/workflows/build-official-ios.yml b/.github/workflows/build-official-ios.yml index 815995bb83f..e2440548fbd 100644 --- a/.github/workflows/build-official-ios.yml +++ b/.github/workflows/build-official-ios.yml @@ -6,11 +6,16 @@ on: type: type: string required: true + trigger: + type: string + required: false + default: pr jobs: build-hold: name: Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: official_ios_build steps: - run: echo "Waiting for manual approval..." @@ -19,7 +24,7 @@ jobs: name: Build runs-on: macos-15 needs: [build-hold] - if: ${{ inputs.type == 'official' }} + if: ${{ inputs.type == 'official' && (always() && (needs.build-hold.result == 'success' || needs.build-hold.result == 'skipped')) }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -30,9 +35,20 @@ jobs: - name: Generate Version Code id: version uses: ./.github/actions/generate-version-code + with: + official: true + os: ios + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} + MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} + APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + FASTLANE_REPO_PAT: ${{ secrets.FASTLANE_REPO_PAT }} - name: Build iOS uses: ./.github/actions/build-ios + timeout-minutes: 40 with: type: official MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} @@ -49,6 +65,7 @@ jobs: upload-hold: name: Upload Hold runs-on: ubuntu-latest + if: ${{ inputs.trigger == 'pr' }} environment: upload_official_ios needs: [build-ios] steps: @@ -58,7 +75,7 @@ jobs: name: Upload runs-on: macos-15 needs: [upload-hold] - if: ${{ inputs.type == 'official' }} + if: ${{ inputs.type == 'official' && (always() && (needs.upload-hold.result == 'success' || needs.upload-hold.result == 'skipped')) }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -70,6 +87,7 @@ jobs: uses: ./.github/actions/upload-ios with: type: official + trigger: ${{ inputs.trigger }} MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }} MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index fcf7d3dcc32..f0e83eaf052 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -9,6 +9,10 @@ on: branches: - '*' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: run-eslint-and-test: name: ESLint and Test @@ -23,6 +27,7 @@ jobs: secrets: inherit with: type: experimental + trigger: "pr" android-build-official-store: name: Build Android Official @@ -32,6 +37,7 @@ jobs: secrets: inherit with: type: official + trigger: "pr" ios-build-experimental-store: name: Build iOS Experimental @@ -41,6 +47,7 @@ jobs: secrets: inherit with: type: experimental + trigger: "pr" ios-build-official-store: name: Build iOS Official @@ -49,4 +56,5 @@ jobs: needs: [run-eslint-and-test] secrets: inherit with: - type: official \ No newline at end of file + type: official + trigger: "pr" \ No newline at end of file diff --git a/.github/workflows/lint-testunit.yml b/.github/workflows/lint-testunit.yml deleted file mode 100644 index 4f96fbc7093..00000000000 --- a/.github/workflows/lint-testunit.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Lint and Unit Tests - -on: - pull_request: - branches: - - '*' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - lint-testunit: - if: ${{ github.repository == 'RocketChat/Rocket.Chat.ReactNative' }} - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - cache: 'yarn' - - - name: Cache node_modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }} - - - name: Install dependencies - run: yarn install --frozen-lockfile - - - name: Run ESLint - run: yarn lint - - - name: Run Tests - run: yarn test --runInBand diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index ddd98481eb9..10316d2ed95 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -20,22 +20,8 @@ jobs: with: fetch-depth: 0 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '22' - cache: 'yarn' - - - name: Cache node_modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }} - - - name: Install dependencies - run: yarn install + - name: Checkout and Setup Node + uses: ./.github/actions/setup-node - name: Run Prettier run: yarn prettier --write . diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile index 96dc7c6411f..da9c958269f 100644 --- a/android/fastlane/Fastfile +++ b/android/fastlane/Fastfile @@ -16,6 +16,83 @@ default_platform(:android) platform :android do + def with_retries(times: 3, sleep_time: 10) + tries = 0 + begin + yield + rescue => e + tries += 1 + if tries < times + UI.error("Retrying due to error: #{e}") + sleep(sleep_time) + retry + else + raise + end + end + end + + desc 'Get the highest version code from all tracks' + lane :version_code do |options| + production_versions = with_retries do + google_play_track_version_codes( + package_name: options[:official] ? 'chat.rocket.android' : 'chat.rocket.reactnative', + json_key: 'service_account.json', + track: 'production' + ) + end + + beta_versions = with_retries do + google_play_track_version_codes( + package_name: options[:official] ? 'chat.rocket.android' : 'chat.rocket.reactnative', + json_key: 'service_account.json', + track: 'beta' + ) + end + + alpha_versions = with_retries do + google_play_track_version_codes( + package_name: options[:official] ? 'chat.rocket.android' : 'chat.rocket.reactnative', + json_key: 'service_account.json', + track: 'alpha' + ) + end + + internal_versions = with_retries do + google_play_track_version_codes( + package_name: options[:official] ? 'chat.rocket.android' : 'chat.rocket.reactnative', + json_key: 'service_account.json', + track: 'internal' + ) + end + + all_versions = production_versions + beta_versions + alpha_versions + internal_versions + highest_version = all_versions.max + + UI.message("All: #{all_versions}") + UI.success("Highest: #{highest_version}") + UI.success("Highest + 1: #{highest_version + 1}") + + puts "VERSIONCODE=#{highest_version}" + end + + desc "Upload App to Play Store Internal (Circle CI)" + lane :beta_circle_ci do |options| + if options[:official] + upload_to_play_store( + package_name: 'chat.rocket.android', + track: 'internal', + aab: 'android/app/build/outputs/bundle/officialRelease/app-official-release.aab' + ) + else + upload_to_play_store( + package_name: 'chat.rocket.reactnative', + track: 'internal', + aab: 'android/app/build/outputs/bundle/experimentalRelease/app-experimental-release.aab' + ) + end + end + desc "Upload App to Play Store Internal" lane :beta do |options| if options[:official] @@ -33,6 +110,21 @@ platform :android do end end + desc "Upload App to Internal App Sharing (Circle CI)" + lane :internal_app_sharing_circle_ci do |options| + if options[:official] + upload_to_play_store_internal_app_sharing( + package_name: 'chat.rocket.android', + aab: 'android/app/build/outputs/bundle/officialRelease/app-official-release.aab' + ) + else + upload_to_play_store_internal_app_sharing( + package_name: 'chat.rocket.reactnative', + aab: 'android/app/build/outputs/bundle/experimentalRelease/app-experimental-release.aab' + ) + end + end + desc "Upload App to Internal App Sharing" lane :internal_app_sharing do |options| if options[:official] @@ -48,12 +140,30 @@ platform :android do end end + desc "Upload App to Play Store Production (Circle CI)" + lane :production_circle_ci do |options| + upload_to_play_store( + package_name: 'chat.rocket.reactnative', + track: 'production', + aab: 'android/app/build/outputs/bundle/experimentalRelease/app-experimental-release.aab' + ) + end + desc "Upload App to Play Store Production" - lane :production do |options| + lane :experimental_production do upload_to_play_store( package_name: 'chat.rocket.reactnative', track: 'production', aab: 'app/build/outputs/bundle/experimentalRelease/app-experimental-release.aab' ) end + + desc "Upload App to Play Store Open Testing" + lane :official_open_testing do + upload_to_play_store( + package_name: 'chat.rocket.android', + track: 'beta', + aab: 'app/build/outputs/bundle/officialRelease/app-official-release.aab' + ) + end end diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index cf7c0b98d65..3040cddd876 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -25,6 +25,43 @@ platform :ios do ) end + desc "Get testflight version" + lane :get_testflight_version do |options| + api_key = app_store_connect_api_key( + key_id: ENV["APP_STORE_CONNECT_API_KEY_ID"], + issuer_id: ENV["APP_STORE_CONNECT_API_KEY_ISSUER_ID"], + key_filepath: 'fastlane/app_store_connect_api_key.p8', + in_house: false + ) + latest_version = latest_testflight_build_number( + app_identifier: options[:official] ? 'chat.rocket.ios' : 'chat.rocket.reactnative' + ) + + UI.message("Latest version: #{latest_version}") + puts "VERSIONCODE=#{latest_version}" + end + + desc "Submit a new Beta Build to Apple TestFlight (Circle CI)" + lane :beta_circle_ci do |options| + api_key = app_store_connect_api_key( + key_id: ENV["APP_STORE_CONNECT_API_KEY_ID"], + issuer_id: ENV["APP_STORE_CONNECT_API_KEY_ISSUER_ID"], + key_filepath: 'fastlane/app_store_connect_api_key.p8', + in_house: false + ) + pilot( + ipa: 'ios/Rocket.Chat.ipa', + app_identifier: options[:official] ? 'chat.rocket.ios' : 'chat.rocket.reactnative', + skip_waiting_for_build_processing: true + ) + upload_symbols_to_crashlytics(dsym_path: "./ios/Rocket.Chat.app.dSYM.zip") + upload_symbols_to_bugsnag( + config_file: "./RocketChatRN/Info.plist", + dsym_path: "./ios/Rocket.Chat.app.dSYM.zip", + api_key: options[:official] ? ENV["BUGSNAG_KEY_OFFICIAL"] : ENV["BUGSNAG_KEY"] + ) + end + desc "Submit a new Beta Build to Apple TestFlight" lane :beta do |options| api_key = app_store_connect_api_key(