Contributing to Osmia¶
Thank you for your interest in contributing to Osmia! This document provides guidelines and information for contributors.
Code of Conduct¶
This project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
Getting Started¶
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/osmia.git - Install git hooks:
./hack/install-hooks.sh - Create a feature branch:
git checkout -b feat/my-feature - Make your changes
- Commit with a conventional commit message
- Push and open a pull request (hooks run lint and tests automatically)
Development Prerequisites¶
- Go 1.23+
- Docker (for container builds)
kind(for local Kubernetes clusters)kubectl(for cluster interaction)helm(for chart deployment)gofumpt(for code formatting)golangci-lint(for linting)buf(for protobuf linting and generation)
Install development dependencies:
Git Hooks¶
Install the recommended git hooks after cloning:
This installs a pre-push hook that runs golangci-lint and go test -race ./... before every push, catching lint errors and test failures locally before they reach CI.
Local Development Workflow¶
Osmia uses kind for local development and testing. The full workflow is automated via Make targets:
# Verify all prerequisites are installed
make check-prereqs
# Full setup: build the controller binary, build the controller image,
# create the kind cluster, and deploy the local-dev profile
make local-up
# Stream controller logs
make logs
# Run end-to-end smoke tests
make e2e-test
# Fast rebuild and redeploy (reuses existing cluster)
make local-redeploy
# Tear everything down
make local-down
The local-up target creates a two-node kind cluster (control-plane + worker),
builds the controller image with a dev tag, loads it into kind, and deploys
the Helm chart with local-dev overrides. The local-dev profile disables image
pulls and leader election, exposes the controller HTTP endpoint on
localhost:30080 for /healthz, /readyz, and /metrics,
and uses the noop ticketing backend so the controller starts without external
credentials. Use make live-up when you want to exercise real ticketing
backends and engine containers.
Code Style¶
- Run
gofumpton all Go files before committing - Run
golangci-lint runand fix all warnings - Use British English in comments, documentation, and error messages
- Follow standard Go project layout conventions
- All exported types, functions, and methods must have doc comments
- Prefer table-driven tests with subtests
Commit Messages¶
We use Conventional Commits:
feat:— new featurefix:— bug fixdocs:— documentation onlytest:— adding or updating testsrefactor:— code change that neither fixes a bug nor adds a featurechore:— maintenance tasks
Pull Requests¶
- Keep PRs focused — one logical change per PR
- Update documentation as needed
- Add an entry to
CHANGELOG.mdunder "Unreleased" - Ensure CI passes before requesting review
Dev Releases (Edge Deployments)¶
Every push to main automatically publishes:
- Edge container images tagged
main(andsha-<hash>) toghcr.io - An edge Helm chart versioned
0.0.0-edgeto the same GitHub Pages repo
The 0.0.0-edge chart is always overwritten with the latest main commit. Its
appVersion is set to the full git SHA so you can trace exactly which commit is
running.
Consuming the edge chart¶
helm repo add osmia https://unitaryai.github.io/osmia
helm repo update
# Inspect the dev chart (--devel required for pre-release versions)
helm show chart osmia/osmia --version 0.0.0-edge --devel
# Install/upgrade with the edge chart
helm upgrade --install osmia osmia/osmia \
--version 0.0.0-edge --devel \
--set image.tag=main \
--set image.pullPolicy=Always
Switching ArgoCD between dev and release mode¶
Dev mode — track main continuously (no semver release needed):
# kustomization.yaml
version: 0.0.0-edge
# values.yaml
image:
tag: "main"
pullPolicy: Always
engines:
claude-code:
image: ghcr.io/unitaryai/osmia/engine-claude-code:main
Release mode — pin to a specific semver release:
# kustomization.yaml
version: X.Y.Z
# values.yaml
image:
tag: "X.Y.Z"
pullPolicy: IfNotPresent
# remove engines.claude-code.image override (uses chart default)
Dev vs full release¶
| Situation | Use |
|---|---|
| Iterating on a fix — chart templates, RBAC, deployment config | Dev edge |
| Sharing a fix with external users or documenting in CHANGELOG | Full semver release |
| Testing a new feature before it's ready to announce | Dev edge |
| Stable, versioned deployment you can roll back to by number | Full semver release |
Manual dev build¶
You can trigger the edge image + chart build without pushing to main via the
GitHub Actions UI: go to Actions → Build and push edge images → Run workflow.
Releasing¶
Osmia uses git tags to trigger the release pipeline. The release.yaml workflow
builds container images and publishes the Helm chart to the GitHub Pages
repository (https://unitaryai.github.io/osmia).
Release checklist¶
- Ensure
mainis clean — all PRs merged, CI passing. - Decide the version — follow Semantic Versioning:
- Patch (
x.y.Z) for bug fixes - Minor (
x.Y.0) for new features (backward-compatible) - Major (
X.0.0) for breaking changes - Stamp
CHANGELOG.md— move the[Unreleased]section to a new[x.y.z] - YYYY-MM-DDheading. Add a fresh empty[Unreleased]above it. - Bump
charts/osmia/Chart.yaml— set bothversionandappVersionto the new version (without thevprefix). Thechart-releaser-actionuses this to decide whether to publish; if it matches an already-published version the chart release is silently skipped. - Commit —
chore: release vX.Y.Z - Tag —
git tag vX.Y.Z - Push both —
git push && git push origin vX.Y.Z - Verify the release pipeline — check GitHub Actions for:
- Container images built and pushed to
ghcr.io - Images signed with cosign
- Helm chart published to the
gh-pagesbranch - Verify ArgoCD (if applicable) — confirm the new chart version is
available:
helm repo update && helm search repo osmia
Common mistakes¶
- Forgetting
Chart.yaml— the most common failure. IfversioninChart.yamlisn't bumped, the chart-releaser sees the version already exists in thegh-pagesindex and skips publishing. Container images are built but the Helm chart is not released. - Tag without pushing main — the tag must point to a commit that is on
main(or at least pushed to the remote), otherwise the release workflow checks out stale code.
Plugin Contributions¶
If you're building a plugin, see the Writing a Plugin guide.
Licence¶
By contributing, you agree that your contributions will be licensed under the Apache License 2.0.