From 6962afc8fd7c6b446b5a5f287e642ca0146d19ca Mon Sep 17 00:00:00 2001 From: Adel Bensaad Date: Mon, 3 Jun 2024 11:53:04 +0100 Subject: [PATCH] chore: [DHIS2-17375] optimise Cypress triggers and refine parallel execution in GitHub Actions (#1507) * chore: optimize Cypress triggers and refine parallel execution in GitHub Actions * chore: debug ci --- .github/workflows/dhis2-verify-lib.yml | 61 +++++++++++++++++++++----- README.md | 9 ++++ cypress/support/generateTestMatrix.js | 35 +++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 cypress/support/generateTestMatrix.js diff --git a/.github/workflows/dhis2-verify-lib.yml b/.github/workflows/dhis2-verify-lib.yml index 58143965d6..88bcada1ad 100644 --- a/.github/workflows/dhis2-verify-lib.yml +++ b/.github/workflows/dhis2-verify-lib.yml @@ -1,20 +1,35 @@ name: 'dhis2: verify (lib)' -on: push +on: + push: + pull_request: + types: [labeled] concurrency: - group: ${{ github.workflow}}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} env: GIT_AUTHOR_NAME: '@dhis2-bot' GIT_AUTHOR_EMAIL: 'apps@dhis2.org' GIT_COMMITTER_NAME: '@dhis2-bot' GIT_COMMITTER_EMAIL: 'apps@dhis2.org' - NPM_TOKEN: ${{secrets.DHIS2_BOT_NPM_TOKEN}} - GH_TOKEN: ${{secrets.DHIS2_BOT_GITHUB_TOKEN}} + NPM_TOKEN: ${{ secrets.DHIS2_BOT_NPM_TOKEN }} + GH_TOKEN: ${{ secrets.DHIS2_BOT_GITHUB_TOKEN }} D2_VERBOSE: true jobs: + setup-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.specs }} + steps: + - uses: actions/checkout@v3 + - name: Generate test matrix + id: set-matrix + run: | + node cypress/support/generateTestMatrix.js > matrix.json + echo "::set-output name=specs::$(cat matrix.json)" + build: runs-on: ubuntu-latest steps: @@ -84,12 +99,14 @@ jobs: e2e: runs-on: ubuntu-latest if: "!github.event.push.repository.fork && github.actor != 'dependabot[bot]'" - needs: [build] + needs: [build, setup-matrix] strategy: fail-fast: false matrix: - containers: [1, 2, 3, 4] + spec-group: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + env: + SHOULD_RECORD: ${{ contains(github.event.head_commit.message, '[e2e record]') || contains(join(github.event.pull_request.labels.*.name), 'e2e record') }} steps: - name: Checkout @@ -108,17 +125,37 @@ jobs: - name: Increase FS watchers run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + - name: Set Cypress Record Environment Variables + if: env.SHOULD_RECORD == 'true' + run: | + echo "CYPRESS_GROUP=e2e-${{ matrix.spec-group.id }}" >> $GITHUB_ENV + echo "CYPRESS_TAG=${{ github.event_name }}" >> $GITHUB_ENV + echo "CYPRESS_CI_BUILD_ID=${{ github.run_id }}" >> $GITHUB_ENV + + - name: Debug Environment Variables + run: | + echo "SHOULD_RECORD=${{ env.SHOULD_RECORD }}" + echo "CI Build ID=${{ github.run_id }}" + echo "Group ID=e2e-${{ matrix.spec-group.id }}" + echo "Spec=${{ join(matrix.spec-group.tests, ',') }}" + echo "Record=${{ env.SHOULD_RECORD }}" + echo "Parallel=${{ env.SHOULD_RECORD }}" + echo "Computed Group=${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_GROUP || '' }}" + echo "Computed Tag=${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_TAG || '' }}" + echo "Computed CI Build ID=${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_CI_BUILD_ID || '' }}" + - name: End-to-End tests uses: cypress-io/github-action@v6 with: - # This should be a command that starts the server to test against. start: 'yarn cy:start:legacy' wait-on: 'http://localhost:5000' wait-on-timeout: 300 - record: true - parallel: true - group: 'e2e' - tag: ${{ github.event_name }} + record: ${{ env.SHOULD_RECORD }} + parallel: ${{ env.SHOULD_RECORD }} + group: ${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_GROUP || '' }} + tag: ${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_TAG || '' }} + ci-build-id: ${{ env.SHOULD_RECORD == 'true' && env.CYPRESS_CI_BUILD_ID || '' }} + spec: ${{ join(matrix.spec-group.tests, ',') }} env: BROWSER: none COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }} @@ -133,7 +170,7 @@ jobs: steps: - uses: actions/checkout@v2 with: - token: ${{env.GH_TOKEN}} + token: ${{ env.GH_TOKEN }} - uses: actions/setup-node@v3 with: node-version: 20.x diff --git a/README.md b/README.md index 0fce5f1c93..d118cb32de 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,15 @@ yarn start yarn start --no-manager-cache ``` +## Conditional E2E Test Recording + +To record e2e tests in Cypress Cloud, you can use one of the following methods based on your needs: + +- **Commit Message**: Include `[e2e record]` in your commit messages to activate recording. +- **GitHub Labels**: Apply the `e2e record` label to your pull request to trigger recording. + +This setup helps in managing Cypress Cloud credits more efficiently, ensuring recordings are only made when explicitly required. + ## Reporting an issue or opening a PR See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/cypress/support/generateTestMatrix.js b/cypress/support/generateTestMatrix.js new file mode 100644 index 0000000000..e1cfecb9dc --- /dev/null +++ b/cypress/support/generateTestMatrix.js @@ -0,0 +1,35 @@ +const fs = require('fs') +const path = require('path') + +const getAllFiles = (dirPath, arrayOfFiles = []) => { + const files = fs.readdirSync(dirPath) + + files.forEach((file) => { + if (fs.statSync(path.join(dirPath, file)).isDirectory()) { + arrayOfFiles = getAllFiles(path.join(dirPath, file), arrayOfFiles) + } else if (path.extname(file) === '.feature') { + arrayOfFiles.push(path.join(dirPath, file)) + } + }) + + return arrayOfFiles +} + +const createGroups = (files, numberOfGroups = 7) => { + const groups = [] + for (let i = 0; i < numberOfGroups; i++) { + groups.push([]) + } + + files.forEach((file, index) => { + groups[index % numberOfGroups].push(file) + }) + + return groups.map((group, index) => ({ id: index + 1, tests: group })) +} + +const cypressSpecsPath = '../' +const specs = getAllFiles(cypressSpecsPath) +const groupedSpecs = createGroups(specs) + +console.log(JSON.stringify(groupedSpecs))