Contributing to Portwing

July 11, 2026 · View on GitHub

Thanks for your interest in contributing! Whether it is a bug fix, new feature, documentation improvement, or something else — all contributions are welcome.

Questions or help? Open an issue.

Getting started

  1. Fork the repository and clone your fork.

  2. Install Go 1.26+:

    go version  # should be 1.26+
    
  3. Download dependencies:

    go mod download
    
  4. Create a branch from main. Portwing uses a trunk-based flow: both bug fixes and features branch from and merge back into main (there is no long-lived dev/* branch).

Development loop

go build ./...                  # Build
go test -race ./...             # All tests with race detector
gofmt -l .                      # List unformatted files (must be empty)
golangci-lint run               # Lint
go vet ./...                    # Vet

Running integration tests

Integration tests require a running Docker daemon:

go test -tags=integration -race -timeout=10m ./internal/integration/

Drydock compatibility

A compatibility verification script is included:

# Verify protocol compatibility with the Drydock platform
./scripts/drydock-compat-check.sh

Fuzz testing (Tier 0 smoke)

Each fuzz target runs for 5 seconds locally:

go test -run=^$ -fuzz=^FuzzParsePHC$           -fuzztime=5s ./internal/server/
go test -run=^$ -fuzz=^FuzzParseTrustedProxies$ -fuzztime=5s ./internal/server/
go test -run=^$ -fuzz=^FuzzParseImageRef$       -fuzztime=5s ./internal/adapter/
go test -run=^$ -fuzz=^FuzzParseLabels$         -fuzztime=5s ./internal/adapter/drydock/
go test -run=^$ -fuzz=^FuzzMCPHandler$          -fuzztime=5s ./internal/mcp/
go test -run=^$ -fuzz=^FuzzEnvelope$            -fuzztime=5s ./internal/protocol/

Code style

  • Formatter: gofmt (enforced by CI)
  • Linter: golangci-lint
  • Follow Effective Go conventions
  • Line length: no hard limit; use judgment
  • Zero new dependencies: stdlib + golang.org/x/crypto + github.com/google/uuid + github.com/gorilla/websocket. PRs adding deps require a strong justification.

Commit convention

We use Gitmoji + Conventional Commits:

<emoji> <type>(<scope>): <description>
EmojiTypeUse
featNew feature
🐛fixBug fix
📝docsDocumentation
🎨styleFormatting only
🔄refactorRefactor (no feature/fix)
🧪testTests
📦depsDependencies
🔧configConfiguration / tooling
🚀deployDeployment / release
🗑️removeRemoving code/files

Multi-change commits: lead emoji+type on first line, bulleted sub-changes in body. Reference Linear issues in footer as Fixes: LIN-XXX.

Pull request guidelines

  • Target main for all PRs (bug fixes and features alike).
  • Keep PRs focused — one feature or fix per PR.
  • Include tests for non-trivial changes.
  • Update CHANGELOG.md under [Unreleased] for user-visible changes.
  • All CI checks must pass before merge.

Security

Please report security vulnerabilities privately via GitHub Security Advisoriesdo NOT open a public issue. See SECURITY.md for the full policy.