diff --git a/.github/workflows/android-appetize.yml b/.github/workflows/android-appetize.yml deleted file mode 100644 index 380df505d..000000000 --- a/.github/workflows/android-appetize.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Android Appetize - -on: pull_request - -jobs: - android-distribute-to-appetize: - runs-on: ubuntu-latest - name: "Build and upload app to Appetize ๐Ÿš€" - steps: - - - name: Cancel previous jobs - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ github.token }} - - - uses: actions/checkout@v3 - - - uses: ruby/setup-ruby@v1 - with: - ruby-version: "2.6" - bundler-cache: true - - - uses: actions/setup-ruby@v1 - with: - ruby-version: '2.6' - - - name: Install npm - run: | - npm config set legacy-peer-deps true install - - name: Install packages - run: | - yarn - - name: Distribute the React Native Android app on Appetize ๐Ÿš€ - run: bundle exec fastlane android preview - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - SOURCE_BRANCH: ${{ github.head_ref }} - APPETIZE_API_TOKEN: ${{ secrets.APPETIZE_API_TOKEN }} diff --git a/.github/workflows/android-preview.yml b/.github/workflows/android-preview.yml new file mode 100644 index 000000000..92ef24ae4 --- /dev/null +++ b/.github/workflows/android-preview.yml @@ -0,0 +1,180 @@ +name: Android Preview + +on: pull_request + +jobs: + android-distribute-to-appetize: + runs-on: ubuntu-latest + name: "Build and upload app to Appetize ๐Ÿš€" + steps: + + - name: Cancel previous jobs + uses: styfle/cancel-workflow-action@0.11.0 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v3 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.6" + bundler-cache: true + + - uses: actions/setup-ruby@v1 + with: + ruby-version: '2.6' + + - name: Install npm + run: | + npm config set legacy-peer-deps true install + + - run: npm install --save slack-message-builder + + - name: Install packages + run: | + yarn + + - name: Distribute the React Native Android app on Appetize and upload to BrowserStack ๐Ÿš€ + run: bundle exec fastlane android preview + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + SOURCE_BRANCH: ${{ github.head_ref }} + APPETIZE_API_TOKEN: ${{ secrets.APPETIZE_API_TOKEN }} + BROWSERSTACK_USERNAME: ${{secrets.BROWSERSTACK_USERNAME}} + BROWSERSTACK_ACCESS_KEY: ${{secrets.BROWSERSTACK_ACCESS_KEY}} + + - name: Save Browserstack ID + uses: actions/upload-artifact@v3 + id: save_browserstack_id_step + with: + name: browserstack_id + path: /var/tmp/browserstack_id.txt + if-no-files-found: error + + - uses: peter-evans/find-comment@v2 + if: ${{ success() }} + id: find_comment + with: + issue-number: ${{ github.event.pull_request.number }} + body-includes: Appetize link + + - uses: peter-evans/create-or-update-comment@v2 + if: ${{ success() }} + with: + body: | + Appetize link: ${{ env.APPETIZE_APP_URL }} + edit-mode: replace + comment-id: ${{ steps.find_comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Slack Success Summary Report + if: ${{ success() && github.event.pull_request.base.ref == 'master' }} + run: | + node report-scripts/appetize-success-report-script.js createAppetizeSummaryReport ${{ github.head_ref || github.ref_name }} 'RN Android' + - name: Slack Success Notification + if: ${{ success() && github.event.pull_request.base.ref == 'master' }} + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/appetize-success-link-summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create Slack Failure Summary Report + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + run: | + node report-scripts/appetize-failure-report-script.js createAppetizeSummaryReport ${{ github.head_ref || github.ref_name }} 'RN Android' + - name: Slack Notification + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/appetize-failure-link-summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + android-test-via-browserstack: + runs-on: ubuntu-latest + name: "Browserstack test" + needs: android-distribute-to-appetize + steps: + - name: Clone and launch Browserstack tests via Appium ๐Ÿงช + run: | + git clone -b develop https://project_41483872_bot:$GITLAB_TEMP_PATH@gitlab.com/primer-io/dx/mobile-appium-tests.git . + env: + GITLAB_TEMP_PATH: ${{ secrets.GITLAB_APPIUM_PULL_KEY }} + + - name: Retrieve Browserstack ID + uses: actions/download-artifact@v3 + with: + name: browserstack_id + path: /var/tmp + + - uses: actions/checkout@v3 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.6" + bundler-cache: true + + - uses: actions/setup-ruby@v1 + with: + ruby-version: '2.6' + + - name: Install npm + run: | + npm config set legacy-peer-deps true install + + - run: npm install --save slack-message-builder + + - name: Install packages + run: | + yarn + + - name: Run Appium Test + env: + BROWSERSTACK_USERNAME: ${{secrets.BROWSERSTACK_USERNAME}} + BROWSERSTACK_ACCESS_KEY: ${{secrets.BROWSERSTACK_ACCESS_KEY}} + run: | + export BROWSERSTACK_APP_ID=$(cat /var/tmp/browserstack_id.txt) + npx wdio config/wdio.rn.android.bs.conf.js + + - name: Create Slack Report + if: ${{ (success() || failure()) && github.event.pull_request.base.ref == 'master' }} + run: | + node report-script/slack-report-script.js createSlackReport 'RN Android' + + - name: Post summary message to a Slack channel + if: ${{ (success() || failure()) && github.event.pull_request.base.ref == 'master' }} + id: slack + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/slack-minimal_summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create Slack Failed Summary Report + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + run: | + node report-script/slack-failed-report-script.js createSlackFailedSummaryReport ${{ steps.slack.outputs.thread_ts }} + env: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + - name: Post detailed summary to Slack channel thread + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + id: slack_thread + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/slack_failed_summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create and post Github summary + if: ${{ success() || failure() }} + run: | + node report-script/github-tests-summary-script.js createGithubSummaryReport + diff --git a/.github/workflows/ios-appetize.yml b/.github/workflows/ios-appetize.yml index 072e9f1d3..bc3f5e788 100644 --- a/.github/workflows/ios-appetize.yml +++ b/.github/workflows/ios-appetize.yml @@ -51,6 +51,8 @@ jobs: with: cache: 'yarn' + - run: npm install --save slack-message-builder + - name: Cache pods uses: actions/cache@v3 with: @@ -89,6 +91,50 @@ jobs: APPETIZE_API_TOKEN: ${{ secrets.APPETIZE_API_TOKEN }} SOURCE_BRANCH: ${{ github.head_ref }} PR_NUMBER: ${{ github.event.pull_request.number }} + + - uses: peter-evans/find-comment@v2 + if: ${{ success() }} + id: find_comment + with: + issue-number: ${{ github.event.pull_request.number }} + body-includes: Appetize link + + - uses: peter-evans/create-or-update-comment@v2 + if: ${{ success() }} + with: + body: | + Appetize link: ${{ env.APPETIZE_APP_URL }} + edit-mode: replace + comment-id: ${{ steps.find_comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Slack Success Summary Report + if: ${{ success() && github.event.pull_request.base.ref == 'master' }} + run: | + node Report\ Scripts/appetize-success-report-script.js createAppetizeSummaryReport ${{ github.head_ref || github.ref_name }} 'RN iOS' + - name: Slack Success Notification + if: ${{ success() && github.event.pull_request.base.ref == 'master' }} + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/appetize-success-link-summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create Slack Failure Summary Report + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + run: | + node Report\ Scripts/appetize-failure-report-script.js createAppetizeSummaryReport ${{ github.head_ref || github.ref_name }} 'RN iOS' + - name: Slack Notification + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/appetize-failure-link-summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + - name: Save Simulator app uses: actions/upload-artifact@v3 id: save_simulator_app_id_step @@ -96,3 +142,4 @@ jobs: name: PrimerSDK_Debug_Build path: /var/tmp/PrimerSDK_Debug_Build.zip if-no-files-found: error + diff --git a/.github/workflows/ios-browserstack.yml b/.github/workflows/ios-browserstack.yml index 3b3da38c3..e7809db08 100644 --- a/.github/workflows/ios-browserstack.yml +++ b/.github/workflows/ios-browserstack.yml @@ -1,5 +1,5 @@ --- -name: iOS BS +name: iOS BrowserStack on: pull_request jobs: @@ -56,6 +56,8 @@ jobs: with: cache: 'yarn' + - run: npm install --save slack-message-builder + - name: Cache pods uses: actions/cache@v3 with: @@ -138,3 +140,40 @@ jobs: run: | export BROWSERSTACK_APP_ID=$(cat /var/tmp/browserstack_id.txt) npx wdio config/wdio.rn.ios.bs.conf.js + + - name: Create Slack Report + if: ${{ (success() || failure()) && github.event.pull_request.base.ref == 'master' }} + run: | + node report-script/slack-report-script.js createSlackReport 'RN iOS' + - name: Post summary message to a Slack channel + if: ${{ (success() || failure()) && github.event.pull_request.base.ref == 'master' }} + id: slack + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/slack-minimal_summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create Slack Failed Summary Report + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + run: | + node report-script/slack-failed-report-script.js createSlackFailedSummaryReport ${{ steps.slack.outputs.thread_ts }} + env: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + - name: Post detailed summary to Slack channel thread + if: ${{ failure() && github.event.pull_request.base.ref == 'master' }} + id: slack_thread + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ secrets.SLACK_MOBILE_SDK_CHANNEL }} + payload-file-path: '/var/tmp/slack_failed_summary.json' + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_REPORTER_BOT_TOKEN }} + + - name: Create and post Github summary + if: ${{ success() || failure() }} + run: | + node report-script/github-tests-summary-script.js createGithubSummaryReport diff --git a/fastlane/AndroidFastFile b/fastlane/AndroidFastFile index 79131868b..c77f4ddc4 100644 --- a/fastlane/AndroidFastFile +++ b/fastlane/AndroidFastFile @@ -4,7 +4,6 @@ default_platform(:android) platform :android do - def set_version_name (version_name) path = '../example_0_70_6/android/app/build.gradle' re = /versionName\s+\"(\S+)\"/ @@ -60,6 +59,13 @@ platform :android do gradle(task: "clean assembleRelease", project_dir: 'example_0_70_6/android/') + upload_to_browserstack_app_automate( + browserstack_username: ENV["BROWSERSTACK_USERNAME"], + browserstack_access_key: ENV["BROWSERSTACK_ACCESS_KEY"] + ) + + save_browserstack_id(browserstack_id: ENV['BROWSERSTACK_APP_ID']) + sdk_version_name_source_branch = ENV['SOURCE_BRANCH'] pr_number = ENV['PR_NUMBER'] @@ -74,6 +80,23 @@ platform :android do public_key: public_key, note: version_name ) + update_deployment_url(lane_context[SharedValues::APPETIZE_APP_URL]) + end + + + desc 'Store the Browserstack ID into a file' + private_lane :save_browserstack_id do |options| + + browserstack_id_to_save = options[:browserstack_id] + browserstack_id_file = "/var/tmp/browserstack_id.txt" + + UI.message("Saving #{browserstack_id_to_save} into #{browserstack_id_file}") + + File.open(browserstack_id_file, 'w') { |file| file.write(options[:browserstack_id]) } + end + def update_deployment_url(pub_url) + sh("echo APPETIZE_APP_URL=#{pub_url} >> $GITHUB_ENV") + end end diff --git a/fastlane/IOSFastFile b/fastlane/IOSFastFile index cd3bcafa2..c82059cc5 100644 --- a/fastlane/IOSFastFile +++ b/fastlane/IOSFastFile @@ -121,6 +121,7 @@ platform :ios do ) save_simulator_app(app_path: zip_path) + update_deployment_url(lane_context[SharedValues::APPETIZE_APP_URL]) end @@ -221,6 +222,9 @@ platform :ios do ################## END PRIVATE LANES ###################### + def update_deployment_url(pub_url) + sh("echo APPETIZE_APP_URL=#{pub_url} >> $GITHUB_ENV") + end end #--------------------- END FASTLANE ------------------------# diff --git a/report-scripts/appetize-failure-report-script.js b/report-scripts/appetize-failure-report-script.js new file mode 100644 index 000000000..c03e9c490 --- /dev/null +++ b/report-scripts/appetize-failure-report-script.js @@ -0,0 +1,47 @@ +const fs = require('fs'); +const smb = require('slack-message-builder') + +const FAILED_SUMMARY_FILE_PATH = '/var/tmp/appetize-failure-link-summary.json' + +createAppetizeSummaryReport(process.argv[3],process.argv[4]) + +async function createAppetizeSummaryReport(branch, platform) { + fs.writeFileSync(FAILED_SUMMARY_FILE_PATH, JSON.stringify(createAppetizeSummary(branch, platform))); +} + +function createAppetizeSummary(branch, platform) { + return smb() + .attachment() + .mrkdwnIn(["title"]) + .color("#ff0000") + .title(`Failed to generate Appetize link for branch ${branch}.`) + .authorName(process.env.GITHUB_ACTOR) + .authorLink(`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_ACTOR}`) + .authorIcon(`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_ACTOR}.png?size=32`) + .field() + .title("Ref") + .value(process.env.GITHUB_REF) + .short(true) + .end() + .field() + .title("Actions URL") + .value( + `<${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}|${process.env.GITHUB_WORKFLOW}>` + ) + .short(true) + .end() + .field() + .title("Commit") + .value( + `<${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}|${process.env.GITHUB_SHA.slice(0,6)}>` + ) + .short(true) + .end() + .field() + .title("Platform") + .value(platform) + .short(true) + .end() + .end() + .json() +} diff --git a/report-scripts/appetize-success-report-script.js b/report-scripts/appetize-success-report-script.js new file mode 100644 index 000000000..8264ef34c --- /dev/null +++ b/report-scripts/appetize-success-report-script.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const smb = require('slack-message-builder') + +const SUCCESS_SUMMARY_FILE_PATH = '/var/tmp/appetize-success-link-summary.json' + +createAppetizeSummaryReport(process.argv[3], process.argv[4]) + +async function createAppetizeSummaryReport(branch, platform) { + fs.writeFileSync(SUCCESS_SUMMARY_FILE_PATH, JSON.stringify(createAppetizeSummary(branch, platform))); +} + +function createAppetizeSummary(branch, platform) { + return smb() + .attachment() + .mrkdwnIn(["title"]) + .color("#36a64f") + .title(`Successfully generated Appetize link for branch ${branch}.`) + .authorName(process.env.GITHUB_ACTOR) + .authorLink(`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_ACTOR}`) + .authorIcon(`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_ACTOR}.png?size=32`) + .field() + .title("Appetize URL") + .value(`<${process.env.APPETIZE_APP_URL}|${process.env.APPETIZE_APP_URL.slice(-6)}>`) + .short(true) + .end() + .field() + .title("Ref") + .value(process.env.GITHUB_REF) + .short(true) + .end() + .field() + .title("Actions URL") + .value( + `<${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}|${process.env.GITHUB_WORKFLOW}>` + ) + .short(true) + .end() + .field() + .title("Commit") + .value( + `<${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}|${process.env.GITHUB_SHA.slice(0,6)}>` + ) + .short(true) + .end() + .field() + .title("Platform") + .value(platform) + .short(true) + .end() + .end() + .json() +}