Reusable CI/CD workflows, composite actions, and Taskfile modules for Solti repositories.
Consumer repositories keep their project-specific commands and release configuration. This repository owns the shared GitHub Actions machinery and toolchain containers.
| Quick start | Workflows | Actions | Taskfiles |
| Component | Location | Used from |
|---|---|---|
| Reusable workflows | .github/workflows/ |
A caller workflow job through uses |
| Composite actions | <name>/action.yml |
A workflow step through uses |
| Taskfile modules | taskfiles/ |
A repository Taskfile.yml through includes |
Workflows and actions use the v1 tag.
Remote Taskfile includes should use the same tag.
The Taskfile modules run tools inside versioned images from soltiHQ/images:
| Module | Image | Version source |
|---|---|---|
| Rust | ghcr.io/soltihq/ci/rust:<version> |
Root Cargo.toml rust-version |
| Go | ghcr.io/soltihq/ci/golang:<version> |
Root go.mod go directive |
| Proto | ghcr.io/soltihq/ci/proto:<version> |
buf_version, defaulting to 1.50.0 |
CI refreshes the selected image before each task. Local runs reuse an existing image and pull it when missing.
A Rust repository exposes its own ci/* tasks through Taskfile.yml:
version: '3'
includes:
rust:
taskfile: https://raw.githubusercontent.com/soltiHQ/actions/v1/taskfiles/rust/Taskfile.yml
tasks:
ci/fmt:
cmds:
- task: rust:fmt
ci/check:
cmds:
- task: rust:check
vars: { CHECK_ARGS: '--all-targets --all-features --locked' }The pull-request workflow delegates CI to the shared workflow:
name: PR
on:
pull_request:
jobs:
ci:
uses: soltiHQ/actions/.github/workflows/rust-ci.yml@v1For a Cargo workspace, enable workspace-specific checks:
jobs:
ci:
uses: soltiHQ/actions/.github/workflows/rust-ci.yml@v1
with:
workspace: trueThe branch-protection check is ci / gate when the caller job is named ci.
| Workflow | Purpose |
|---|---|
rust-ci.yml |
Validate a Rust package or workspace |
rust-release.yml |
Publish one crate and create one GitHub release |
rust-workspace-release.yml |
Publish workspace crates in dependency order and create one release |
label-check.yml |
Require a changelog label declared in .github/release.yml |
TODO: fix it; Both Rust release workflows install
protocbefore Cargo verifies and publishes package tarballs.
rust-ci.yml calls the consumer repository's ci/* tasks.
The shared workflow owns job isolation, caching, matrices, and the final gate.
| Job | Consumer task or behavior |
|---|---|
fmt |
ci/fmt |
MSRV |
ci/check |
unittest |
ci/test-unit |
integration |
ci/test-integration |
clippy |
ci/clippy FEATURE=<configuration> |
audit |
ci/audit |
docs |
ci/docs |
examples-build |
ci/build CRATE=<package> for packages containing examples |
package |
ci/package when workspace: true |
preflight |
Advisory ci/publish-dry-run; not included in the final gate |
gate |
Require every non-advisory CI dependency to succeed |
Package repositories test none, every declared feature, and all in separate Clippy jobs.
Workspace repositories test none and all across the workspace.
A workspace can add focused package configurations:
[workspace.metadata.ci]
clippy-matrix = [
{ package = "my-crate", features = ["feature-a", "feature-b"] },
]Each entry must name an existing workspace package and existing features.
label-check.yml reads allowed changelog and exclusion labels from the caller's .github/release.yml.
The pull request must carry at least one of them.
jobs:
label-check:
uses: soltiHQ/actions/.github/workflows/label-check.yml@v1The branch-protection check is label-check / required when the caller job is named label-check.
rust-release.yml verifies that the tagged commit belongs to main and that package.version matches the tag.
It then publishes the crate and creates a GitHub release.
jobs:
publish:
uses: soltiHQ/actions/.github/workflows/rust-release.yml@v1
with:
crate: my-crate
secrets:
crates-io-token: ${{ secrets.CRATES_IO_TOKEN }}rust-workspace-release.yml reads publishable crates from .github/crates.txt by default.
The tagged commit must belong to default-branch, which defaults to main.
The file must contain every publishable workspace crate exactly once and in dependency order.
Every published crate version must match the tag.
jobs:
publish:
uses: soltiHQ/actions/.github/workflows/rust-workspace-release.yml@v1
with:
crates-file: .github/crates.txt
prepare-task: proto/vendor
allow-dirty: true
secrets:
crates-io-token: ${{ secrets.CRATES_IO_TOKEN }}prepare-task is optional.
Use allow-dirty only when that task creates required package inputs.
| Action | Purpose |
|---|---|
taskfile |
Install Task, export optional variables, and run one repository task |
gate |
Validate the results supplied through toJSON(needs) |
cargo-cache |
Cache .cache/cargo and .cache/target under a caller-provided scope |
cargo-publish |
Publish crates in order, tolerate existing versions, and retry HTTP 429 |
ghcr-build |
Build and publish a multi-platform GHCR image with version and commit tags |
The taskfile action installs Task 3.44.1 by default.
Set its version input to override the binary version.
gate accepts two explicit exceptions:
allowtolerates any result for named jobs;allow-skippedtolerates onlyskippedfor named jobs.
ghcr-build targets linux/amd64 and linux/arm64 by default.
It publishes <tag> and <tag>-sha-<commit>.
The modules provide low-level tasks.
Consumer repositories wrap them with stable, repository-specific commands such as ci/test or proto/vendor.
| Module task | Operation |
|---|---|
fmt |
Check cargo fmt |
check |
Run cargo check |
build |
Build one package selected by CRATE |
clippy |
Run Clippy with warnings denied |
test |
Run Cargo tests |
bench |
Run Cargo benchmarks |
audit |
Run cargo audit |
package-list |
Inspect the package file set for CRATE |
publish-dry-run |
Simulate publishing CRATE |
doc |
Build stable rustdoc with warnings denied |
docs |
Emulate the docs.rs nightly rustdoc build |
image/pull |
Refresh the selected Rust image |
fmt/fix |
Apply cargo fmt |
audit/fix |
Apply supported cargo audit fix changes |
Argument variables such as CHECK_ARGS, CLIPPY_ARGS, and TEST_ARGS let the consumer define its exact repository policy.
includes:
go:
taskfile: https://raw.githubusercontent.com/soltiHQ/actions/v1/taskfiles/go/Taskfile.yml
tasks:
ci/test:
cmds:
- task: go:test
ci/lint:
cmds:
- task: go:golangci| Module task | Operation |
|---|---|
gofumpt |
Check tracked Go files |
golangci |
Run golangci-lint |
build |
Build a named binary for the selected GOOS and GOARCH |
govulncheck |
Run Go vulnerability analysis |
test |
Run Go tests |
proto |
Generate protobuf sources with Buf |
templ |
Generate templ sources |
tailwindcss |
Build CSS from required INPUT and OUTPUT paths |
tidy |
Run go mod tidy |
vendor |
Run go mod vendor |
fmt |
Apply gofumpt |
image/pull |
Refresh the selected Go image |
includes:
proto:
taskfile: https://raw.githubusercontent.com/soltiHQ/actions/v1/taskfiles/proto/Taskfile.yml
tasks:
ci/lint:
cmds:
- task: proto:lint| Module task | Operation |
|---|---|
lint |
Run buf lint |
build |
Compile the schema with buf build |
format |
Check every .proto file with clang-format |
breaking |
Compare against .git#branch=main or an explicit AGAINST |
format/fix |
Apply clang-format |
image/pull |
Refresh the selected Proto image |
Code generation remains a consumer responsibility. The Proto module validates the schema.
taskfiles/helpers/Taskfile.yml provides two internal building blocks:
download/filedownloads one missing file;proto/vendorchecks out a selectedsoltiHQ/protorevision and replaces mapped destination trees.
Consumers decide the protobuf revision and source-to-destination mappings.
Use @v1 for workflows and composite actions.
Use /v1/ in raw Taskfile URLs.
Moving the v1 tag updates every consumer on its next run.
Test shared changes from an explicit branch or commit before moving the tag.
Toolchain image versions are independent from the actions revision.
They come from Cargo.toml, go.mod, or the explicit Proto setting.
Issues and pull requests are welcome.
Changes to reusable workflows, actions, and Taskfile modules affect their consumers independently. Test the boundary being changed from a representative caller repository.
Read the contributing guide before a large change.