Development
Local development requires Go.
Source Checkout Runtime
Load .envrc when running Taxiway from the checkout:
source .envrc
It sets:
export TAXIWAY_CONTEXT=dev
export TAXIWAY_CONTEXT_ID="$(test -f "$PWD/.context-id" || uuidgen | tr '[:upper:]' '[:lower:]' | cut -c1-8 > "$PWD/.context-id"; cat "$PWD/.context-id")"
export TAXIWAY_AUTH_DIR="$PWD/.auth"
export TAXIWAY_OBSERVABILITY_DIR="$PWD/.observability"
export TAXIWAY_PROXY_DIR="$PWD/.proxy"
export TAXIWAY_RUNTIME_DIR="$PWD"
export TAXIWAY_LAB_STATE_DIR="$PWD/.lab-state"
These values make ./taxiway and go run ./cmd/taxiway use runtime assets
from the checkout, keep lab state in ./.lab-state, and create an isolated
dev runtime under ./.auth, ./.observability, and ./.proxy. The context id
is generated once into ./.context-id so two local checkouts do not reuse the
same Docker Compose project or gateway container, and so moving the checkout
does not change the environment id.
Optional: use direnv to load .envrc automatically.
Build
go build -o ./taxiway ./cmd/taxiway
./taxiway version
The Makefile target builds all packages:
make build
Test
make test-unit
make lint
Docker-backed end-to-end tests require Docker and are intended for local, scheduled, or manually triggered validation:
make test-e2e
Use make test-e2e-only to run only end-to-end tests.
Use make test-e2e-claude-code, make test-e2e-codex, or
make test-e2e-gastown to run one orchestrator integration.
Use the *-up variants, followed by the *-prepare-run variants, before the
*-phase-by-phase variants when debugging the scheduled orchestrator end-to-end
sequence locally.
Use make test-scripts to run shell script tests.
Commit Messages
Release notes are generated by GoReleaser from commit subjects, so commits must follow Conventional Commits:
<type>[(scope)][!]: <description>
Examples:
feat: add a new capability
feat(record): support explicit window sizing
fix: correct broken behavior
cleanup: remove obsolete behavior
docs: update documentation
What appears in the release notes
GoReleaser sorts each commit into a section by matching its subject, in this order (the first match wins):
| Section | Matched subjects |
|---|---|
| Features | feat:, feat(scope):, feat!: |
| Fixes | fix:, fix(scope):, fix!: |
| Cleanup | any subject containing cleanup, remove, simplif, or polish (e.g. cleanup:) |
A feat:/fix: prefix takes precedence over the Cleanup keywords, so
fix: remove race lands under Fixes.
The following are excluded from the release notes — use them for changes
that should not appear in a release: docs:, test: / tests:, chore:,
style:, refactor:, merge commits, and reverts.
A commit matching no section and no exclusion is not grouped, so always use one of the types above.
If a pull request is squash-merged, the squash commit subject (the PR title by default) is what GoReleaser reads — give the PR a Conventional Commits title.
Local Snapshot
To test the same packaging path as a release, build a GoReleaser snapshot and copy the platform binary back into the repository:
make snapshot
Snapshot builds are local-only and include the current commit in the version,
for example 0.1.0-SNAPSHOT-2f1183a.
Local Completion
Generate completion for the local development binary:
make completion
You can also target a shell explicitly:
make completion-zsh
make completion-bash
make completion-fish
Release
See Release.