Contributing

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.

See Testing and Drivers.

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):

SectionMatched subjects
Featuresfeat:, feat(scope):, feat!:
Fixesfix:, fix(scope):, fix!:
Cleanupany 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.