| name | mina-ci-commands |
| description | Use when the user asks to trigger Mina CI, Buildkite CI, PR CI, !ci-build-me, !ci-single-me, !ci-docker-me, !ci-nightly-me, or other MinaProtocol/mina GitHub comment CI commands. Use this skill to choose the right magic comment and post it with gh CLI on Mina PRs instead of guessing command syntax. |
Mina CI Commands
Use this skill when working in or against MinaProtocol/mina and the user asks to trigger CI, rerun Buildkite, run a specific job, build docker/debian/toolchain artifacts, run nightly CI, or post a !ci-* PR comment.
The Mina repo uses GitHub PR comments as CI control commands. Prefer gh CLI; do not invent syntax. If the target PR or job/filter is ambiguous, ask one focused question before commenting.
Safety checks before posting
- Identify the PR number or URL.
- Confirm the repository is
MinaProtocol/mina unless the user explicitly gives another repo.
- If the requested command is broad or expensive (
!ci-build-me, !ci-nightly-me, broad !ci-docker-me), proceed if the user clearly requested it; otherwise ask confirmation.
- Prefer exact command-only comments unless extra context is useful. The CI bot mostly keys off the command text.
- After posting, return the GitHub comment URL and the exact command body.
Useful PR extraction:
pr=19061
gh pr view --repo MinaProtocol/mina --json number,url,headRefName,baseRefName
Post a comment:
gh api repos/MinaProtocol/mina/issues/$pr/comments \
-f body='!ci-build-me' \
--jq '.html_url'
For multiline comments, use -F body=/path/to/body.txt.
Commands handled by frontend/ci-build-me
These commands are handled by the Mina frontend/ci-build-me webhook on issue_comment.created for PRs. The comment author must be a public member of the MinaProtocol GitHub org for most commands.
| Command | Buildkite pipeline | Use when |
|---|
!ci-build-me | mina-o-1-labs | Normal broad PR CI / rerun standard CI. |
!ci-nightly-me | mina-end-to-end-nightlies | Nightly/end-to-end checks. Heavier than normal CI. |
!ci-nix-me | mina-nix-experimental | Nix experimental pipeline. |
!ci-debian-me | mina-build-debian | Debian package build pipeline. |
!ci-docker-me | mina-build-docker | Docker image build pipeline; may be filtered. |
!ci-toolchain-me | mina-toolchains-build | Rebuild the opam toolchain images (tag Toolchain). Takes hours. Does not touch the mina-base images. |
!ci-docker-base-me | mina-docker-base-build | Rebuild the shared mina-base images (tag Base) for all codenames. Use after changing dockerfiles/stages/1-base-deps, or to publish/refresh the minaBase* pins. |
!approved-for-mainnet | mina-pr-gating | Mainnet approval/gating command; restricted to specific approvers. |
Examples:
gh api repos/MinaProtocol/mina/issues/$pr/comments -f body='!ci-build-me' --jq '.html_url'
gh api repos/MinaProtocol/mina/issues/$pr/comments -f body='!ci-nightly-me' --jq '.html_url'
gh api repos/MinaProtocol/mina/issues/$pr/comments -f body='!ci-debian-me' --jq '.html_url'
gh api repos/MinaProtocol/mina/issues/$pr/comments -f body='!ci-toolchain-me' --jq '.html_url'
gh api repos/MinaProtocol/mina/issues/$pr/comments -f body='!ci-docker-base-me' --jq '.html_url'
!ci-docker-base-me
Takes no arguments. It triggers mina-docker-base-build with:
BUILDKITE_PIPELINE_FILTER=BaseDockersOnly
BUILDKITE_PIPELINE_JOB_SELECTION=Full
BaseDockersOnly maps to the Base tag, which only the MinaBaseArtifact* jobs carry, so the opam toolchain images are excluded. Full skips dirty-when triage, so the rebuild runs even when the PR touched nothing under dockerfiles/stages/.
This is the only way these jobs run: they carry neither Fast nor Long, so the standard PR/nightly pipeline stages (FastOnly, LongAndVeryLong, TearDownOnly) filter them out regardless of dirtyWhen.
Each selected job pushes to docker.io/minaprotocol/mina-base:<githash>-<codename>-<network> and writes ${CACHE_ROOT}/mina-base/<tag>.tar.zst to the storagebox. After it finishes, bump the minaBase* pins in buildkite/src/Constants/ContainerImages.dhall to the new githash, otherwise the daemon/archive builds keep falling back to building the base-deps stage inline.
!ci-docker-me filters
Current ci-build-me parsing accepts only whitespace-separated key=value arguments. Only these keys affect the Buildkite env:
arch: amd64, arm64
profile: devnet, lightnet, mainnet
codename: jammy, noble, bullseye, focal, bookworm
When all three are present and valid, the handler sets:
BUILDKITE_PIPELINE_FILTER=DockerBuild<Arch><Profile><Codename>
BUILDKITE_PIPELINE_FILTER_MODE=All
Example:
!ci-docker-me arch=amd64 profile=devnet codename=bookworm
maps to:
DockerBuildAmd64DevnetBookworm
Post it:
gh api repos/MinaProtocol/mina/issues/$pr/comments \
-f body='!ci-docker-me arch=amd64 profile=devnet codename=bookworm' \
--jq '.html_url'
If any of arch, profile, or codename is missing, the current handler falls back to the broad filter:
BUILDKITE_PIPELINE_FILTER=DockerBuild
Do not use old examples like network=testnet-generic; the current handler ignores that key.
!ci-single-me <JobName>
!ci-single-me is not handled by frontend/ci-build-me. It is a separate mechanism that runs buildkite/scripts/run-single-job-with-deps.sh or equivalent logic.
Use it to trigger one generated Buildkite job and its dependencies:
!ci-single-me HardForkTestMixed
Post it:
gh api repos/MinaProtocol/mina/issues/$pr/comments \
-f body='!ci-single-me HardForkTestMixed' \
--jq '.html_url'
Matching behavior from buildkite/scripts/run-single-job-with-deps.sh:
- Case-insensitive.
- Full-string exact match against generated YAML
spec.name.
- Falls back to filename stem if
spec.name is absent.
- No substring matching.
- No aliases found.
Good:
!ci-single-me HardForkTestMixed
!ci-single-me TestnetIntegrationTests
!ci-single-me TestnetIntegrationTestsLocalApps
Likely bad:
!ci-single-me HardFork
!ci-single-me Testnet
Known job-name families
The effective names come from generated Buildkite YAML under buildkite/src/gen/, created from Dhall. If accuracy matters, inspect or regenerate the current job list before posting.
Previously observed examples include:
- Test:
HardForkTestMixed, HardForkTestLegacy, TestnetIntegrationTests, TestnetIntegrationTestsLocalApps, TestnetIntegrationTestsLong, SingleNodeTest, RosettaIntegrationTests, ArchiveNodeTest, DaemonUnitTest, Libp2pUnitTest, ZkappsExamplesTest, MonorepoTest, NixBuildTest, VersionLint.
- Lint:
OCaml, Rust, Dhall, Docker, Bash, Changelog, Fast, Merge, Xrefcheck, ArchiveUpgrade.
- Bench:
ArchiveStable, ArchiveUnstable, HeapUsageStable, HeapUsageUnstable, LedgerApplyStable, LedgerApplyUnstable, MinaBaseStable, MinaBaseUnstable, SnarkProfilerStable, SnarkProfilerUnstable, ZkappLimitsStable, ZkappLimitsUnstable.
- Release:
MinaArtifactBookworm, MinaArtifactBookwormArm64, MinaArtifactBullseye, MinaArtifactBullseyeApps, MinaArtifactBullseyeInstrumented, MinaArtifactMainnetBullseye, MinaArtifactNoble, MinaToolchainArtifactBookworm, MinaToolchainArtifactNoble, Minimina, TraceTool.
- TearDown:
Coverage.
Release names are especially dynamic because they are derived from Dhall constants such as network, Debian codename, build flags, and architecture.
Discover current job names
When the user asks for a specific !ci-single-me job and the exact name is uncertain, inspect the repo instead of guessing.
Useful files:
buildkite/scripts/run-single-job-with-deps.sh
buildkite/src/Jobs/
buildkite/src/gen/ if present/generated
buildkite/HOWTO-add-a-job.md
Fast checks:
rg 'HardForkTestMixed|TestnetIntegrationTests|spec.name|name =' buildkite/src buildkite/scripts
rg '^\s*name:|spec:' buildkite/src/gen buildkite -g '*.yml' -g '*.yaml'
If a generated list is unavailable and the job name matters, run or inspect the repo's Dhall generation path before posting.
Survey existing usage
Use GitHub search when you need examples from past PRs:
gh api -X GET search/issues \
-f q='repo:MinaProtocol/mina is:pr !ci-docker-me in:comments' \
-f per_page=30 \
--jq '.items[] | {number,title,url,updated_at}'
Fetch matching comments for specific PRs:
for pr in 19061 18638; do
gh api "repos/MinaProtocol/mina/issues/$pr/comments" --paginate \
--jq ".[] | select(.body | test(\"!ci-\"; \"i\")) | {pr:$pr,user:.user.login,created_at,url:.html_url,body:.body}"
done
Response format after triggering
Keep it concise:
Posted:
<comment URL>
Body:
!ci-single-me HardForkTestMixed
If no comment was posted because details were ambiguous, say what is missing and suggest the exact candidate command.