Skip to content

Development

Contributing workflow (issues, pull requests, checklist) is described in CONTRIBUTING.md. For pull requests, ensure your commits are signed off (DCO); see the Sign-off (DCO) section for git config and git commit -s.

End-to-end tests

E2E tests run Neptune against MinIO via Docker Compose and do not require a real GitHub PR. See e2e/README.md for prerequisites and how to run ./e2e/scripts/run-terramate.sh. PR emulation is done with an isolated git repo (main + pr-1 branch with changed stacks) and NEPTUNE_E2E=1 so GitHub checks are skipped.

Go

make build      # build binary
make test-all   # run tests
make check-fmt  # check formatting
make lint       # run golangci-lint (optional)

Use the Go version from go.mod. See AGENTS.md for code style, testing, and CI.

Release Process

Neptune uses semantic versioning and GoReleaser to create releases. Only maintainers with push access can create releases.

Semantic Versioning

Tags follow the pattern vMAJOR.MINOR.PATCH (e.g., v0.2.0, v1.0.0). The v prefix is required.

  • MAJOR: Breaking changes or significant architectural changes
  • MINOR: New features, backward-compatible
  • PATCH: Bug fixes, backward-compatible

Creating a Release

  1. Ensure CI is green: All tests, linting, and checks must pass on main (or the branch you're releasing from).

  2. Create and push the tag:

git tag v0.3.0
git push origin v0.3.0
  1. GoReleaser runs automatically: The .github/workflows/release.yml workflow triggers on tag push and runs GoReleaser with the configuration from .goreleaser.yml.

  2. Release artifacts: GoReleaser creates a GitHub Release with:

  3. Neptune binaries: archives (e.g. neptune_linux_amd64.tar.gz, neptune_darwin_arm64.tar.gz, neptune_windows_amd64.zip) and raw binaries (e.g. neptune_linux_amd64, neptune_windows_amd64.exe) for Linux, macOS, Windows (amd64, arm64)
  4. neptune-webhook.zip and raw neptune-webhook_linux_amd64 (Lambda handler binary is neptune-webhook; CloudFormation Handler must match)
  5. checksums.txt (SHA256 checksums for all artifacts)
  6. Release notes generated by GitHub (GoReleaser uses changelog.use: github-native), categorized by .github/release.yml and PR labels (Breaking Changes, Features, Bug fixes, Documentation, Dependency updates, Other work), and a Full Changelog link in the release footer

The version, commit SHA, and build date are injected into the binary via ldflags at build time (see main.version, main.commit, main.date).

Manual Release (if needed)

If you need to run GoReleaser locally (e.g., for testing or troubleshooting), ensure you have GoReleaser installed and a GITHUB_TOKEN with contents: write permission:

export GITHUB_TOKEN=your_token_here
goreleaser release --clean

For a dry run without publishing:

goreleaser release --snapshot --clean

Release notes and labels

Release notes are generated by GitHub when GoReleaser runs (because of changelog.use: github-native in .goreleaser.yml). Categories come from .github/release.yml and the labels on merged PRs in the release range. To create the repository labels once, run from the repo root (requires gh and authentication):

./scripts/create-release-labels.sh

The labeler applies labels from .github/labeler.yml: path-based (dependencies, documentation) and head-branch rules (breaking-change when branch contains !, feature for feat*, enhancement for enhance*, bug for fix* without dep, github-actions for ci*, dependencies for branch containing (deps)). To label already-merged (or other existing) PRs, run the Label old PRs workflow: Actions → "Label old PRs" → Run workflow. You can choose PR state (merged, closed, all) and a limit. The workflow first applies the same rules as the labeler to both head branch and PR title (since the labeler has no branch context on manual runs), then runs the labeler for path-based labels (see actions/labeler). Contributors can use these branch names so PRs are auto-labeled; see CONTRIBUTING.md.

Testing the changelog

With changelog.use: github-native, the release body is produced by GitHub's API, which uses .github/release.yml for categories. The groups, sort, and filters in .goreleaser.yml are not used. To preview release notes without publishing:

  • GoReleaser Pro: Use the dedicated changelog command to preview the next release notes (from latest tag to current commit). Output goes to stdout or to a file:

    goreleaser changelog
    goreleaser changelog -o preview.md
    
    See goreleaser changelog.

  • Open-source GoReleaser: The changelog is generated as the release body but not written to a file. To preview it:

  • Create and push a draft release from the tag you want to test (e.g. a new tag or an existing one): run GoReleaser with --draft and --skip=announce, or trigger the release workflow and mark the release as draft in GitHub.
  • Open the draft release on GitHub to see the generated changelog.
  • Delete the draft release (and the tag if you created it only for this test).

Local run with changelog file: Run make goreleaser.test from a tagged commit (or goreleaser release --skip=publish,validate --clean). GoReleaser writes the generated changelog to dist/CHANGELOG.md, which you can open to verify the format. When there is no previous tag, GoReleaser falls back to the git provider locally, so author appears as Name <Email>; in CI with a previous tag, GitHub's API is used and categories follow .github/release.yml and PR labels.