Project
Contributing
Golden rules, the PR bar and the review checklist.
CONTRIBUTING.mdOn this page
Thanks for your interest in SnowOps Labs — the flight simulator for platform engineers. This project thrives on community-contributed scenarios, platform modules, documentation, and code. This guide explains how to contribute and what to expect.
New here? The highest-leverage place to start is content — a new scenario or incident. Start with Your First Scenario and look for issues labelled good first issue.
Code of Conduct
By participating you agree to our Code of Conduct.
Sign-off (DCO)
SnowOps Labs uses the Developer Certificate of Origin — a lightweight,
no-paperwork way to certify you wrote (or have the right to submit) your
contribution. Just add a Signed-off-by line to each commit by committing with
-s:
git commit -s -m "your message"The DCO check in CI verifies every commit in a PR is signed off. That's the only agreement required — no CLA, no bot account, no click-through.
What you can contribute
| Type | Where it lives | Review owner |
|---|---|---|
| Scenarios | scenarios/ |
scenario maintainers |
| Platform modules | platform/<category>/<provider>/ |
platform maintainers |
| Incidents / learning / challenges | incidents/, learn/, challenges/ |
scenario maintainers |
| Documentation | docs/ |
docs maintainers |
| Engine / CLI / SDK | src/cmd/, src/internal/, src/pkg/, src/engine/ |
lead maintainer (see GOVERNANCE.md) |
Changes to the engine, the public SDK (pkg/), or the scenario schema require an
RFC first — a short markdown PR under docs/rfcs/ that a maintainer approves
before implementation. This keeps architectural direction coherent.
Development setup
Unlike end users (who download a released labctl binary — see the
README Quickstart), contributors build labctl from
source so they can test their changes. You need Go 1.24+ and Node 22+.
The steps are identical on macOS, Linux, and Windows/WSL2 — on Windows run them
inside your WSL2 distro, never native PowerShell.
# 1. Build the CLI, UI embedded (no committed binary). The Go module lives under
# src/; the root make targets delegate there and the binary lands at bin/labctl.
make cli-build
# 2. Run the gates. All four test layers are mandatory — see docs/TESTING.md.
make test # Go unit + shell (bats), race detector, coverage gate
make test-ui # vitest component tests
make test-e2e # playwright journeys
make lint # gofmt, golangci-lint, gosec, govulncheck, shellcheck,
# shfmt, the portability gate, and TypeScript strict
# 3. Bring up a local cluster + platform to test changes end to end. Use the CLI
# you just built — it drives the same loop end users run:
bin/labctl init # setup-tools + create cluster + install platform
bin/labctl scenario up observability-sreNew to the repo? Work through R00 — Environment & Build once; it verifies your setup and shows you each gate biting.
The golden rules (please read before a code/content PR)
- Cross-platform. Must run on macOS (Apple Silicon + Intel) and modern
Linux. No GNU-only shell flags (
grep -P,sed -iwithout a backup suffix,readlink -f,date -d), and no cgo — it breaks cross-compilation.make lint-shellenforces this automatically. - Go orchestrates, scripts do the work. Don't move shell/helm/kubectl logic into Go.
- Declarative content. Scenarios, faults, learning paths and checks are YAML + scripts — never hardcoded in Go.
- Idempotent everything.
helm upgrade --install,kubectl apply, safe re-activation. Interrupting an operation and re-running it must converge. - Every operation is cancellable and durable. Anything that shells out goes
through
internal/runwith a context, a timeout and a lock key. Never callexec.Command(...).Run()directly. - Tests at every applicable layer. Go unit (table-driven, hermetic, ≥80%, cancellation covered), bats for scripts with logic, contract tests for endpoints and commands, Vitest + Playwright for UI. See docs/TESTING.md.
- Docs and runbook in the same PR. Update the relevant
docs/, add or update the runbook, and write an ADR if you made a notable decision.
Pull-request workflow
fork → branch → make your change → run lint + tests → commit with -s (DCO) →
open a PR → CI green → CODEOWNERS review → maintainer merge- Keep PRs focused and small where possible.
- Use Conventional Commits (
feat:,fix:,docs:,ci:,chore:). - Fill out the PR template (what/why/how-tested).
- CI must pass every gate: Go build/vet/test on macOS and Linux with the race detector, the per-package coverage gate, golangci-lint, gosec, govulncheck, a fuzz smoke run, bats, shellcheck, the portability gate, TypeScript strict, vitest, Playwright, the license scan, and content validation. None of them are advisory.
- A maintainer or domain code owner reviews; the lead maintainer holds final merge authority on engine/SDK/schema changes (see GOVERNANCE.md).
Reporting bugs / requesting features
Use the issue templates. For security vulnerabilities, do not open a public issue — follow SECURITY.md.
Licensing of contributions
All contributions are licensed under Apache-2.0 (the same license as
the project); your Signed-off-by line certifies you have the right to submit
them under it (see DCO.md). New source files should carry an SPDX
header:
// SPDX-License-Identifier: Apache-2.0Thank you for helping build the open platform-engineering simulator. ✈️