-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ci(test): split into multiple machines #4164
Conversation
📊 Benchmark resultsComparing with 54040d8 Package size: 360 MB⬇️ 0.00% decrease vs. 54040d8
Legend
|
continue-on-error: true | ||
with: | ||
file: coverage/coverage-final.json | ||
flags: ${{ steps.test-coverage-flags.outputs.os }},${{ steps.test-coverage-flags.outputs.node }} | ||
if: '${{ !steps.release-check.outputs.IS_RELEASE }}' | ||
all: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is here strictly to make branch protection rules easier, to avoid changing those based on matrix naming
f6e9c84
to
c5cce82
Compare
d2379ef
to
55fc4ce
Compare
55fc4ce
to
e3e90fa
Compare
@@ -97,4 +104,5 @@ module.exports = { | |||
onChanges, | |||
getLanguage, | |||
createRewriter, | |||
getWatchers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we can close the watchers in the tests
@@ -44,8 +46,8 @@ test.after(async (t) => { | |||
t.context.server.on('close', resolve) | |||
t.context.server.close() | |||
}) | |||
// TODO: check why this line breaks the rewriter on windows | |||
// await t.context.builder.cleanupAsync() | |||
await Promise.all(getWatchers().map((watcher) => watcher.close())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to close the watchers as a part of the cleanup
@@ -0,0 +1,5 @@ | |||
const path = require('path') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was renamed
e3e90fa
to
94f78ee
Compare
runs-on: ${{ matrix.os }} | ||
timeout-minutes: 30 | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, macOS-latest, windows-latest] | ||
node-version: [12.x, '*'] | ||
machine: ['0', '1', '2', '3', '4', '5', '6'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea!
I am wondering about how this will scale. As we add more tests, we might be likely to distribute too many or not enough tests to a specific number, because that distribution is manual instead of being automated.
Not sure if this is worth exploring for this initial PR, but I am wondering whether we could hash each test filename (or file path relative to the repository root directory), then use a modulo on them to know to which machine to assign?
For example, if we had 16 machines, we could make a SHA-1 of each test filename, then use the last hexadecimal number to decide on which machine to use. We could make the base arbitrary (not only hexadecimal / base 16) so that increasing/decreasing the number of machines just works.
While this would be a more thorough initial implementation work, this would decrease the amount of maintenance: we would not need to figure out which digit to assign to each test file, instead the only thing we'd need to remember would be to keep test files small. Also, we would be able to optimize the best amount of machines easily by just trying different ones and see how long the CI tests take.
What do you think?
Note: that's just an idea. The initial PR looks ready to ship otherwise as it already helps a lot with the performance as is.
Also, we should probably merge this asap to avoid merge conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good idea, and I think we should definitely find a way to automate the distribution.
I like the idea of small specs (maybe we can enforce via a lint rule), making the need to load balance less important.
This is awesome @erezrokah! |
🎉 Thanks for submitting a pull request! 🎉
Summary
This is a PR to split our tests across multiple machines.
ava
sorts the files by name, then split them to chunks across machines. See hereDue to
ava
's behavior I grouped our unit tests to run during thebuild
job and our integration tests to run during thetest
job. Integration tests will get split across machines.Since there isn't a good way to load balance the tests, I renamed the specs to better distribute them (yes I know this is ugly).
I also divided the
dev
command tests into 6 specs to help with load balancing (thedev
spec had over 60 tests).To stabilize the tests I changed some specs to use
test.serial
.Also see avajs/ava#2947 for disabling worker threads
Todo
For us to review and ship your PR efficiently, please perform the following steps:
passes our tests.
A picture of a cute animal (not mandatory, but encouraged)