CI/CD Architecture¶
This is the canonical reference for FastVideo's CI/CD system. Contributor-facing PR steps live in Pull Requests, and test-authoring guidance lives in Testing.
Overview¶
FastVideo splits validation across GitHub Actions, Buildkite, and Modal:
PR opened or updated
|
|-- Tier 1: pre-commit
| GitHub Actions on ubuntu-latest
| style, lint, type, spelling, Markdown, workflow syntax, filenames
|
|-- Tier 2: Fastcheck
| Buildkite orchestrates Modal GPU jobs
| path-filtered component and unit checks
|
|-- /merge, /test full, or ready label
|
`-- Tier 3: Full Suite
Buildkite orchestrates Modal GPU jobs
path-filtered integration, SSIM, training, eval, and performance checks
|
pass -> Mergify squash-merges when all merge conditions pass
fail -> fix, push, and re-run
CI is not one monolithic job:
- GitHub Actions owns pre-commit, slash-command handling, aggregate status updates, docs deployment, image builds, package publishing, and community automations.
- Buildkite owns the GPU test pipeline and path filtering.
- Modal owns the actual GPU execution environment for test jobs.
- Mergify owns merge protection, labeling, and the final squash merge.
CI Tiers¶
Tier 1: Pre-commit¶
| Attribute | Value |
|---|---|
| Triggered by | Pull requests targeting main, plus /test pre-commit through workflow_call |
| Runner | GitHub Actions, ubuntu-latest |
| Workflow | .github/workflows/ci-precommit.yml |
| Local command | pre-commit run --all-files |
The workflow runs .pre-commit-config.yaml with --hook-stage manual.
| Hook | Checks |
|---|---|
yapf | Python formatting |
ruff | Python linting and auto-fixes |
codespell | Spelling in code and docs |
pymarkdown | Markdown formatting |
actionlint | GitHub Actions workflow syntax |
mypy | Static typing |
check-filenames | Spaces in tracked filenames |
Run the pre-commit command above to reproduce failures locally. Do not bypass the project hook chain by calling individual tools directly unless you are debugging a hook implementation.
Tier 2: Fastcheck¶
| Attribute | Value |
|---|---|
| Triggered by | Buildkite PR builds with TEST_SCOPE=fastcheck or unset |
| Runner | Buildkite agent that launches Modal GPU jobs |
| Definition | .buildkite/pipeline.yml |
| Entrypoint | .buildkite/scripts/pr_test.sh -> fastvideo/tests/modal/pr_test.py |
Fastcheck uses Buildkite's monorepo-diff plugin. Jobs whose watched paths did not change are skipped and do not block the aggregate fastcheck-passed status.
| Buildkite label | TEST_TYPE | Main watched paths |
|---|---|---|
| Encoder Tests | encoder | fastvideo/models/encoders/**, fastvideo/models/loader/**, fastvideo/tests/encoders/**, pyproject.toml, docker/Dockerfile |
| VAE Tests | vae | fastvideo/models/vaes/**, fastvideo/models/loader/**, fastvideo/tests/vaes/**, pyproject.toml, docker/Dockerfile |
| Transformer Tests | transformer | fastvideo/models/dits/**, fastvideo/models/loader/**, fastvideo/tests/transformers/**, fastvideo/layers/**, fastvideo/attention/**, pyproject.toml, docker/Dockerfile |
| Kernel Tests | kernel_tests | fastvideo-kernel/**, pyproject.toml, docker/Dockerfile |
| Unit Tests | unit_test | fastvideo/**, .buildkite/**, .github/**, pyproject.toml, docker/Dockerfile |
| DreamVerse App Tests | dreamverse_app | apps/dreamverse/**, pyproject.toml |
Tier 3: Full Suite¶
| Attribute | Value |
|---|---|
| Triggered by | /merge, adding ready, /test full, or a new push to a PR that already has ready |
| Runner | Buildkite agent that launches Modal GPU jobs |
| Definition | .buildkite/pipeline.yml |
| Entrypoint | .buildkite/scripts/pr_test.sh -> fastvideo/tests/modal/pr_test.py |
Full Suite is also path-filtered. It validates broader behavior before Mergify can merge a PR.
A ready-labeled PR does not hit Buildkite immediately: ci-trigger-full-suite.yml first runs .github/scripts/gate_full_suite.sh, which waits for the cheap Tier-1 checks (pre-commit, docs build) on the PR head. A red cheap check blocks the suite (fail closed; the next push re-arms it), while a GitHub outage or a >25 min wait lets it run anyway (fail open). /test full bypasses the gate.
| Buildkite label | TEST_TYPE | Main watched paths |
|---|---|---|
| SSIM Tests | ssim | fastvideo/**/*.py, pyproject.toml, docker/Dockerfile |
| LoRA Inference Tests | inference_lora | LoRA tests, loader, transformer tests, pipelines, LoRA layers |
| LoRA Extraction Tests | lora_extraction | LoRA extraction scripts/tests, loader, training utilities, LoRA layers |
| Training Tests | training | fastvideo/**, pyproject.toml, docker/Dockerfile |
| Distillation DMD Tests | distillation_dmd | fastvideo/training/*distillation_pipeline.py |
| Self-Forcing Tests | self_forcing | self-forcing distillation pipeline and tests |
| LoRA Training Tests | training_lora | fastvideo/**, pyproject.toml, docker/Dockerfile |
| Training Tests VSA | training_vsa | fastvideo/**, fastvideo-kernel/**, pyproject.toml, docker/Dockerfile |
| Inference Tests VMoBA | inference_vmoba | fastvideo-kernel/**, fastvideo/attention/backends/vmoba.py |
| Performance Tests | performance | DiTs, pipelines, attention, layers, worker, entrypoints, performance tests/configs |
| API Server Tests | api_server | OpenAI entrypoints, serve CLI, OpenAI API integration test |
| Train Framework Tests | train_framework | fastvideo/train/**, train model/method tests, model loader, DiTs |
| Eval Metrics Tests | eval | fastvideo/eval/**, fastvideo/tests/eval/**, pyproject.toml, docker/Dockerfile |
See Performance Benchmarks for the performance lane's thresholds, rolling baseline, artifacts, and reseeding process.
Slash Commands¶
Slash commands are handled by .github/workflows/ci-slash-commands.yml. Repository write permission is required.
| Command | Effect |
|---|---|
/merge | Adds ready and triggers Full Suite for the PR head branch. |
/test full | Runs the whole Full Suite with TEST_SCOPE=full. |
/test fastcheck | Runs the whole Fastcheck suite with TEST_SCOPE=fastcheck. |
/test pre-commit | Re-runs the pre-commit workflow on the PR merge ref. |
/test <name> | Runs one Buildkite test with TEST_SCOPE=direct. |
Valid direct test names:
| Command | TEST_TYPE |
|---|---|
/test encoder | encoder |
/test vae | vae |
/test transformer | transformer |
/test kernel | kernel_tests |
/test unit | unit_test |
/test dreamverse | dreamverse_app |
/test ssim | ssim |
/test training | training |
/test lora-inference | inference_lora |
/test lora-training | training_lora |
/test lora-extraction | lora_extraction |
/test distillation | distillation_dmd |
/test self-forcing | self_forcing |
/test vsa | training_vsa |
/test vmoba | inference_vmoba |
/test performance | performance |
/test api | api_server |
/test train-framework | train_framework |
/test eval | eval |
When a direct test completes successfully, Buildkite posts direct-test-completed. .github/workflows/ci-aggregate-status.yml then reads the latest Buildkite statuses for the commit and updates fastcheck-passed or full-suite-passed if all jobs in that group are green.
Skipped path-filtered jobs have no status entry and do not block the aggregate.
Merge Protection¶
Mergify enforces these conditions before it squash-merges to main:
| Condition | Meaning |
|---|---|
check-success~=pre-commit | Tier 1 passed. |
check-success=fastcheck-passed | All triggered Fastcheck jobs passed. |
check-success=full-suite-passed | All triggered Full Suite jobs passed. |
#approved-reviews-by>=1 | At least one approving review. |
| Valid title regex | PR title starts with an accepted [type] tag. |
label=ready | The PR has entered the merge flow. |
-draft | PR is not a draft. |
-conflict | PR has no merge conflicts. |
-closed | PR is still open. |
The final merge action is a squash merge. Mergify also labels conflicting PRs with needs-rebase and removes that label after conflicts are resolved.
Title Tags And Labels¶
PR title tags are the source for type:* labels and are required by merge protection.
| Tag | Label | Use for |
|---|---|---|
[feat], [feature] | type: feat | New feature or capability |
[bugfix], [fix] | type: bugfix | Bug fix |
[refactor] | type: refactor | Code restructuring without behavior change |
[perf] | type: perf | Performance improvement |
[ci] | type: ci | CI/CD or build tooling changes |
[infra] | type: infra | Repo infrastructure, agent tooling, debug hooks, conversion scripts, dev infra |
[doc], [docs] | type: docs | Documentation only |
[misc], [chore] | type: misc | Housekeeping, dependency bumps, cleanup |
[kernel] | No dedicated type label currently | CUDA kernel changes in fastvideo-kernel/ |
[new-model] | type: new-model | Adding a new model or pipeline |
[skill], [skills] | type: skill | Agent skills under .agents/skills/ or .claude/skills/ |
Scope labels are inferred from changed files.
| Label | File paths that trigger it |
|---|---|
scope: training | fastvideo/train/, fastvideo/training/, fastvideo/distillation/, examples/train/, examples/training/, examples/distill/ |
scope: inference | fastvideo/pipelines/basic/, fastvideo/pipelines/stages/, fastvideo/pipelines/samplers/, fastvideo/entrypoints/, fastvideo/worker/, fastvideo/api/sampling_param.py, fastvideo/configs/pipelines/, examples/inference/ |
scope: attention | fastvideo/attention/ |
scope: kernel | fastvideo-kernel/, csrc/ |
scope: data | fastvideo/dataset/, fastvideo/pipelines/preprocess/, examples/preprocessing/ |
scope: infra | .github/, .buildkite/, fastvideo/tests/, docker/ |
scope: distributed | fastvideo/distributed/ |
scope: docs | docs/ |
scope: studio | apps/fastvideo_studio/ |
scope: model | fastvideo/models/, fastvideo/layers/, fastvideo/configs/models/ |
Process labels:
| Label | Who sets it | Meaning |
|---|---|---|
ready | /merge or maintainer action | Triggers/keeps Full Suite active and enables auto-merge. |
needs-rebase | Mergify | PR has merge conflicts. |
do-not-merge | Maintainer | Blocks merge regardless of CI status. |
Modal Test Entrypoints¶
All Buildkite test jobs go through .buildkite/scripts/pr_test.sh, which:
- Reads Buildkite secrets for Modal, Hugging Face, and W&B when needed.
- Selects a Modal function based on
TEST_TYPE. - Passes Buildkite metadata into the Modal container.
- Runs the selected test command from
fastvideo/tests/modal/pr_test.pyorfastvideo/tests/modal/ssim_test.py. - Uploads performance artifacts for
TEST_TYPE=performance.
If you add a new CI test category:
- Add the Modal function in
fastvideo/tests/modal/pr_test.pyor a focused companion module. - Add the
TEST_TYPEcase in.buildkite/scripts/pr_test.sh. - Add the Buildkite direct-test step and any Fastcheck/Full Suite path filters in
.buildkite/pipeline.yml. - Add or update the
/testmapping in.github/workflows/ci-slash-commands.yml. - Document the lane here and link any domain-specific authoring guide.
CD And Release Workflows¶
Documentation¶
.github/workflows/infra-docs.yml builds documentation for PRs that touch docs/**, mkdocs.yml, requirements-mkdocs.txt, or the workflow itself. On pushes to main, it also deploys the built site to GitHub Pages.
The docs job:
- Installs the pinned MkDocs dependencies.
- Runs
mkdocs build; the native MkDocs hook generates example pages before the build. - Runs
python scripts/check_docs_links.pyagainst the generated documentation. - Uploads the Pages artifact and deploys only from
main.
Docker Images¶
.github/workflows/infra-build-image.yml supports manual workflow_dispatch runs and automatically rebuilds the CUDA matrix when a repository-controlled image input changes on main in the canonical repository. Those inputs include the CUDA Dockerfile and reusable workflow, dependency metadata, Docker context policy, fastvideo-kernel/**, and the kernel artifact metadata/key helper. Manual runs let maintainers choose which image families to build. The fastvideo-dev matrix builds Python 3.12 images for CUDA 12.6 and CUDA 13 on native amd64 and arm64 runners, then publishes one multi-platform manifest per CUDA version. CUDA 12.6 owns the py3.12-latest and global latest tags, as well as the explicit py3.12-cuda12.6.3-latest alias. CUDA 13 is published under the explicit py3.12-cuda13.0.0-latest tag. This publication policy does not change the unparameterized docker/Dockerfile build defaults, which remain CUDA 13 and cu130.
Published amd64 development images keep their configured Hopper kernel wheel installed and also carry an immutable SM89 wheel under /opt/fastvideo-kernel-prebuilt. Modal PR and SSIM jobs select the exact source, ABI, and GPU-architecture match from that directory, so L40S jobs reuse the trusted image artifact while kernel-changing PRs still build locally. Once a kernel or artifact-key change reaches main, the image workflow republishes the matching trusted artifact before later jobs consume the updated image tag.
The optional Dreamverse matrix builds backend and UI images for CUDA 12.6 and CUDA 13 on amd64. Dreamverse remains amd64-only because its FA4 dependency stack is not yet validated on ARM64.
The reusable implementation lives in .github/workflows/_template-build-image.yml.
Package Publishing¶
| Workflow | Trigger | Publishes |
|---|---|---|
publish-fastvideo.yml | pyproject.toml changes on main, or manual dispatch | fastvideo package to PyPI when the version changes |
publish-kernel.yml | fastvideo-kernel/pyproject.toml changes on main, or manual dispatch | fastvideo-kernel wheels to PyPI when the version changes |
publish-comfyui.yml | pyproject.toml changes on main/master, or manual dispatch | ComfyUI custom node to the Comfy registry |
Community Automations¶
| Workflow | Trigger | Purpose |
|---|---|---|
community-issue-labeler.yml | Issue opened or edited | Adds scope/platform labels from issue keywords. |
community-welcome.yml | First contribution | Posts a welcome comment for first-time contributors. |
community-stale.yml | Daily schedule | Marks and closes stale issues and PRs, with exemption labels. |
File Reference¶
| File | Owner area |
|---|---|
.github/mergify.yml | Merge protection, PR title validation, PR labels, conflict labels, auto-merge |
.github/workflows/ci-precommit.yml | Tier 1 pre-commit |
.github/workflows/ci-slash-commands.yml | /merge and /test handling |
.github/workflows/ci-trigger-full-suite.yml | Full Suite trigger for ready PRs and new pushes to ready PRs |
.github/workflows/ci-aggregate-status.yml | Aggregate Fastcheck/Full Suite commit statuses |
.buildkite/pipeline.yml | Buildkite test graph and path filters |
.buildkite/scripts/pr_test.sh | Buildkite-to-Modal test dispatcher |
fastvideo/tests/modal/pr_test.py | Modal functions for most GPU CI lanes |
fastvideo/tests/modal/ssim_test.py | Modal functions and partitioning for SSIM |
.buildkite/performance-benchmarks/tests/*.json | Performance benchmark configs and thresholds |
.github/workflows/infra-docs.yml | Docs build and GitHub Pages deploy |
.github/workflows/infra-build-image.yml | Automatic CUDA matrix and manual Docker image builds |
.github/workflows/publish-fastvideo.yml | FastVideo PyPI publishing |
.github/workflows/publish-kernel.yml | FastVideo kernel PyPI publishing |
.github/workflows/publish-comfyui.yml | ComfyUI registry publishing |