From b0d896c3e34ec9b175a5166e11554997a44cab22 Mon Sep 17 00:00:00 2001 From: Christopher Allford <6451942+ObliviousHarmony@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:23:08 -0800 Subject: [PATCH] Refactored Monorepo Setup Action This makes some adjustments for consistency in style as well as making improvements to usability and performance. It also updates all of the pinned hashes to pull in any fixes that have been made. --- .../setup-woocommerce-monorepo/action.yml | 128 ++++++------ .../scripts/parse-input-filter.js | 27 +-- .github/workflows/ci.yml | 187 +++++++++--------- .../extend-cart-checkout-block/project.json | 5 - packages/js/internal-js-tests/project.json | 19 -- packages/js/notices/project.json | 25 --- 6 files changed, 167 insertions(+), 224 deletions(-) delete mode 100644 packages/js/extend-cart-checkout-block/project.json delete mode 100644 packages/js/internal-js-tests/project.json delete mode 100644 packages/js/notices/project.json diff --git a/.github/actions/setup-woocommerce-monorepo/action.yml b/.github/actions/setup-woocommerce-monorepo/action.yml index 7c69a9f4f47..afdc8d9a713 100644 --- a/.github/actions/setup-woocommerce-monorepo/action.yml +++ b/.github/actions/setup-woocommerce-monorepo/action.yml @@ -1,72 +1,60 @@ -name: Setup WooCommerce Monorepo -description: Handles the installation, building, and caching of the projects within the monorepo. -permissions: {} - +name: 'Setup WooCommerce Monorepo' +description: 'A composite action bundling together the setup of dependencies and optional installation and building of projects.' inputs: - install: - description: Indicates whether or not the action should install any projects. - default: 'true' - install-filters: - description: The PNPM filter used to decide what projects to install. Supports multiline strings for multiple filters. - default: '' - build: - description: Indicates whether or not the action should build any projects. - default: 'true' - build-filters: - description: The PNPM filter used to decide what projects to build. Supports multiline strings for multiple filters. - default: '' - php-version: - description: The version of PHP that the action should set up. - default: '7.4' - + php-version: + description: 'The PHP version that should be installed. Use "false" to skip PHP installation.' + default: '7.4' + install: + description: 'Given a boolean or PNPM filter, runs the install command for monorepo project(s).' + default: false + build: + description: 'Given a boolean or PNPM filter, runs the build command for monorepo project(s).' + default: false +defaults: + run: + shell: 'bash' runs: - using: composite - steps: - - name: Parse Action Input - id: parse-input - shell: bash - run: | - echo "INSTALL_FILTERS=$(node ./.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js '${{ inputs.install-filters }}')" >> $GITHUB_OUTPUT - echo "BUILD_FILTERS=$(node ./.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js '${{ inputs.build-filters }}')" >> $GITHUB_OUTPUT - - - name: Setup PNPM - uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd - with: - version: '8.6.7' - - - name: Setup Node - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c - with: - node-version-file: .nvmrc - cache: pnpm - registry-url: 'https://registry.npmjs.org' - - - name: Setup PHP - uses: shivammathur/setup-php@8e2ac35f639d3e794c1da1f28999385ab6fdf0fc - with: - php-version: ${{ inputs.php-version }} - coverage: none - tools: phpcs, sirbrillig/phpcs-changed:2.11.1 - - - name: Cache Composer Dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 - with: - path: ~/.cache/composer/files - key: ${{ runner.os }}-php-${{ inputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-php-${{ inputs.php-version }}-composer- - - - name: Install Node and PHP Dependencies - shell: bash - if: ${{ inputs.install == 'true' }} - env: - PUPPETEER_SKIP_DOWNLOAD: 'true' - run: pnpm install ${{ steps.parse-input.outputs.INSTALL_FILTERS }} - - - name: Cache Build Output - if: ${{ inputs.install == 'true' && inputs.build == 'true' }} - uses: google/wireit@setup-github-actions-caching/v1 - - - name: Build - if: ${{ inputs.install == 'true' && inputs.build == 'true' }} - shell: bash - run: pnpm ${{ steps.parse-input.outputs.BUILD_FILTERS }} build + using: 'composite' + steps: + - name: 'Setup PNPM' + uses: 'pnpm/action-setup@d882d12c64e032187b2edb46d3a0d003b7a43598' + with: + version: '8' + - name: 'Setup Node' + uses: 'actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65' + with: + node-version-file: '.nvmrc' + cache: 'pnpm' + - name: 'Setup PHP' + if: ${{ inputs.php-version !== 'false' }} + uses: 'shivammathur/setup-php@a36e1e52ff4a1c9e9c9be31551ee4712a6cb6bd0' + with: + php-version: '${{ inputs.php-version }}' + coverage: 'none' + tools: 'phpcs, sirbrillig/phpcs-changed:2.11.1' + - name: 'Cache Composer Dependencies' + if: ${{ inputs.php-version !== 'false' }} + uses: 'actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84' + with: + path: '~/.cache/composer/files' + key: '${{ runner.os }}-composer-${{ hashFiles( "**/composer.lock" ) }}' + restore-keys: '${{ runner.os }}-composer-' + - name: 'Parse Project Filters' + id: 'project-filters' + run: | + echo "install=$(node ./.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js '${{ inputs.install }}')" >> $GITHUB_OUTPUT + echo "build=$(node ./.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js '${{ inputs.build }}')" >> $GITHUB_OUTPUT + - name: 'Install Project Dependencies' + # Boolean inputs aren't parsed into filters so it'll either be "true" or there will be a filter. + if: ${{ inputs.install == 'true' || steps.project-filters.outputs.install != '' }} + run: 'pnpm install ${{ steps.project-filters.outputs.install }}' + # We want to include an option to build projects using this action so that we can make + # sure that the build cache is always used when building projects. + - name: 'Cache Build Output' + # Boolean inputs aren't parsed into filters so it'll either be "true" or there will be a filter. + if: ${{ inputs.build == 'true' || steps.project-filters.outputs.build != '' }} + uses: 'google/wireit@f3a3c79c553122e2fe5829eeac7d815326502903' + - name: 'Build' + # Boolean inputs aren't parsed into filters so it'll either be "true" or there will be a filter. + if: ${{ inputs.build == 'true' || steps.project-filters.outputs.build != '' }} + run: 'pnpm ${{ steps.project-filters.outputs.build }} build' diff --git a/.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js b/.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js index 70d7bf583a6..dd63def2010 100644 --- a/.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js +++ b/.github/actions/setup-woocommerce-monorepo/scripts/parse-input-filter.js @@ -1,22 +1,27 @@ -const args = process.argv.slice(2); -if (args.length != 1) { - console.error('Filters must be passed as a single string!'); - process.exit(-1); +const args = process.argv.slice( 2 ); +if ( args.length != 1 ) { + console.error( 'Filters must be passed as a single string!' ); + process.exit( -1 ); +} + +// Boolean inputs should not be processed. +if ( args[0] === 'true' || args[0] === 'false' ) { + process.exit(); } // Read all of the given filters and return the full filter options string. -const filterLines = args[0].split("\n"); +const filterLines = args[0].split( "\n" ); let output = ''; -for (const line of filterLines) { - if (line === '') { +for ( const line of filterLines ) { + if ( line === '' ) { continue; } - if (output !== '') { + if ( output !== '' ) { output += ' '; } - output += "--filter='" + line + "'"; + output += `--filter='${ line }'`; } -console.log(output); -process.exit(0); +console.log( output ); +process.exit(); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76c3373bc1a..d8cce1e963f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,97 +9,96 @@ concurrency: group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true jobs: - project-matrix: - # Since this is a monorepo, not every pull request or change is going to impact every project. - # Instead of running CI tasks on all projects indiscriminately, we use a script to detect - # which projects have changed and what kind of change occurred. This lets us build a - # matrix that we can use to run CI tasks only on the projects that need them. - name: 'Build Project Matrix' - runs-on: 'ubuntu-20.04' - outputs: - matrix: ${{ steps.project-matrix.outputs.matrix }} - steps: - - uses: 'actions/checkout@v3' - name: 'Checkout' - with: - fetch-depth: 0 - - uses: './.github/actions/setup-woocommerce-monorepo' - name: 'Setup Monorepo' - with: - build: false - - uses: actions/github-script@v6 - id: 'project-matrix' - name: 'Build Matrix' - with: - script: | - let baseRef = ${{ toJson( github.base_ref ) }}; - if ( baseRef ) { - baseRef = 'origin/' + baseRef; - } - const buildCIMatrix = require( './.github/workflows/scripts/build-ci-matrix' ); - core.setOutput( 'matrix', JSON.stringify( await buildCIMatrix( baseRef ) ) ); - project-task-matrix: - # This is the actual CI job that will be ran against every project with applicable changes. - # Note that we only run the tasks that have commands set. Our script will set them if - # they are needed and so all the workflow needs to do is run them. - name: '${{ matrix.projectName }} - ${{ matrix.taskName }}' # Note: GitHub doesn't process expressions for skipped jobs so when there's no matrix the name will literally be this. - runs-on: 'ubuntu-20.04' - needs: 'project-matrix' - if: ${{ needs.project-matrix.outputs.matrix != '[]' }} - timeout-minutes: 30 - strategy: - fail-fast: false - matrix: - include: ${{ fromJSON( needs.project-matrix.outputs.matrix ) }} - steps: - - uses: 'actions/checkout@v3' - name: 'Checkout' - with: - fetch-depth: 0 - - uses: './.github/actions/setup-woocommerce-monorepo' - id: 'setup-monorepo' - name: 'Setup Monorepo' - with: - # install-filters: '${{ matrix.projectName }}...' - build-filters: '${{ matrix.projectName }}' - - name: 'Lint' - if: ${{ !cancelled() && matrix.lintCommand && steps.setup-monorepo.conclusion == 'success' }} - run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.lintCommand }}' - - name: 'Prepare Test Environment' - id: 'prepare-test-environment' - if: ${{ !cancelled() && matrix.testEnvCommand && steps.setup-monorepo.conclusion == 'success' }} - env: ${{ matrix.testEnvVars }} - run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnvCommand }}' - - name: 'Test - JS' - if: ${{ !cancelled() && matrix.jsTestCommand && steps.setup-monorepo.conclusion == 'success' && ( ! matrix.testEnvCommand || steps.prepare-test-environment.conclusion == 'success' ) }} - run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.jsTestCommand }}' - - name: 'Test - PHP' - if: ${{ !cancelled() && matrix.phpTestCommand && steps.setup-monorepo.conclusion == 'success' && ( ! matrix.testEnvCommand || steps.prepare-test-environment.conclusion == 'success' ) }} - run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.phpTestCommand }}' - project-task-matrix-evaluation: - # In order to add a required status check we need a consistent job that we can grab onto. - # Since we are dynamically generating a project matrix, however, we can't rely on - # on any specific job being present. We can get around this limitation by using - # a job that runs after all the others and either passes or fails based on the - # results of the other jobs in the workflow. - name: 'Evaluate Project Matrix' - runs-on: 'ubuntu-20.04' - needs: [ - 'project-matrix', - 'project-task-matrix' - ] - if: ${{ always() }} - steps: - - name: 'Check Matrix Success' - run: | - result="${{ needs.project-matrix.result }}" - if [[ $result != "success" && $result != "skipped" ]]; then - echo "An error occurred generating the CI matrix." - exit 1 - fi - result="${{ needs.project-task-matrix.result }}" - if [[ $result != "success" && $result != "skipped" ]]; then - echo "One or more jobs in the matrix has failed." - exit 1 - fi - echo "The matrix has completed successfully." + project-matrix: + # Since this is a monorepo, not every pull request or change is going to impact every project. + # Instead of running CI tasks on all projects indiscriminately, we use a script to detect + # which projects have changed and what kind of change occurred. This lets us build a + # matrix that we can use to run CI tasks only on the projects that need them. + name: 'Build Project Matrix' + runs-on: 'ubuntu-20.04' + outputs: + matrix: ${{ steps.project-matrix.outputs.matrix }} + steps: + - uses: 'actions/checkout@v3' + name: 'Checkout' + with: + fetch-depth: 0 + - uses: './.github/actions/setup-woocommerce-monorepo' + with: + php-version: false # We don't want to waste time installing PHP since we aren't using it in this job. + name: 'Setup Monorepo' + - uses: actions/github-script@v6 + id: 'project-matrix' + name: 'Build Matrix' + with: + script: | + let baseRef = ${{ toJson( github.base_ref ) }}; + if ( baseRef ) { + baseRef = 'origin/' + baseRef; + } + const buildCIMatrix = require( './.github/workflows/scripts/build-ci-matrix' ); + core.setOutput( 'matrix', JSON.stringify( await buildCIMatrix( baseRef ) ) ); + project-task-matrix: + # This is the actual CI job that will be ran against every project with applicable changes. + # Note that we only run the tasks that have commands set. Our script will set them if + # they are needed and so all the workflow needs to do is run them. + name: '${{ matrix.projectName }} - ${{ matrix.taskName }}' # Note: GitHub doesn't process expressions for skipped jobs so when there's no matrix the name will literally be this. + runs-on: 'ubuntu-20.04' + needs: 'project-matrix' + if: ${{ needs.project-matrix.outputs.matrix != '[]' }} + strategy: + fail-fast: false + matrix: + include: ${{ fromJSON( needs.project-matrix.outputs.matrix ) }} + steps: + - uses: 'actions/checkout@v3' + name: 'Checkout' + with: + fetch-depth: 0 + - uses: './.github/actions/setup-woocommerce-monorepo' + id: 'setup-monorepo' + name: 'Setup Monorepo' + with: + install: '${{ matrix.projectName }}...' + build: '${{ matrix.projectName }}' + - name: 'Lint' + if: ${{ !cancelled() && matrix.lintCommand && steps.setup-monorepo.conclusion == 'success' }} + run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.lintCommand }}' + - name: 'Prepare Test Environment' + id: 'prepare-test-environment' + if: ${{ !cancelled() && matrix.testEnvCommand && steps.setup-monorepo.conclusion == 'success' }} + env: ${{ matrix.testEnvVars }} + run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnvCommand }}' + - name: 'Test - JS' + if: ${{ !cancelled() && matrix.jsTestCommand && steps.setup-monorepo.conclusion == 'success' && ( ! matrix.testEnvCommand || steps.prepare-test-environment.conclusion == 'success' ) }} + run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.jsTestCommand }}' + - name: 'Test - PHP' + if: ${{ !cancelled() && matrix.phpTestCommand && steps.setup-monorepo.conclusion == 'success' && ( ! matrix.testEnvCommand || steps.prepare-test-environment.conclusion == 'success' ) }} + run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.phpTestCommand }}' + project-task-matrix-evaluation: + # In order to add a required status check we need a consistent job that we can grab onto. + # Since we are dynamically generating a project matrix, however, we can't rely on + # on any specific job being present. We can get around this limitation by using + # a job that runs after all the others and either passes or fails based on the + # results of the other jobs in the workflow. + name: 'Evaluate Project Matrix' + runs-on: 'ubuntu-20.04' + needs: [ + 'project-matrix', + 'project-task-matrix' + ] + if: ${{ always() }} + steps: + - name: 'Check Matrix Success' + run: | + result="${{ needs.project-matrix.result }}" + if [[ $result != "success" && $result != "skipped" ]]; then + echo "An error occurred generating the CI matrix." + exit 1 + fi + result="${{ needs.project-task-matrix.result }}" + if [[ $result != "success" && $result != "skipped" ]]; then + echo "One or more jobs in the matrix has failed." + exit 1 + fi + echo "The matrix has completed successfully." diff --git a/packages/js/extend-cart-checkout-block/project.json b/packages/js/extend-cart-checkout-block/project.json deleted file mode 100644 index f0a497781bf..00000000000 --- a/packages/js/extend-cart-checkout-block/project.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "root": "packages/js/extend-cart-checkout-block", - "sourceRoot": "packages/js/extend-cart-checkout-block", - "projectType": "library" -} diff --git a/packages/js/internal-js-tests/project.json b/packages/js/internal-js-tests/project.json deleted file mode 100644 index faccb2f296c..00000000000 --- a/packages/js/internal-js-tests/project.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "root": "packages/js/internal-js-tests", - "sourceRoot": "packages/js/internal-js-tests/src", - "projectType": "library", - "targets": { - "build": { - "executor": "@nrwl/workspace:run-script", - "options": { - "script": "build" - } - }, - "test": { - "executor": "@nrwl/workspace:run-script", - "options": { - "script": "test" - } - } - } - } \ No newline at end of file diff --git a/packages/js/notices/project.json b/packages/js/notices/project.json deleted file mode 100644 index 33f1da11cee..00000000000 --- a/packages/js/notices/project.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "root": "packages/js/notices", - "sourceRoot": "packages/js/notices/src", - "projectType": "library", - "targets": { - "build": { - "executor": "@nrwl/workspace:run-script", - "options": { - "script": "build" - } - }, - "build-watch": { - "executor": "@nrwl/workspace:run-script", - "options": { - "script": "start" - } - }, - "test": { - "executor": "@nrwl/workspace:run-script", - "options": { - "script": "test" - } - } - } - } \ No newline at end of file