Monorepo: caching deps per target package in GH actions (#49020)
In this PR, we are implementing per-package build and caching, which optimizes build and fetching cached dependencies times across our workflows.
This commit is contained in:
parent
f1399c9d77
commit
4311640de2
|
@ -16,6 +16,9 @@ inputs:
|
|||
pull-playwright-cache:
|
||||
description: 'Given a boolean value, invokes Playwright dependencies caching.'
|
||||
default: false
|
||||
pull-package-deps:
|
||||
description: 'Given a string value, will pull the package specific dependencies cache.'
|
||||
default: false
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
|
@ -31,27 +34,39 @@ runs:
|
|||
uses: 'actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# We only want to use the cache if something is being installed.
|
||||
cache: ${{ inputs.install != 'false' && 'pnpm' || '' }}
|
||||
# The built-in caching is not fit to per-package caching we are aiming.
|
||||
cache: ''
|
||||
- name: 'Setup PHP'
|
||||
if: ${{ inputs.php-version != 'false' }}
|
||||
uses: 'shivammathur/setup-php@a36e1e52ff4a1c9e9c9be31551ee4712a6cb6bd0'
|
||||
with:
|
||||
php-version: '${{ inputs.php-version }}'
|
||||
coverage: 'none'
|
||||
- name: 'Cache: identify pnpm caching directory'
|
||||
if: ${{ inputs.pull-package-deps != 'false' }}
|
||||
shell: 'bash'
|
||||
run: |
|
||||
echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
- name: 'Cache: pnpm downloads'
|
||||
if: ${{ inputs.pull-package-deps != 'false' }}
|
||||
uses: 'actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319'
|
||||
with:
|
||||
path: "${{ env.PNPM_STORE_PATH }}"
|
||||
key: "${{ runner.os }}-pnpm-${{ inputs.pull-package-deps }}-${{ hashFiles( 'pnpm-lock.yaml' ) }}"
|
||||
restore-keys: '${{ runner.os }}-pnpm-${{ inputs.pull-package-deps }}-'
|
||||
- name: 'Cache Composer Dependencies'
|
||||
if: ${{ inputs.build == 'false' }}
|
||||
if: ${{ inputs.pull-package-deps != 'false' }}
|
||||
uses: 'actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319'
|
||||
with:
|
||||
path: '~/.cache/composer/files'
|
||||
key: "${{ runner.os }}-composer-${{ hashFiles( '**/composer.lock' ) }}"
|
||||
restore-keys: '${{ runner.os }}-composer-'
|
||||
key: "${{ runner.os }}-composer-${{ inputs.pull-package-deps }}-${{ hashFiles( 'packages/*/*/composer.lock', 'plugins/*/composer.lock' ) }}"
|
||||
restore-keys: '${{ runner.os }}-composer-${{ inputs.pull-package-deps }}-'
|
||||
- name: 'Cache: playwright downloads'
|
||||
if: ${{ inputs.pull-playwright-cache != 'false' }}
|
||||
uses: 'actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319'
|
||||
with:
|
||||
path: '~/.cache/ms-playwright/'
|
||||
key: "${{ runner.os }}-playwright-${{ hashFiles( '**/pnpm-lock.yaml' ) }}"
|
||||
key: "${{ runner.os }}-playwright-${{ hashFiles( 'pnpm-lock.yaml' ) }}"
|
||||
restore-keys: '${{ runner.os }}-playwright-'
|
||||
- name: 'Parse Project Filters'
|
||||
id: 'project-filters'
|
||||
|
@ -63,9 +78,8 @@ runs:
|
|||
# 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 != '' }}
|
||||
shell: 'bash'
|
||||
run: 'pnpm install'
|
||||
# `pnpm install` filtering is broken: https://github.com/pnpm/pnpm/issues/6300
|
||||
# run: 'pnpm install ${{ steps.project-filters.outputs.install }}'
|
||||
# The installation command is a bit odd as it's a workaround for know bug - https://github.com/pnpm/pnpm/issues/6300.
|
||||
run: "pnpm install ${{ steps.project-filters.outputs.install }} --frozen-lockfile ${{ steps.project-filters.outputs.install != '' && '--config.dedupe-peer-dependents=false' || '' }}"
|
||||
# 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'
|
||||
|
@ -75,6 +89,8 @@ runs:
|
|||
- 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 != '' }}
|
||||
env:
|
||||
BROWSERSLIST_IGNORE_OLD_DATA: true
|
||||
shell: 'bash'
|
||||
run: |
|
||||
if [[ '${{ inputs.build-type }}' == 'backend' ]]; then
|
||||
|
|
|
@ -30,12 +30,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Cache PNPM Dependencies
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: pnpm
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Prepare plugin zips
|
||||
id: prepare
|
||||
|
|
|
@ -20,6 +20,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Build zip
|
||||
working-directory: plugins/woocommerce
|
||||
|
|
|
@ -153,6 +153,7 @@ jobs:
|
|||
id: 'setup-monorepo'
|
||||
with:
|
||||
install: '${{ matrix.projectName }}...'
|
||||
pull-package-deps: '${{ matrix.projectName }}'
|
||||
|
||||
- name: 'Lint'
|
||||
run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}'
|
||||
|
@ -186,6 +187,7 @@ jobs:
|
|||
build: ${{ ( github.ref_type == 'tag' && 'false' ) || matrix.projectName }}
|
||||
build-type: ${{ ( matrix.testType == 'unit:php' && 'backend' ) || 'full' }}
|
||||
pull-playwright-cache: ${{ matrix.testEnv.shouldCreate && matrix.testType == 'e2e' }}
|
||||
pull-package-deps: '${{ matrix.projectName }}'
|
||||
|
||||
- name: 'Update wp-env config'
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
|
|
|
@ -52,6 +52,7 @@ jobs:
|
|||
install: '@woocommerce/plugin-woocommerce...'
|
||||
build: '@woocommerce/plugin-woocommerce'
|
||||
pull-playwright-cache: true
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Install Playwright dependencies
|
||||
run: pnpm exec playwright install chromium --with-deps
|
||||
|
|
|
@ -18,6 +18,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Build zip
|
||||
working-directory: plugins/woocommerce
|
||||
|
|
|
@ -24,6 +24,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Build zip
|
||||
working-directory: plugins/woocommerce
|
||||
|
|
|
@ -27,6 +27,7 @@ jobs:
|
|||
with:
|
||||
install: true
|
||||
build: './tools/package-release'
|
||||
pull-package-deps: 'tools/package-release'
|
||||
|
||||
- name: Clean working directory
|
||||
run: git checkout pnpm-lock.yaml # in case for whatever reason the lockfile is out of sync, there won't be interference with npm publish.
|
||||
|
|
|
@ -39,12 +39,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Cache PNPM Dependencies
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: pnpm
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Prepare plugin zips
|
||||
id: prepare
|
||||
|
|
|
@ -17,6 +17,8 @@ jobs:
|
|||
with:
|
||||
install: 'code-analyzer...'
|
||||
build: 'code-analyzer'
|
||||
pull-package-deps: 'code-analyzer'
|
||||
|
||||
- name: 'Analyze'
|
||||
id: 'analyze'
|
||||
working-directory: 'tools/code-analyzer'
|
||||
|
|
|
@ -26,6 +26,7 @@ jobs:
|
|||
with:
|
||||
install: true
|
||||
build: './tools/package-release'
|
||||
pull-package-deps: 'tools/package-release'
|
||||
|
||||
- name: Execute script
|
||||
run: ./tools/package-release/bin/dev prepare ${{ github.event.inputs.packages }}
|
||||
|
|
|
@ -191,6 +191,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Build zip
|
||||
working-directory: plugins/woocommerce
|
||||
|
@ -219,6 +221,8 @@ jobs:
|
|||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce'
|
||||
|
||||
- name: Build zip
|
||||
working-directory: plugins/woocommerce
|
||||
|
|
|
@ -22,6 +22,7 @@ jobs:
|
|||
with:
|
||||
install: '@woocommerce/plugin-woocommerce'
|
||||
build: '@woocommerce/plugin-woocommerce'
|
||||
pull-package-deps: '@woocommerce/plugin-woocommerce-beta-tester'
|
||||
|
||||
- name: Lint
|
||||
working-directory: plugins/woocommerce-beta-tester
|
||||
|
|
|
@ -39,10 +39,7 @@ describe( 'Shipping methods API tests', () => {
|
|||
expect( body.method_id ).toEqual( methodId );
|
||||
expect( body.method_title ).toEqual( methodTitle );
|
||||
expect( body.enabled ).toEqual( true );
|
||||
|
||||
if ( [ 'flat_rate', 'local_pickup' ].includes( methodId ) ) {
|
||||
expect( body.settings.cost.value ).toEqual( cost );
|
||||
}
|
||||
expect( body.settings.cost.value || '' ).toEqual( cost || '' );
|
||||
|
||||
// Cleanup: Delete the shipping method
|
||||
await shippingMethodsApi.delete.shippingMethod(
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
CI: added a missing dev-dependency for passing tests in updated CI environment.
|
|
@ -171,6 +171,7 @@
|
|||
"jest-cli": "~27.5.1",
|
||||
"postcss": "^8.4.32",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^17.0.2",
|
||||
"rimraf": "5.0.5",
|
||||
"sass-loader": "^10.5.0",
|
||||
|
|
|
@ -87,7 +87,7 @@ describe( 'Search', () => {
|
|||
userEvent.type( getByRole( 'combobox' ), 'A' );
|
||||
// Wait for async options processing.
|
||||
await waitFor( () => {
|
||||
expect( optionsSpy ).toBeCalledWith( 'A' );
|
||||
expect( optionsSpy ).toHaveBeenCalledWith( 'A' );
|
||||
} );
|
||||
await waitFor( () => {
|
||||
expect( queryAllByRole( 'option' ) ).toHaveLength( 3 );
|
||||
|
@ -119,7 +119,7 @@ describe( 'Search', () => {
|
|||
userEvent.type( getByRole( 'combobox' ), 'A' );
|
||||
// Wait for async options processing.
|
||||
await waitFor( () => {
|
||||
expect( optionsSpy ).toBeCalledWith( 'A' );
|
||||
expect( optionsSpy ).toHaveBeenCalledWith( 'A' );
|
||||
} );
|
||||
await waitFor( () => {
|
||||
expect( queryAllByRole( 'option' ) ).toHaveLength( 3 );
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
CI: code style fixes to pass linting in updated CI environment.
|
|
@ -50,7 +50,7 @@ describe( 'fetchExperimentAssignment', () => {
|
|||
experimentName: '123',
|
||||
anonId: null,
|
||||
} );
|
||||
await expect( fetchPromise ).rejects.toThrowError();
|
||||
await expect( fetchPromise ).rejects.toThrow();
|
||||
} );
|
||||
|
||||
it( 'should throw error when experiment_name is empty', async () => {
|
||||
|
@ -58,7 +58,7 @@ describe( 'fetchExperimentAssignment', () => {
|
|||
experimentName: '',
|
||||
anonId: null,
|
||||
} );
|
||||
await expect( fetchPromise ).rejects.toThrowError();
|
||||
await expect( fetchPromise ).rejects.toThrow();
|
||||
} );
|
||||
|
||||
it( 'should throw error when experiment_name is invalid', async () => {
|
||||
|
@ -66,7 +66,7 @@ describe( 'fetchExperimentAssignment', () => {
|
|||
experimentName: '',
|
||||
anonId: null,
|
||||
} );
|
||||
await expect( fetchPromise ).rejects.toThrowError();
|
||||
await expect( fetchPromise ).rejects.toThrow();
|
||||
} );
|
||||
|
||||
it( 'should return .json response', async () => {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
CI: code style fixes to pass linting in updated CI environment.
|
|
@ -5,10 +5,6 @@ import { setLocaleData } from '@wordpress/i18n';
|
|||
import { registerStore } from '@wordpress/data';
|
||||
import 'regenerator-runtime/runtime';
|
||||
|
||||
// Mock the config module to avoid errors like:
|
||||
// Core Error: Could not find config value for key ${ key }. Please make sure that if you need it then it has a default value assigned in config/_shared.json.
|
||||
jest.mock( '@automattic/calypso-config' );
|
||||
|
||||
// Due to the dependency @wordpress/compose which introduces the use of
|
||||
// ResizeObserver this global mock is required for some tests to work.
|
||||
global.ResizeObserver = require( 'resize-observer-polyfill' );
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
CI: code style fixes to pass linting in updated CI environment.
|
|
@ -335,7 +335,7 @@ describe( 'navigateTo', () => {
|
|||
|
||||
const resultUrl = new URL( window.location.href );
|
||||
|
||||
expect( getHistory().push ).not.toBeCalled();
|
||||
expect( getHistory().push ).not.toHaveBeenCalled();
|
||||
expect( resultUrl.search ).toBe(
|
||||
'?page=wc-admin&path=%2Fsetup-wizard'
|
||||
);
|
||||
|
@ -353,7 +353,7 @@ describe( 'navigateTo', () => {
|
|||
|
||||
const resultUrl = new URL( window.location.href );
|
||||
|
||||
expect( getHistory().push ).not.toBeCalled();
|
||||
expect( getHistory().push ).not.toHaveBeenCalled();
|
||||
expect( resultUrl.toString() ).toBe(
|
||||
'https://vagrant.local/wp/wp-admin/orders.php'
|
||||
);
|
||||
|
@ -385,7 +385,7 @@ describe( 'navigateTo', () => {
|
|||
|
||||
const resultUrl = new URL( window.location.href );
|
||||
|
||||
expect( getHistory().push ).not.toBeCalled();
|
||||
expect( getHistory().push ).not.toHaveBeenCalled();
|
||||
expect( resultUrl.toString() ).toBe(
|
||||
'https://vagrant.local/wp/wp-admin/admin.php?page=wc-admin&path=%2Fsetup-wizard'
|
||||
);
|
||||
|
|
|
@ -14,6 +14,7 @@ class AddSplitChunkDependencies {
|
|||
apply( compiler ) {
|
||||
compiler.hooks.thisCompilation.tap(
|
||||
'AddStableChunksToAssets',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- not used.
|
||||
( compilation, callback ) => {
|
||||
compilation.hooks.processAssets.tap(
|
||||
{
|
||||
|
|
|
@ -330,6 +330,7 @@ const getFrontConfig = ( options = {} ) => {
|
|||
// translations which we must avoid.
|
||||
// @see https://github.com/Automattic/jetpack/pull/20926
|
||||
chunkFilename: `[name]-frontend${ fileSuffix }.js?ver=[contenthash]`,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- not used.
|
||||
filename: ( pathData ) => {
|
||||
return `[name]-frontend${ fileSuffix }.js`;
|
||||
},
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
CI: code style fixes to pass linting in updated CI environment.
|
|
@ -905,6 +905,9 @@ importers:
|
|||
postcss-loader:
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0(postcss@8.4.32)(webpack@5.89.0(webpack-cli@3.3.12))
|
||||
qrcode.react:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(react@17.0.2)
|
||||
react:
|
||||
specifier: ^17.0.2
|
||||
version: 17.0.2
|
||||
|
|
Loading…
Reference in New Issue