Skip to content

Commit

Permalink
Use GH Actions for parallelism rather than Yarn (#1029)
Browse files Browse the repository at this point in the history
`yarn test` is a multi-package command: it really runs `yarn test` for
each package in parallel using `yarn workspaces foreach`. This works
fine as long as all of the tests pass. But because this command produces
a lot of output, if tests fail for any package, it can be very difficult
to locate the failure. (The same goes for `yarn validate:changelog`.)

There are a few ways we could solve this when these commands are run
locally, but it's particularly a pain point when run on CI. For this
reason, this commit adjusts the GitHub Actions configuration so that we
use GitHub Actions instead of Yarn to run these commands in parallel
across the monorepo. This means that if tests fail for a particular
package, you only see output for that package and no other package.
  • Loading branch information
mcmire authored and MajorLift committed Oct 11, 2023
1 parent 1df2ecc commit e0c8732
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
36 changes: 34 additions & 2 deletions .github/workflows/lint-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jobs:
strategy:
matrix:
node-version: [14.x, 16.x]
outputs:
child-workspace-package-names: ${{ steps.workspace-package-names.outputs.child-workspace-package-names }}
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -18,6 +20,11 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable
- name: Fetch workspace package names
id: workspace-package-names
run: |
echo "child-workspace-package-names=$(yarn child-workspace-package-names-as-json)" >> "$GITHUB_OUTPUT"
shell: bash

lint:
name: Lint
Expand All @@ -35,7 +42,31 @@ jobs:
cache: yarn
- run: yarn --immutable --immutable-cache
- run: yarn lint
- run: yarn changelog:validate
- name: Require clean working directory
shell: bash
run: |
if ! git diff --exit-code; then
echo "Working tree dirty at end of job"
exit 1
fi
validate-changelog:
name: Validate changelog
runs-on: ubuntu-latest
needs: prepare
strategy:
matrix:
node-version: [14.x, 16.x]
package-name: ${{ fromJson(needs.prepare.outputs.child-workspace-package-names) }}
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable --immutable-cache
- run: yarn workspace ${{ matrix.package-name }} changelog:validate
- name: Require clean working directory
shell: bash
run: |
Expand Down Expand Up @@ -75,6 +106,7 @@ jobs:
strategy:
matrix:
node-version: [14.x, 16.x]
package-name: ${{ fromJson(needs.prepare.outputs.child-workspace-package-names) }}
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -83,7 +115,7 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable --immutable-cache
- run: yarn test
- run: yarn workspace ${{ matrix.package-name }} run test
- name: Require clean working directory
shell: bash
run: |
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"build:docs": "yarn workspaces foreach --parallel --interlaced --verbose run build:docs",
"build:watch": "yarn run build --watch",
"changelog:validate": "yarn workspaces foreach --parallel --interlaced --verbose run changelog:validate",
"child-workspace-package-names-as-json": "ts-node scripts/child-workspace-package-names-as-json.ts",
"generate-dependency-graph": "ts-node scripts/generate-dependency-graph.ts",
"lint": "yarn lint:eslint && yarn lint:misc --check && yarn constraints",
"lint:eslint": "eslint . --cache --ext js,ts",
Expand Down
20 changes: 20 additions & 0 deletions scripts/child-workspace-package-names-as-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!yarn ts-node

import execa from 'execa';

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

/**
* The entrypoint to this script.
*/
async function main() {
const { stdout } = await execa('yarn', ['workspaces', 'list', '--json']);
const workspaces = stdout.split('\n').map((line) => JSON.parse(line));
const childWorkspaceNames = workspaces
.filter((workspace) => workspace.location !== '.')
.map((workspace) => workspace.name);
console.log(JSON.stringify(childWorkspaceNames));
}

0 comments on commit e0c8732

Please sign in to comment.