Skip to content

Contributing ​

Contributions are welcome. This document describes the workflow.

Prerequisites ​

  • Go 1.26 or newer. go.mod declares the minimum version and preferred toolchain.
  • Git and Make for the commands below.
  • golangci-lint v2.14.0, govulncheck, and shellcheck for lint gates. Install the linter from the official releases.

Unit tests and tests against controlled gRPC servers run with the Go toolchain. The optional BMv2 tests also need Bash, p4c-bm2-ss and a running target. Native mode uses local simple_switch_grpc. Docker mode uses an accessible Docker daemon and an image containing simple_switch_grpc, while compilation still uses local p4c. See script requirements.

Local Setup ​

sh
git clone https://github.com/zhh2001/p4runtime-go-controller.git
cd p4runtime-go-controller
make tidy
make lint
make test

make lint uses Go 1.27.1, matching the lint job in CI. Go downloads that toolchain when needed. Update the Go and linter versions together when changing the lint configuration.

Go toolchain checks ​

The CI build matrix runs Go 1.26 and stable on Ubuntu, macOS and Windows. The 1.26 selector chooses a patch release in that series, which can be newer than the minimum 1.26.0 declared in go.mod. stable follows the latest stable release.

actions/setup-go@v6 sets GOTOOLCHAIN=local. Each CI job uses the installed Go toolchain without switching to the preferred toolchain in go.mod. The setup step prints the actual version and Go environment. Check those logs when comparing results across runs. See Go toolchain selection.

To check the declared minimum locally, use an explicit toolchain name:

sh
GOTOOLCHAIN=go1.26.0 go build ./...
GOTOOLCHAIN=go1.26.0 go vet ./...
GOTOOLCHAIN=go1.26.0 go test -race -covermode=atomic -coverpkg=./... -coverprofile=coverage.out ./...

Replace go1.26.0 with the version shown in a CI run to reproduce that run's toolchain. A bare go command can switch versions because of the preferred toolchain. Adding +auto to an explicit name also allows switching. Minimum-version checks verify compatibility. Use a current patch release for regular builds. The preferred toolchain is Go 1.26.9.

BMv2 integration tests ​

From the repository root, start a native target in one terminal:

sh
./scripts/run-bmv2.sh

In another terminal, run:

sh
make e2e

The launcher and test script each compile a matching L2 P4Info and device config. The test script runs with race detection, which requires CGO and a C compiler supported by the Go toolchain. Use a dedicated target because tests install their pipeline. Docker startup, custom ports and compiler overrides are described in the script guide. Linux Ethernet tests also need bound data interfaces and raw socket permissions. See the integration guide for those tests and their settings.

API documentation ​

Install the documentation generator and add Go's binary directory to PATH:

sh
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@v1.1.0
export PATH="$(go env GOPATH)/bin:$PATH"
make docs

The script writes docs/api-reference.md as an index of all 12 public packages, including codec and pre. Each package has its own page under docs/api/, with a link back to the index. Same-named declarations such as Reader and Subscriber have separate anchors on their package pages. Command, example, internal and integration-test packages are excluded. These are local generated files. Regenerate them after changing exported declarations or their comments.

To check an existing reference without rewriting it, run:

sh
./scripts/gen-docs.sh --check

The script checks each package page separately, then the index. A missing or outdated file produces a nonzero exit status without rewriting any output. Rendering and checking flags are forwarded to gomarkdoc. The script sets the output paths and file templates. Use gomarkdoc directly for a custom layout.

Documentation website ​

Use Node.js 24 or newer. Install the documentation tools and start the local site from the repository root:

sh
npm --prefix docs ci
npm --prefix docs run dev

The site uses VitePress 1.6.4 with Vite 6.4.3 selected through an npm override. Commit docs/package-lock.json when updating dependencies. Check both development and production builds after a tool update.

The source remains in the existing Markdown files. docs/.vitepress/site.mjs maps each source to its website page. The preparation script copies those files into a generated directory, and the Markdown renderer resolves repository links to website pages or GitHub files. Edit the original source. The development server watches those files and refreshes their generated pages. Restart it after changing the page map.

Build the site, check its links and compile complete Go examples against the published SDK:

sh
npm --prefix docs run build
node scripts/check-doc-examples.mjs
npm --prefix docs run preview

The build checks internal links, heading anchors, local assets, page metadata and sitemap URLs under the project base path. Complete Go programs in the site's Markdown are compiled and vetted without a local SDK replacement. Run BMv2 tests for changes to commands, examples or target behavior. The API reference links to the version declared in docs/.vitepress/site.mjs.

Page descriptions and share metadata are defined in docs/.vitepress/metadata.mjs. The share image is docs/public/social-card.png, rendered at 1200 × 630 from docs/public/social-card.svg. Update both files when changing the card. VitePress includes language alternatives in the sitemap for pages with English and Chinese counterparts.

Document typography is defined in docs/.vitepress/theme/typography.css. Body text uses Times New Roman and SimSun from the reader's system, with Songti SC and Noto Serif fallbacks. Paragraphs use an 18px font size and 1.8 line spacing. The home pages, headings, navigation and code keep the default theme's font families. The home page project name uses responsive sizing in docs/.vitepress/theme/home.css to stay on one line. Check English and Chinese pages on desktop and mobile when adjusting these styles.

Navigation styles are defined in docs/.vitepress/theme/navigation.css. On Chinese pages between 768px and 959px, the search button hides its keyboard shortcut hint to leave room for the navigation links.

The docs workflow builds pull requests. On main, it also deploys to GitHub Pages. Select GitHub Actions under the repository's Settings → Pages → Build and deployment → Source before its first deployment. The project path is /p4runtime-go-controller/.

Workflow ​

  1. Open an issue before starting non-trivial work so the design can be agreed on first.
  2. Create a branch named feature/<topic> or fix/<topic> from main.
  3. Commit using Conventional Commits (feat, fix, docs, test, refactor, chore, ci, build, perf).
  4. Sign each commit (git commit -s) — the project uses the Developer Certificate of Origin.
  5. Open a pull request against main. Rebase before requesting review. We squash-merge to keep history linear.

Coding Standards ​

  • gofmt, goimports, and golangci-lint run must be clean. CI enforces this.
  • Every exported symbol has a godoc comment beginning with the symbol name.
  • Every blocking exported function takes ctx context.Context first.
  • No new package-level mutable state. No side effects inside init.
  • New tests use testify/require for fatal assertions and testify/assert for soft ones.

Pull Request Checklist ​

  • [ ] make lint test passes locally.
  • [ ] New behavior has tests; public API changes add an entry under [Unreleased] in CHANGELOG.md.
  • [ ] Exported symbols have godoc; major additions ship with an Example* function.
  • [ ] Commits are signed and follow Conventional Commits.

See the Code of Conduct for expected behavior in all project spaces.

Releases ​

See the release guide for version selection, local release validation and the tagged draft-release workflow. This branch uses the /v2 module path. SDK imports must use that prefix, and release tags must be in the v2 series.

Keep the v2 migration guide current when changing public APIs or behavior. Verify its examples from an application outside this module as part of release preparation.

Released under the Apache License 2.0.