Skip to content

Latest commit

 

History

History
194 lines (148 loc) · 8.81 KB

File metadata and controls

194 lines (148 loc) · 8.81 KB

Contributing

Thanks for your interest in contributing to the ClickHouse Terraform provider.

Getting started

  1. Install Go >= 1.26.

  2. Fork and clone the repository.

  3. Enable the git hooks:

    make enable_git_hooks

    This symlinks the committed .githooks/ hooks (pre-commit and commit-msg) into .git/hooks/. Most tooling is fetched on demand by the Make targets: golangci-lint and the patched tfplugindocs are downloaded automatically the first time you run make fmt / make docs, and adr-tool / go-test-coverage are go tool dependencies pinned in go.mod. Only goreleaser must be installed separately if you want to run make goreleaser-check locally.

Development workflow

All commands are exposed through the Makefile so that local runs match CI:

Command Purpose
make build Build the provider binary.
make fmt Format Go source (gofumpt + goimports via golangci-lint).
make lint Run go vet and golangci-lint.
make sec Run security analysis (gosec) on its own.
make test Run unit tests.
make testacc Run acceptance tests (creates real resources).
make cover Run tests and enforce coverage thresholds (.testcoverage.yml).
make docs Regenerate registry documentation with tfplugindocs.
make docs-check Fail if generated docs are out of date.
make goreleaser-check Validate the release config and run a snapshot build.
make adr Create a new ADR (title="..." statement="...").
make mock Regenerate the Cloud API client mock.

Git hooks

make enable_git_hooks symlinks the committed .githooks/ hooks into .git/hooks/. Bypass either in an emergency with git commit --no-verify.

pre-commit

The pre-commit hook runs make fmt docs build and aborts the commit if any step fails. The remaining checks (lint, sec, coverage, docs staleness, goreleaser config) run as separate CI jobs on every pull request.

commit-msg

The commit-msg hook enforces Conventional Commits via scripts/check-conventional-commit.sh: it rejects the commit if the subject line does not match <type>[optional scope][!]: <description>. Merge, revert, and fixup!/squash! subjects are allowed through unchanged.

Commit messages

This project uses Conventional Commits. Each commit subject must take the form:

<type>[optional scope][!]: <description>
  • type — one of feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert.
  • scope (optional) — the area of the codebase; prefer the service group where applicable, e.g. feat(clickstack): ..., fix(postgres): ....
  • ! (optional) — marks a breaking change, e.g. fix!: ....

Examples:

feat(clickstack): add connection resource
fix!: drop support for Terraform < 1.0
docs: explain the ADR workflow

The repository squash-merges pull requests, so the PR title becomes the commit subject on main and is validated by the Validate PR title CI check. The commit-msg hook enforces the same format locally for every commit. Conventional Commits keep history machine-readable, which makes changelog generation and semantic versioning straightforward.

Raising an Architecture Decision Record (ADR)

Significant architectural choices are recorded as Architecture Decision Records under decisions/ — separate from docs/, which is reserved for the generated public Terraform Registry documentation. Raise an ADR whenever you make a decision that is hard to reverse or that future contributors would otherwise have to reverse-engineer (package layout, dependencies, release mechanics, public behavior, and so on).

Records are managed with adr-tool, a Go CLI pinned as a go tool dependency in go.mod (no separate install, no Node.js). It is purely directory-based: numbers are zero-padded and assigned automatically from the highest existing record, and templates are built in. There is no generated index — we rely on the decisions/ listing and each record's header.

  1. Create a record:

    make adr title="Short decision title" statement="The decision and its context"

    This writes decisions/000N-short-decision-title.md from the built-in template. (Equivalent: go tool adr-tool short-adr -p ./decisions -t "..." -s "...".)

  2. Fill it in. Complete the considered options and decision outcome, and set the Status (Proposed, Accepted, Rejected, Deprecated, or Superseded). The title is the file's single top-level heading.

  3. Commit the record. Prefer raising the ADR in the same pull request that implements the decision, so the rationale is reviewed alongside the change.

For richer records or lifecycle changes, use the tool directly:

go tool adr-tool long-adr      -p ./decisions -t "Title" -d "Deciders" -s "Statement"
go tool adr-tool change-status -p ./decisions -a 0001-some-adr.md -s accepted
go tool adr-tool supersede     --help

Tip

adr-tool's --options/-o flag splits values on commas, so avoid commas inside a single option (use a dash or semicolon instead).

Adding a resource or data source

  1. Implement it in a service group under internal/service/<group>/ (clickhouse, postgres, clickstack, …).
  2. Register it in the group's ServicePackage (Resources() / DataSources() in internal/service/<group>/<group>.go) — never in provider.go, which composes its resources from the registry.
  3. Add an example under examples/ and run make docs.
  4. Add acceptance tests and run make testacc.
  5. If it is not GA yet, mark it beta: call utils.BetaWarning("<name>", &resp.Diagnostics) so users see it at plan time, and open its description markdown with a ~> **Note:** This resource is in beta. callout. When a whole service group is beta (as ClickStack is), one callout in internal/provider/README.md covers the group instead of repeating it per resource. Beta resources ship in the normal build — there is no separate binary.

See GO_CONVENTIONS.md for package layout and naming, and decisions/0002-adopt-service-group-layout.md for why the provider is organised into service groups.

Code conventions

Go code in this repository follows the conventions documented in GO_CONVENTIONS.md — package layout (internal/ over pkg/, service groups), Must* vs error-returning naming, error handling, and the rules that golangci-lint enforces automatically.

Releases

Note: the release process can only be run by ClickHouse employees.

Releases are produced by GoReleaser and published by the Release workflow. The provider version embedded in the binary is injected at build time via -X internal/project.version, and the published checksums are signed with GPG.

There is one GoReleaser config, .goreleaser.yml. Every release is built the same way — beta resources ship in the normal build, so there is no separate binary to install.

The tag decides how GitHub serves the release: vX.Y.Z is a normal release, and vX.Y.Z-<suffix> (e.g. v1.2.3-beta1) is flagged a pre-release by prerelease: auto, so it is never served as "latest" and must be requested by exact version. Pre-releases cut before this was renamed use -alphaN tags.

Validate the config locally before releasing with make goreleaser-check.

Pull requests

  • Keep changes focused and include tests where practical.
  • Ensure make lint test docs-check passes before opening a PR.
  • Use a Conventional Commit PR title (it becomes the squash commit subject).
  • Describe user-facing changes clearly in the PR description.

Code of conduct

Be respectful and constructive. Report unacceptable behavior to the maintainers.