Shipwright is a Dagger-powered software delivery engine: it defines CI/CD pipelines as code, once, so they can run the same way on your laptop and in any CI provider.
CI/CD logic tends to spread out and drift: provider YAML (GitHub Actions, GitLab CI, Jenkins) accumulates business delivery logic, local scripts reimplement a looser version of the same thing for developer convenience, and every repository re-derives its own version of "lint, test, build, scan, package, publish." Shipwright's premise is that this logic should live in one place, as code, executed consistently — with CI providers reduced to thin triggers instead of the source of truth for delivery behavior.
Shipwright is under active architectural evolution. It started as a Go-specific pipeline library and is moving toward a provider-neutral, polyglot delivery engine built on Dagger. Some of what follows already works today; some of it is the direction the project is heading. They are marked accordingly — do not assume a "planned" item is already usable.
Available today
- A compiled Go CLI/binary (
shipwright) whose sole entrypoint is a declarative workflow manifest engine (--workflow,shipwright.dev/v1schema) that composes registered providers per step. Providers registered today include five Go providers (setup/test, lint, vulnerability scan, build, container publish) plus a full Rust equivalent set (rust,rust-test,rust-integration-test,clippy,cargo-audit,rust-container) and toolchain-driftruntime-inspect/runtime-upgradecapabilities. - A Docker/Dagger-based execution path for workflow steps.
- Rust provider support (
providers/rust): a Go-implemented provider package — builder, unit/integration testers, linter, vulnerability scanner, container publisher — mirroringproviders/go's shape and consumed through the workflow manifest engine above. Proven standalone (GOWORK=off, no workspace, noreplacedirective) on every push viamake provider-rust-standalone, and via a dedicated git-tag release workflow. - A public, versionable Dagger Module API at the repository root (
dagger call; see.dagger/capabilities.goandCOMPATIBILITY.md). The five core capabilities (Builder/Tester/Artifactor/Deployer/Runner) are wired into a chainablePlan/Executecomposition today, versioned viaContractVersion(currently1.0.0). Two further capabilities,RuntimeInspector/RuntimeUpgrader, are also declared as Dagger Interfaces but not yet wired intoPlan's composition chain. - A GitHub Actions composite action that wraps the CLI.
- A plugin/hook registration system at the infrastructure level.
Planned / evolving
- One unified pipeline/step abstraction (two structurally similar
Pipelineinterfaces exist internally today, bridged by an adapter). - Typed artifacts between steps (today steps communicate through struct fields and host paths).
- Reusable step composition — configuring, disabling, replacing, or inserting steps without forking Shipwright.
- An additional language toolchain (Java) — not implemented today (Rust ships today, see above).
- Wiring
RuntimeInspector/RuntimeUpgraderinto the Dagger Module API'sPlan/Executecomposition chain. - Build-once/promote artifact handling and an explicit Git-lifecycle (feature/develop/release/main/hotfix) model.
- GitLab CI and Jenkins integration with parity to the GitHub Actions path.
See docs/PRD.md for the full product vision, current-state detail, and roadmap.
Shipwright ships as a single binary whose only entrypoint is a declarative
workflow manifest (shipwright.dev/v1 schema). It executes steps against
a Dagger-provisioned environment.
# Build from source
git clone https://github.com/pablogore/shipwright.git
cd shipwright
make build
# Run every step in a workflow manifest
./shipwright --workflow path/to/workflow.yaml
# Run a single step (and its needs-transitive dependencies)
./shipwright --workflow path/to/workflow.yaml --step test
# List the steps declared in a manifest instead of executing them
./shipwright --workflow path/to/workflow.yaml --list-steps
# Select which branch predicate conditional steps evaluate against
./shipwright --workflow path/to/workflow.yaml --branch mainA missing or invalid manifest fails closed with an explicit error — there is
no fallback pipeline to run instead. --workflow, --step, --list-steps,
and --branch are the flags that actually affect a workflow run; see
shipwright --help for the full flag set, but note that several flags in
that list (--executor, --local, --env, --coverage, --git-ref,
--git-auth, --config/.shipwright.yml) are parsed but currently have no
effect on --workflow execution — everything a workflow needs (source,
secrets, variables, per-step options) is declared in the manifest itself.
git clone https://github.com/pablogore/shipwright.git
cd shipwright
go mod download
make build # builds ./shipwright
make test # go test -race ./...
make lint # golangci-lintRequires Go 1.26 (see go.mod / .go-version) and Docker, since workflow
steps run via Dagger.
Compiled release binaries for Linux/macOS/Windows (amd64/arm64) are published on the GitHub Releases page.
A composite action wraps the CLI so provider YAML stays a thin trigger:
- uses: actions/checkout@v4
- uses: ./.github/actions/shipwright
with:
workflow: .shipwright/workflow.yaml
step: test
branch: developSee examples/github-actions for complete workflow examples.
GitHub Actions / GitLab CI / Jenkins / Local
|
v
Shipwright
|
+-----------+-----------+
| | |
Lifecycle* Pipeline Toolchain*
| | |
+-----------+-----------+
|
Dagger
|
v
reproducible execution
* marks target components that do not exist as standalone abstractions
yet — Lifecycle and Toolchain are goals of the ongoing architectural
evolution, not shipped concepts. Pipeline exists today but as two
overlapping internal interfaces rather than one unified model. Dagger is
already the real execution substrate for the workflow manifest engine's
container-based steps.
Verified against the repository:
- Declarative workflow manifests (
--workflow,shipwright.dev/v1schema) composing registered Go and Rust providers per step: test with coverage threshold,golangci-lint/clippylinting,govulncheck/cargo-auditvulnerability scanning, binary and/or container image build, and toolchain-driftruntime-inspect/runtime-upgrade. - A public, versionable Dagger Module API at the repository root (
dagger call,.dagger/capabilities.go) exposingBuilder/Tester/Artifactor/Deployer/Runneras chainable Dagger Interfaces viaPlan/Execute— seeCOMPATIBILITY.mdfor the exact guaranteed surface. - Dagger-provisioned execution for workflow steps.
- Plugin registry/loader and a hook manager at the infrastructure layer
(one built-in plugin,
nomad-deploy); pipelines do not yet invoke before/after hooks. - GitHub Actions composite action and example workflows.
- Dagger-based multi-platform release builds, packaging, and checksums, published via GitHub CLI.
internal/pipelines/ still contains the original go-service and infra
pipeline implementations (setup/test/lint/scan/build/package/tag/push logic
predating the workflow manifest engine). They are not invocable from the
current CLI — the --pipeline flag and preset registry that used to
dispatch to them were removed, and main.go's only entrypoint is
--workflow. The code remains in the tree as history/reference, not as a
supported delivery path.
High-level themes (see docs/PRD.md §22 for detail):
- Wire
RuntimeInspector/RuntimeUpgraderinto the Dagger Module API'sPlan/Executecomposition chain (both capabilities exist today but are not yet chained) - Unified pipeline/step model (retire the duplicate
Pipelineinterfaces) - Typed artifacts between steps
- Pipeline composition: configure, disable, add, replace, insert steps
- Additional polyglot toolchain: Java (Rust ships today via
providers/rust) - Explicit Git-lifecycle engine (feature/develop/release/main/hotfix)
- Build-once, promote: immutable release artifacts
- Provider-neutral integrations (GitLab CI, Jenkins) with GitHub Actions parity
- Reproducibility: eliminate mutable
latestdependencies, pin toolchain versions - Structured, queryable execution observability
make build # build the shipwright binary
make test # go test -race ./...
make lint # golangci-lint
make coverage # coverage report with threshold validationProject layout:
shipwright/
├── main.go # CLI entry point
├── internal/
│ ├── app/ # DI container, executors, plugin/hook wiring
│ ├── config/ # configuration loading and validation
│ ├── executors/ # native and Docker/Dagger execution
│ ├── interfaces/ # shared interfaces
│ ├── pipelines/ # legacy pipeline implementations (go-service, infra) -- not invocable from the CLI
│ └── plugins/ # plugin/hook system
├── examples/ # usage examples (GitHub Actions, Jenkins, local)
└── docs/ # documentation
- Product Requirements Document — canonical product vision, current-state detail, target architecture, and roadmap
- Architecture Guide
- Local Usage Guide
- Pipeline Development
- Configuration Reference
- API Reference
- Release Process
- Examples