Ways of Working
Development Workflow
Development is agent-first — every change starts as a structured issue and flows through issue → plan → implement → test → review:
- Create an issue using the devantler-tech/.github issue templates:
- Feature — user story with acceptance criteria.
- Bug — expected vs actual behavior with reproduction steps.
- Chore — user story with acceptance criteria for general tasks.
- Kata — Improvement Kata for continuous improvement (problem → definition of awesome → target condition → actions).
- Plan — create a structured implementation plan from the issue before writing code.
- Implement — execute the plan following the practices in this skill (TDD, quality gates, GitHub Flow, CI/CD).
- Manual test — validate behavior hands-on before merging. Focus on UX: output must be well-presented and every piece of feedback (errors, warnings, prompts) must be actionable.
- Code review (optional) — CI's strict linting, scanning, and quality gates are the primary feedback loop, so manual review is not always required.
Testing
Follow the test-driven-development skill rigorously — write the test first, watch it fail, write minimal code to pass.
Application / Library Repositories
| Type |
Tooling |
When to run |
| Linting |
Linters and linting runners (e.g. golangci-lint, eslint, MegaLinter) |
CI on every PR |
| Scanning |
Security & quality scanners (e.g. CodeQL, Trivy, SonarQube) |
CI on every PR |
| Unit tests |
SDK test frameworks (e.g. go test, xunit, jest) |
CI on every PR |
| Integration tests |
SDK test frameworks |
CI on every PR |
| E2E / system tests |
GitHub Actions workflows that exercise the app/binary/service as an end user would |
CI on every PR; move to merge_group if the suite becomes too heavy |
| Benchmark tests |
SDK benchmark frameworks (e.g. BenchmarkDotNet, go test -bench) |
CI on every PR |
Platform / Kubernetes Repositories
For platform engineering work, ksail provides the build → run → publish loop and Testkube runs the actual test suites inside the cluster:
| Type |
Tooling |
What it does |
| Linting |
Manifest linters (e.g. kubeconform, kube-linter) |
Validate manifests statically — no cluster needed |
| Scanning |
Security scanners (e.g. Trivy) |
Scan manifests and images for vulnerabilities — no cluster needed |
| Integration tests |
Ephemeral local cluster (ksail cluster create) + Testkube |
Spin up a Docker cluster, deploy workloads, and run Testkube test suites against them |
| E2E / system tests |
Ephemeral or real cluster + Testkube |
Deploy to a full environment (local or remote) and run end-to-end Testkube test suites |
Platform lifecycle commands:
| Command |
Purpose |
ksail cluster init |
Scaffold a new cluster configuration |
ksail cluster create |
Spin up the cluster locally (Docker) or on real infrastructure and verify workloads reconcile |
ksail workload push |
Push Kubernetes manifests as OCI artifacts to a container registry |
Code Quality Gates (CI)
Every pull request must pass all linting and scanning checks defined in the Testing section. For application / library repositories, additionally:
- No code coverage regression — coverage must not decrease compared to the base branch.
- No benchmark regression — benchmark results must not regress compared to the base branch.
Problem Solving
- Fix at the root cause — never patch symptoms. Trace every bug or failure to its origin and fix it there.
- Workarounds are always temporary — if a workaround is unavoidable, mark it clearly (e.g.
// WORKAROUND: comment with a linked issue) and schedule its removal.
- Upstream first — when a fix belongs in a dependency or upstream project, contribute it there. Only carry a local patch until the upstream change is released.
Libraries
Prefer popular, well-maintained third-party libraries over writing custom implementations. Only roll your own when no suitable library exists or when the dependency would be disproportionately heavy.
Refactoring & Design
Follow https://refactoring.guru guidelines for refactoring techniques and design patterns.
Branching & Flow
Use GitHub Flow:
- Create a feature branch from
main.
- Open a pull request.
- Pass all CI checks.
- Merge via merge queue (
merge_group) when the repository is configured for it; otherwise merge the pull request normally.
CI/CD Pipeline
Each repository has two core workflow files — ci.yaml and cd.yaml — plus a thin release.yaml that calls a reusable workflow (see Releases). Reusable logic is extracted into local GitHub Actions under .github/actions/:
- Composite actions — for simple, self-contained steps.
- TypeScript actions — for anything complex, because they are locally testable and avoid hard-to-read bash embedded in YAML.
Application / Library Repositories
| Event |
What runs |
pull_request |
Linting, scanning, unit tests, integration tests, E2E tests, benchmarks, coverage & benchmark regression checks. Move E2E to merge_group only if the suite becomes too heavy. |
merge_group |
CD to dev environment. |
push to main |
Publish artifacts (packages, container images, etc.). |
Semver tag (vX.X.X) |
CD to prod environment. |
Platform / Kubernetes Repositories
| Event |
What runs |
pull_request |
Linting, scanning, integration tests on an ephemeral local cluster (ksail cluster create + Testkube). Move integration tests to merge_group if the suite becomes too heavy. |
merge_group |
CD to dev — deploy to staging infrastructure (e.g. Hetzner). |
Semver tag (vX.X.X) |
CD to prod — ksail cluster update, ksail workload push, ksail workload reconcile. |
Releases
Releases are automated via the devantler-tech/actions/.github/workflows/create-release.yaml reusable workflow. It runs semantic-release on push to main, calculates the next semver from conventional commit history, and creates the tag + GitHub release — which in turn triggers the CD pipeline above.
For application publishing, always use upstream releasers — e.g. GoReleaser for Go or dotnet-releaser for .NET — rather than hand-rolling publish scripts.
Data-Driven Improvement
- Use benchmarking data to guide performance improvements — don't optimise without numbers.
- Use code coverage data to guide where to add tests — target uncovered paths, not a vanity percentage.
Reference Implementations
- devantler-tech/ksail — Go CLI built with TDD, full CI/CD pipeline, benchmarks, and E2E system tests in GitHub Actions.
- devantler-tech/platform — Kubernetes platform using ksail for init → create → push OCI workflow, with progressive CI (Docker → Hetzner staging → Hetzner prod).
1---2name: ways-of-working-23description: Codifies devantler-tech engineering practices: agent-first development workflow, TDD, CI/CD pipelines, GitHub Flow, code quality gates, and Kubernetes workflows with ksail. Use when filing issues, planning work, setting up projects, configuring CI/CD, writing tests, debugging, or making architectural decisions.4license: Apache-2.05---67# Ways of Working89## Development Workflow1011Development is agent-first — every change starts as a structured issue and flows through issue → plan → implement → test → review:12131. **Create an issue** using the [devantler-tech/.github issue templates](https://github.com/devantler-tech/.github/tree/main/.github/ISSUE_TEMPLATE):14 - **Feature** — user story with acceptance criteria.15 - **Bug** — expected vs actual behavior with reproduction steps.16 - **Chore** — user story with acceptance criteria for general tasks.17 - **Kata** — Improvement Kata for continuous improvement (problem → definition of awesome → target condition → actions).182. **Plan** — create a structured implementation plan from the issue before writing code.193. **Implement** — execute the plan following the practices in this skill (TDD, quality gates, GitHub Flow, CI/CD).204. **Manual test** — validate behavior hands-on before merging. Focus on UX: output must be well-presented and every piece of feedback (errors, warnings, prompts) must be actionable.215. **Code review** (optional) — CI's strict linting, scanning, and quality gates are the primary feedback loop, so manual review is not always required.2223## Testing2425Follow the [test-driven-development](https://github.com/obra/superpowers/tree/main/skills/test-driven-development) skill rigorously — write the test first, watch it fail, write minimal code to pass.2627### Application / Library Repositories2829| Type | Tooling | When to run |30|------|---------|-------------|31| **Linting** | Linters and linting runners (e.g. `golangci-lint`, `eslint`, `MegaLinter`) | CI on every PR |32| **Scanning** | Security & quality scanners (e.g. CodeQL, Trivy, SonarQube) | CI on every PR |33| **Unit tests** | SDK test frameworks (e.g. `go test`, `xunit`, `jest`) | CI on every PR |34| **Integration tests** | SDK test frameworks | CI on every PR |35| **E2E / system tests** | GitHub Actions workflows that exercise the app/binary/service as an end user would | CI on every PR; move to `merge_group` if the suite becomes too heavy |36| **Benchmark tests** | SDK benchmark frameworks (e.g. `BenchmarkDotNet`, `go test -bench`) | CI on every PR |3738### Platform / Kubernetes Repositories3940For platform engineering work, [ksail](https://github.com/devantler-tech/ksail) provides the build → run → publish loop and [Testkube](https://testkube.io/) runs the actual test suites inside the cluster:4142| Type | Tooling | What it does |43|------|---------|--------------|44| **Linting** | Manifest linters (e.g. kubeconform, kube-linter) | Validate manifests statically — no cluster needed |45| **Scanning** | Security scanners (e.g. Trivy) | Scan manifests and images for vulnerabilities — no cluster needed |46| **Integration tests** | Ephemeral local cluster (`ksail cluster create`) + Testkube | Spin up a Docker cluster, deploy workloads, and run Testkube test suites against them |47| **E2E / system tests** | Ephemeral or real cluster + Testkube | Deploy to a full environment (local or remote) and run end-to-end Testkube test suites |4849Platform lifecycle commands:5051| Command | Purpose |52|---------|---------|53| `ksail cluster init` | Scaffold a new cluster configuration |54| `ksail cluster create` | Spin up the cluster locally (Docker) or on real infrastructure and verify workloads reconcile |55| `ksail workload push` | Push Kubernetes manifests as OCI artifacts to a container registry |5657## Code Quality Gates (CI)5859Every pull request **must** pass all linting and scanning checks defined in the [Testing](#testing) section. For application / library repositories, additionally:6061- **No code coverage regression** — coverage must not decrease compared to the base branch.62- **No benchmark regression** — benchmark results must not regress compared to the base branch.6364## Problem Solving6566- **Fix at the root cause** — never patch symptoms. Trace every bug or failure to its origin and fix it there.67- **Workarounds are always temporary** — if a workaround is unavoidable, mark it clearly (e.g. `// WORKAROUND:` comment with a linked issue) and schedule its removal.68- **Upstream first** — when a fix belongs in a dependency or upstream project, contribute it there. Only carry a local patch until the upstream change is released.6970## Libraries7172Prefer popular, well-maintained third-party libraries over writing custom implementations. Only roll your own when no suitable library exists or when the dependency would be disproportionately heavy.7374## Refactoring & Design7576Follow <https://refactoring.guru> guidelines for refactoring techniques and design patterns.7778## Branching & Flow7980Use **GitHub Flow**:81821. Create a feature branch from `main`.832. Open a pull request.843. Pass all CI checks.854. Merge via merge queue (`merge_group`) when the repository is configured for it; otherwise merge the pull request normally.8687## CI/CD Pipeline8889Each repository has two core workflow files — `ci.yaml` and `cd.yaml` — plus a thin `release.yaml` that calls a reusable workflow (see [Releases](#releases)). Reusable logic is extracted into local GitHub Actions under `.github/actions/`:9091- **Composite actions** — for simple, self-contained steps.92- **TypeScript actions** — for anything complex, because they are locally testable and avoid hard-to-read bash embedded in YAML.9394### Application / Library Repositories9596| Event | What runs |97|-------|-----------|98| `pull_request` | Linting, scanning, unit tests, integration tests, E2E tests, benchmarks, coverage & benchmark regression checks. Move E2E to `merge_group` only if the suite becomes too heavy. |99| `merge_group` | CD to **dev** environment. |100| `push` to `main` | **Publish** artifacts (packages, container images, etc.). |101| Semver tag (`vX.X.X`) | CD to **prod** environment. |102103### Platform / Kubernetes Repositories104105| Event | What runs |106|-------|-----------|107| `pull_request` | Linting, scanning, integration tests on an ephemeral local cluster (`ksail cluster create` + Testkube). Move integration tests to `merge_group` if the suite becomes too heavy. |108| `merge_group` | CD to **dev** — deploy to staging infrastructure (e.g. Hetzner). |109| Semver tag (`vX.X.X`) | CD to **prod** — `ksail cluster update`, `ksail workload push`, `ksail workload reconcile`. |110111### Releases112113Releases are automated via the [`devantler-tech/actions/.github/workflows/create-release.yaml`](https://github.com/devantler-tech/actions/blob/main/.github/workflows/create-release.yaml) reusable workflow. It runs [semantic-release](https://semantic-release.gitbook.io/) on `push` to `main`, calculates the next semver from [conventional commit](https://www.conventionalcommits.org/) history, and creates the tag + GitHub release — which in turn triggers the CD pipeline above.114115For application publishing, always use upstream releasers — e.g. [GoReleaser](https://goreleaser.com/) for Go or [dotnet-releaser](https://github.com/xoofx/dotnet-releaser) for .NET — rather than hand-rolling publish scripts.116117## Data-Driven Improvement118119- Use **benchmarking data** to guide performance improvements — don't optimise without numbers.120- Use **code coverage data** to guide where to add tests — target uncovered paths, not a vanity percentage.121122## Reference Implementations123124- [devantler-tech/ksail](https://github.com/devantler-tech/ksail) — Go CLI built with TDD, full CI/CD pipeline, benchmarks, and E2E system tests in GitHub Actions.125- [devantler-tech/platform](https://github.com/devantler-tech/platform) — Kubernetes platform using ksail for init → create → push OCI workflow, with progressive CI (Docker → Hetzner staging → Hetzner prod).