Contributing
This page covers the development workflow from filing an issue through to a released version.
Issues
Section titled “Issues”Issues use plain descriptive titles. The issue type is captured by the TYPE field (set via the template picker), not by title prefixes or labels.
Good: ICMP availability indicator on hosts page
Bad: feat: ICMP availability indicator on hosts page
Bad: ✨ ICMP availability indicator on hosts page
Issue types
Section titled “Issue types”When you open an issue, pick one of three templates: Bug, Feature, or Task. The TYPE field is set automatically based on your choice.
| Issue type | Maps to PR prefix | Use for |
|---|---|---|
| Bug | fix: | Something is broken or incorrect |
| Feature | feat: | New capability or enhancement |
| Task | chore:, refactor:, test:, perf:, ci:, docs: | Maintenance, cleanup, docs, or improvement work |
| Epic | (grouping) | A collection of related issues |
Labels
Section titled “Labels”Labels are orthogonal to the type field. Use them for component scope and workflow signals, not to classify the kind of work.
| Category | Labels | Purpose |
|---|---|---|
| Component | web, backend | Where the work happens |
| Cross-cutting | architecture, security, ci | Flags special review or handling |
| CI trigger | build, scan, test | Triggers specific CI workflows |
Add component labels when the scope is clear.
Branches
Section titled “Branches”Branch from main. Name branches descriptively:
feat/icmp-availabilityfix/dark-theme-readonlychore/update-dependenciesThe prefix is optional but helps with at-a-glance identification.
Commits
Section titled “Commits”Local commit messages during development are flexible. They will be squashed on merge, so commit freely during development.
Pull requests
Section titled “Pull requests”PR titles must follow Conventional Commits format:
<type>: <description>Allowed types: feat, fix, docs, ci, chore, refactor, test, perf
Examples:
feat: add ICMP availability indicator to hosts pagefix: active-readonly CSS override in dark themedocs: add contributing workflow guideci: enable multi-architecture builds
PR titles are validated by CI (pr-title.yml). The description must start with a lowercase letter.
Scopes are optional but can be used for clarity: fix(web): readonly field color in dark theme.
Merging
Section titled “Merging”All PRs merge via squash merge. The PR title becomes the commit message on main. This gives us a clean, linear history where every commit on main is a self-contained, conventional-commit-formatted change.
Because of squash merge, the PR title is the only commit message that matters for release automation. Write it carefully.
Releases
Section titled “Releases”Releases are fully automated by semantic-release. When a squash-merge commit lands on main:
| PR type prefix | Release effect |
|---|---|
feat: | Minor version bump (0.1.0) |
fix: | Patch version bump (0.0.1) |
docs:, ci:, chore:, refactor:, test:, perf: | No release |
Breaking changes trigger a major bump. Add BREAKING CHANGE: in the PR body (not the title) to signal this.
See Release Strategy for details on image tagging, promotion, and required secrets.
Summary
Section titled “Summary”Issue (plain title + TYPE field: Feature) → Branch (feat/description) → PR (feat: description) → Squash merge (feat: description (#123)) → semantic-release (minor bump → v0.2.0)The type is expressed once at each stage, in the format native to that stage: a structured field on issues, a conventional commit prefix on PRs and commits, a semver bump on releases. No duplication, no ambiguity.