Run CI jobs on your machine
A CI job failed on the forge. Each try of a fix costs a push, and a wait for a container.
src ci run runs the same job on your machine: the same workflow file, steps, matrix cell and needs. You fix the job there, and push once.
The commands are in the npm package @tanstack-source/cli, which has the src binary. src ci plan and src ci run work without the forge.
Run a job
Plan the workflows. The command shows each workflow and its jobs, or the errors with the file to fix.
src ci planRun one job:
src ci run ci testRead the output. The command exits with 0 when the job passed, and with 1 when it failed.
These flags change what runs:
| Flag | What it does |
|---|---|
--matrix <key>=<value> | Runs only the matrix cells with this value. Repeat it for more keys. Without it, every cell runs, one after the other. |
--with-needs | Runs the jobs that the job needs first, and gives it their results and outputs. |
--input <name>=<value> | Gives a value to an input of manual(). Repeat it for more inputs. The run then has the event manual. |
src ci run e2e test --matrix shard=2
src ci run ci gate --with-needs
src ci run release publish --input channel=next
If a job has needs and you leave out --with-needs, the job gets no results or outputs of them. The command then warns you:
Job gate needs test, and this run gives it no results or outputs of them. Add --with-needs to run them first.
How a local run differs
- The trust level is
local. - The event is the type of the first trigger of the workflow. With
--input, the event ismanual. ctx.headis the commit that you checked out,ctx.baseis its parent, andctx.refis your branch.- The steps run in bash, in the root of your checkout, with your environment. On Windows, the steps use the bash of Git for Windows.
- Your machine has its own tools. To use the tools of the forge, use
--docker.
Give the job its secrets
A job gets each secret that it declares from your environment, then from .env in the root of the checkout. On your machine the job gets the value itself, because no proxy sits between the job and the network.
echo 'NPM_TOKEN=<your own token>' >> .env
src ci run release publish
The run reads from
.envonly the secrets that the jobs declare.If a required secret has no value, the command stops before any job runs:
src ci run: Job publish needs the secret NPM_TOKEN. Set it in the environment or in .env.
Keep .env out of git. The forge refuses a push that adds a .env file.
Where the cache, artifacts and fixups go
A local run keeps them in a folder of your machine: $XDG_CACHE_HOME/tanstack-source/, or ~/.cache/tanstack-source/ when XDG_CACHE_HOME is not set.
ci/: the entries ofcache(). Delete this folder to start with an empty cache.artifacts/: the archives ofartifact(). The step prints the path of each one.fixups/: the patches offixup(). The step prints thegit applycommand for each one.tools/: the Node, bun and pnpm that the setup steps download.
report() prints its findings in the log of the step.
Send real writes to the forge: --live
Without --live, each forge() write is a dry run. The step prints the write and sends nothing:
[dry run] POST /repos/acme/app/issues/7/comments {"body":"Released"}
With --live, the job also gets TSS_FORGE_URL and TSS_TOKEN, and forge() sends each write. --live needs TSS_FORGE_URL, TSS_TOKEN and TSS_REPO.
export TSS_FORGE_URL=https://forge.example/api/v1
export TSS_TOKEN=<your personal access token>
export TSS_REPO=acme/app
src ci run release publish --live
CAUTION: Use --live only when you want the writes on the forge. The writes use your own token, so the permissions of the job do not limit them.
Use the image of the forge: --docker
A job can pass on your machine and fail on the forge, because the tools are different. --docker runs the job in its CI image (node or browser) with Docker.
Build the two images once, from a checkout of the TanStack Source repository. The images are for
linux/amd64.docker build --platform linux/amd64 -t tanstack-source-ci-node -f apps/web/containers/node/Dockerfile packages/ci docker build --platform linux/amd64 -t tanstack-source-ci-browser -f apps/web/containers/browser/Dockerfile packages/ciRun the job with
--docker:src ci run ci test --docker
The command mounts your checkout at
/workspace, and runs the job in the container. It usestanstack-source-ci-browserwhen a job to run hasimage: 'browser'.Secrets and the
--livevariables go into the container by name, so their values never show in the command line.To see the
dockercommand without running it, add--print:docker run --rm --mount 'type=bind,source=/home/you/app,target=/workspace' --workdir /workspace tanstack-source-ci-node node /opt/tanstack-source/ci/src/cli.ts run ci test
In Docker, the cache, the artifacts and the fixup patches stay in the container, and Docker deletes the container after the run. Changes to the files of your checkout stay, because the checkout is mounted.
Run a job of a forge run again: --repro
Each job of a run on the forge has a repro command. The run page shows it under "Run this job on your machine". The command runs that job cell again, with the matrix cell, inputs and needs of that run.
Set
TSS_FORGE_URL,TSS_TOKENandTSS_REPO, as for--live.Check out the commit of the run:
git fetch origin <commit> git checkout --detach <commit>Run the command that you copied from the run page:
src ci run --repro '<run>/test (shard: 2)'
What to know about --repro:
- A job key has its matrix cell, like
test (shard: 2). Put it in quotes in the shell. - If your checkout is at another commit, the command stops and prints the two
gitcommands. - Secrets come from your environment and
.env, as in any local run. You can add--live. - The run gives the matrix cell, inputs and needs, so
--reprotakes no--matrix,--input,--with-needsor--docker.
From red to green
The test job of your pull request failed on the forge. Run it on your machine:
src ci run ci test
The end of the output shows the failed test, with its file and line:
--- Test
FAIL src/sum.test.ts > sum > adds two numbers
error src/sum.test.ts:5:22 sum > adds two numbers: expected 3 to be 4 // Object.is equality
Error: vitest exited with code 1
...
--- Test: failed (9.9 s): vitest exited with code 1
--- Save cache pnpm-3b1f2a9c8d7e6f50: skipped
Job test failed: Step "Test" failed: vitest exited with code 1
Fix src/sum.ts, then run the job again:
--- Test
✓ src/sum.test.ts (2 tests) 3ms
No findings
--- Test: passed (6.0 s)
--- Save cache pnpm-3b1f2a9c8d7e6f50
Saved the cache pnpm-3b1f2a9c8d7e6f50 in /home/you/.cache/tanstack-source/ci
--- Save cache pnpm-3b1f2a9c8d7e6f50: passed (2.2 s)
Job test passed.
Commit the fix and push it once. Then list the runs of your pull request:
src ci runs --pr 12
ID STATUS WORKFLOW EVENT REF COMMIT
d4e5f6a7-8b9c-4d0e-9f1a-2b3c4d5e6f70 success ci pull_request fix-sum 5d6e7f8
b51f0e2a-6c7d-4e8f-9a1b-2c3d4e5f6a7b failure ci pull_request fix-sum 1a2b3c4
The run of your fix is green, after one push.