Development
Hacking on aichteeteapee itself. You need Docker and Make, nothing else. Every target runs inside a pinned dev image built from Dockerfile.dev (Go 1.26.9 plus the linter and scanners), so a local run and CI use the exact same toolchain. The container runs as your user with every capability dropped and the checkout mounted at /work.
Make targets
Run make help for the list. The Makefile has:
| Target | What it does |
|---|---|
make dev-image | Builds the aichteeteapee-dev image. Every other Go target depends on it. |
make dep | go mod tidy and go mod vendor. |
make format | gofmt -w on the Go source, shfmt -w on scripts/*.sh. |
make lint | scripts/lint.sh: shellcheck and shfmt -d on the scripts, fails if go fix -diff ./... suggests anything, then golangci-lint with the rules in .golangci.yml. |
make lint-fix | Applies go fix ./... and runs golangci-lint with --fix. |
make test | go test -race -count=1 -timeout=10m ./.... |
make test-unit | Same as make test. |
make test-coverage | scripts/test-coverage.sh: race tests with a coverage profile, writes the total to coverage-percent.txt, fails below 90 percent. |
make sec | scripts/sec.sh: gitleaks over the working tree and the Git history, govulncheck, and Semgrep (p/golang and p/security-audit). Writes the merged report to sec.sarif and fails on any finding. |
make generate | go generate ./.... Nothing generates code today; CI runs it so a future generator cannot drift. |
make shell | A shell in the dev image, for running one test by hand. |
make docs | Builds this site into .testing/docs-site with GitHub’s own Pages image. |
make all | dep, lint and test. |
pre-commit.sh runs make lint && make test-coverage, the same pair CI runs.
To run one test:
make shell
go test -race -run TestBearerAuth ./serbewr/middleware/
Tooling versions
Go, the Alpine packages, govulncheck and gitleaks are pinned in Dockerfile.dev, the base image by digest and gitleaks by SHA-256. Semgrep and its dependencies are pinned with hashes in requirements-semgrep.txt. golangci-lint is a tool dependency in go.mod and runs from the vendored module tree in vendor/.
The linter config is strict on purpose: 80-column lines, wrapped errors, no magic numbers, no globals without a reason. A //nolint names its linter and says why.
Tests
Tests sit next to the code in the same package and use testify. The ones that start a real server, hub or socket are the *_integration_test.go files; they run in the normal suite. Static file and upload tests read fixtures from serbewr/.fixtures/. Everything runs with the race detector.
CI
.github/workflows/pipeline.yml runs on every push, on any branch, through the shared workflows in psyb0t/reusable-github-workflows.
- A branch push runs
make lint,make test-coverage,make secandmake generate. The runner has Docker and Make; the targets do the rest in the dev image. Thesec.sarifreport goes to the repository’s code scanning tab. - On the default branch, a passing run refreshes the coverage, version, license and imported-by badges on the
badgesbranch. - A
v*tag does not rerun the checks. It waits for the default-branch run of the same commit to pass, then cuts the GitHub release from the annotated tag message and refreshes the badges with that run’s coverage. Push the commit tomainfirst, then the tag. - A weekly scheduled run keeps the imported-by badge current.
Releases
Releases are annotated v* tags on a commit that is already on main, and the tag message becomes the release notes. The version is not written into any file. CHANGELOG.md gets an entry per release, and a change that breaks callers starts its line with Breaking:.
Documentation
This site is the docs/ directory, built by GitHub Pages from main with Jekyll and the just-the-docs theme. Every page needs front matter with a unique title and a description of 50 to 170 characters. Links between pages use the relative .md path; a link to anything outside docs/ uses the full GitHub URL. Code blocks with doubled opening braces, which Go composite literals often have, need the Liquid raw tags around them, or Jekyll tries to run them as templates. make docs builds the site the way Pages does, into a gitignored directory.