The workflow model
hypervise update-config [--physical-cpus K] [--recording | --no-recording] [--shards N]
Rules
- Every job starts recorded, on 1 physical CPU, as 1 shard. Anything
else is an explicit
update-config step.
- Recording needs 1 physical CPU. A recorded machine runs on one core,
which is what makes it deterministic.
--recording with more than one
CPU is an error.
- Shards are for good.
--shards N splits the machine into N exact
copies, and every later run: step runs in every copy. There is no way
back to one machine (half-done work can't be merged). Later
update-config calls apply to every shard. One split per job.
- Physical CPUs are host cores. The VM always has the runner's vCPUs.
--physical-cpus K runs them on K cores and keeps K online, so nproc
is K.
What a step sees
| Variable |
Meaning |
HV_SHARD_INDEX |
this shard, from 0 (0 before a split) |
HV_SHARD_COUNT |
number of shards (1 before a split) |
HV_RECORDED |
1 while recorded |
After a split
run: steps run in every shard. The step's log shows one group per
shard, and the step fails if any shard failed.
uses: steps run once, in the machine that keeps the GitHub runner
(its state from before the split). To hand files to such a step, gather
them first:
- run: hypervise gather reports/junit.xml
- uses: actions/upload-artifact@v4
with: {name: reports, path: shard-*/reports/}
Shards have no network. Fetch what the tests need before splitting:
cargo fetch, npm ci, go mod download, docker pull.
Costs
| Change |
Time |
| a split |
about 5 s |
| switching between recorded and unrecorded |
about 8 s |
| changing the CPU count while unrecorded |
about 8 s (a later version will do it in place) |