CI
A hosted runner has two cores and seven gigabytes. Your pool has more. Keep the workflow where it is and send the expensive step to the pool.
From a hosted runner
The workflow stays on GitHub's runners and only the command moves. Checkout, caching and reporting work as before; the step that compiles or solves runs on a pool machine, streams its output into the job log, and fails the step with its own exit code.
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- run: uv tool install "git+https://github.com/milanofthe/falllow#subdirectory=cli"
- run: falllow login --server https://app.falllow.com --token "$FALLLOW_TOKEN"
env:
FALLLOW_TOKEN: ${{ secrets.FALLLOW_TOKEN }}
# the heavy part, on the pool
- run: falllow run --cpu 16 --memory 32G -- cargo test --workspace --releaseOne secret makes this work: FALLLOW_TOKEN, a token for the server.
Give CI a user of its own rather than the admin token, so it can be revoked without locking you
out.
The checkout on the runner is what gets shipped, exactly as it is. Pull requests need nothing special: the merge commit GitHub checks out is a directory like any other.
When the pool fails, not the tests
Exit code 170 means the job did not get to a verdict: the machine
was lost or nothing was free in time. That is the one case where running it again can give a
different answer, so it is the only one worth retrying.
falllow run -- cargo test --workspace || {
code=$?
[ $code -eq 170 ] && falllow run -- cargo test --workspace
exit $code
}A runner on a pool machine
For workflows that should run entirely on your hardware, register a GitHub self-hosted runner on a
machine in the fleet and target it with runs-on: self-hosted. The runner and the
pool's jobs share that machine, so cap the runner's cores and leave the machine's blocks for
dstack. This is GitHub's own runner, nothing falllow reimplements.