Skip to content

🌱 Add golangci-lint v2 configuration and fix all lint issues#200

Merged
openshift-merge-bot[bot] merged 3 commits intoopen-cluster-management-io:mainfrom
xuezhaojun:add-golangci-lint-v2
Feb 25, 2026
Merged

🌱 Add golangci-lint v2 configuration and fix all lint issues#200
openshift-merge-bot[bot] merged 3 commits intoopen-cluster-management-io:mainfrom
xuezhaojun:add-golangci-lint-v2

Conversation

@xuezhaojun
Copy link
Member

@xuezhaojun xuezhaojun commented Feb 13, 2026

Summary

  • Add golangci-lint v2 configuration (ci/lint/golangci-v2.yml) with automated version detection and install scripts
  • Integrate lint into make verify via verify-gocilint target
  • Fix all 69 lint issues across the codebase, achieving 0 issues on make verify

Lint Configuration

Linters Enabled

Category Linters
Default errcheck, govet, ineffassign, staticcheck, unused
Code style misspell, unconvert, unparam, nakedret, prealloc, copyloopvar, revive
Formatters gofmt, goimports (with open-cluster-management.io local prefix)

Exclusion Rules for Public API Stability

Since this SDK is consumed by many external repositories, the following lint rules are excluded via config to avoid breaking changes:

rules:
  # Exported type names that stutter (e.g., grpc.GRPCServer)
  - linters: [revive]
    text: "exported: type name will be used as"
  # Exported functions returning unexported types
  - linters: [revive]
    text: "unexported-return: exported func"
  # Package names (common, utils, util)
  - linters: [revive]
    text: "avoid meaningless package names"

Additionally, //nolint directives are used for 3 specific exported symbols:

  • JsonLib() function name (should be JSONLib per convention)
  • MQTT_SOURCE_PUB_TOPIC_KEY / MQTT_AGENT_PUB_TOPIC_KEY constants (ALL_CAPS style)

Lint Fixes Applied (No Breaking Changes)

All fixes are internal implementation details or comment-only changes. No exported types, functions, constants, or variables were renamed or removed. External consumers will not experience any compilation errors or behavior changes.

Fix Category Count Description
goimports ~30 files Fix import grouping (local module separated)
misspell 6 cancelledcanceled, CancellingCanceling (comments only)
prealloc 8 Preallocate slices with make([]T, 0, cap)
staticcheck QF1008 5 Simplify embedded field selectors (e.g., config.CertConfig.EmbedCerts()config.EmbedCerts())
unconvert 1 Remove unnecessary types.Int() conversion
var-naming (local) 8 Rename local vars/params: metaJsonmetaJSON, overloadIdoverloadID, blockTlsCrtblockTLSCrt, clientIdclientID, sourceIdsourceID
context-as-argument 1 Move ctx to first param in unexported newWrappedCloudEventsMetricsStream
unparam 2 Remove always-nil error return from unexported newManifestWorks; rename unused closure param to _

No Breaking Changes Guarantee

  • All exported types (e.g., GRPCServer, MQTTOptions, CertConfig, ServingCertController) retain their original names
  • All exported functions (e.g., JsonLib(), NewScoreNormalizer(), NewGRPCMetricsHandler()) retain their original signatures
  • All exported constants (e.g., MQTT_SOURCE_PUB_TOPIC_KEY) retain their original names
  • All package import paths remain unchanged
  • Parameter renames (clientIdclientID, etc.) do not affect callers since Go uses positional arguments

Test plan

  • make verify passes with 0 lint issues (verified with 2 consecutive runs)
  • go build ./... compiles successfully
  • No _test.go files modified

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • gRPC server gains dynamic TLS certificate reloading.
    • Addon v1beta1 client now exposed via the addon client wrapper.
  • Documentation

    • Added comprehensive golangci-lint v2 workflow docs with version guidance and troubleshooting.
  • Chores

    • One-command, Go-version-aware golangci-lint install/run tooling integrated.
    • Performance: several places preallocate slices to reduce allocations.

Add golangci-lint v2 configuration with automated version detection and
install scripts. Fix all 69 lint issues across the codebase without
introducing any breaking changes.

Lint fixes applied:
- goimports: fix import grouping across non-test files
- misspell: fix US English spelling in comments (cancelled -> canceled)
- prealloc: preallocate slices with known capacity
- staticcheck QF1008: simplify embedded field selectors
- unconvert: remove unnecessary type conversions
- revive var-naming: rename local variables and parameters to follow
  Go conventions (metaJson -> metaJSON, overloadId -> overloadID, etc.)
- revive context-as-argument: move ctx to first parameter position
- unparam: remove always-nil error return from unexported function

Lint exclusions for public API stability:
- Exported type names that stutter (e.g., grpc.GRPCServer) are excluded
  via config rules since renaming would break external consumers
- Exported functions returning unexported types are excluded
- Package names (common, utils, types) are excluded
- Individual nolint directives added for JsonLib, MQTT_*_KEY constants,
  and two unparam cases where parameters are kept for readability

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: xuezhaojun <zxue@redhat.com>
@openshift-ci openshift-ci bot requested review from deads2k and qiujian16 February 13, 2026 12:52
@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f05af38 and 504f34e.

📒 Files selected for processing (1)
  • ci/OWNERS

Walkthrough

Adds a golangci-lint v2 workflow (installer, runner, v2 config, Makefile change) and a set of small code edits: import/whitespace fixes, identifier renames, slice preallocation, a manifest builder signature change, new Addon v1beta1 accessor, and dynamic TLS certificate reloading for the gRPC server.

Changes

Cohort / File(s) Summary
Linting infrastructure
Makefile, ci/lint/README-golangci-lint.md, ci/lint/run-lint.sh, ci/lint/install-golangci-lint.sh, ci/lint/golangci-v2.yml
Add golangci-lint v2 workflow: installer and runner scripts, bundled v2 config, Go-version → golangci-lint-version mapping, and Makefile now delegates linting to ci/lint/run-lint.sh.
GolangCI config
ci/lint/golangci-v2.yml
Introduce curated GolangCI-Lint v2 configuration (enabled linters, revive rules, exclusions, formatters).
Manifest / work builder
pkg/apis/work/v1/builder/workbuilder.go
Change internalWorkBuilder.newManifestWorks signature to return only []*workapiv1.ManifestWork (remove error return) and update call sites.
gRPC server TLS
pkg/server/grpc/server.go
Add controller-runtime certwatcher and integrate dynamic TLS certificate reloading via GetCertificate; adjust logging setup.
Addon client accessor
pkg/cloudevents/clients/addon/wrapper.go
Add public method AddonV1beta1() to expose v1beta1 addon client via the wrapper.
Cert config promotion
pkg/cloudevents/generic/options/grpc/options.go, pkg/cloudevents/generic/options/mqtt/options.go
Switch calls to use promoted GRPCConfig/MQTTConfig methods (EmbedCerts(), Validate(), HasCerts()) instead of calling through embedded CertConfig; adjust TLS option construction.
Slice preallocation optimizations
pkg/apis/cluster/v1alpha1/rollout.go, pkg/apis/cluster/v1beta1/placement.go, pkg/cloudevents/generic/options/grpc/options.go, pkg/server/grpc/metrics/metrics.go, pkg/servingcert/controller.go, pkg/testing/managedcluster.go
Replace zero/nil slice inits with make(..., 0, len(...)) or preallocated make+append to reduce allocations.
CEL / cost API rename & logic tweak
pkg/cel/common/values.go, pkg/cel/library/cost.go
Rename parameter overloadIdoverloadID across estimator APIs; in calculateListCost use v.Get(i) instead of v.Get(types.Int(i)).
JSON / variable renames
pkg/cloudevents/clients/.../manifestbundle.go, pkg/cloudevents/clients/work/source/codec/manifestbundle.go
Rename JSON helper locals metaJsonmetaJSON (Encode/Decode) with corresponding usages.
CSR variable rename
pkg/helpers/csr.go
Rename local blockTlsCrtblockTLSCrt while preserving logic.
Metrics stream signature
pkg/cloudevents/server/grpc/metrics/metrics.go
Move ctx to first parameter in newWrappedCloudEventsMetricsStream and update call sites.
Import formatting & comment wording
multiple files (pkg/..., test/...)
Numerous import-block blank-line changes, small import additions, and comment wording adjustments (e.g., "cancelled"→"canceled").
Tests & client fake API usage
test/integration/cloudevents/server/grpc.go, test/integration/cloudevents/util/kube.go
Change manifest decode to use .Raw field; replace client.Fake.PrependReactor with client.PrependReactor.
CI/OWNERS
ci/OWNERS
Add CI owners file listing approvers and reviewers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

approved, lgtm

Suggested reviewers

  • qiujian16
  • deads2k
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: adding golangci-lint v2 configuration and fixing lint issues across the codebase.
Description check ✅ Passed The description is comprehensive and follows the template structure with a clear Summary section. It details the configuration, fixes applied, and explicitly guarantees no breaking changes.
Docstring Coverage ✅ Passed Docstring coverage is 81.25% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xuezhaojun
Copy link
Member Author

xuezhaojun commented Feb 13, 2026

/assign @qiujian16

Please take a review when you have time, thanks!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/cloudevents/clients/addon/wrapper.go (1)

3-17: ⚠️ Potential issue | 🟠 Major

Import ordering violates goimports configuration and must be reorganized.

With local-prefixes: open-cluster-management.io configured, goimports groups imports as: stdlib → third-party → local. The current imports place the local open-cluster-management.io/sdk-go import (line 6) before the third-party k8s.io import (line 8), which is incorrect. All open-cluster-management.io imports should be grouped together after third-party imports. Reorder to: stdlib (context), then third-party (k8s.io), then all open-cluster-management.io imports.

🤖 Fix all issues with AI agents
In `@ci/lint/install-golangci-lint.sh`:
- Around line 163-168: The install script currently skips installation only on
exact match of INSTALLED_VERSION == GOLANGCI_LINT_VERSION which can cause
unwanted downgrades; update the check in install-golangci-lint.sh to perform a
proper semver comparison (>=) like run-lint.sh instead of exact equality.
Implement or reuse the same version-compare logic used by run-lint.sh (or add a
small compare_versions/get_semver_compare function) and change the conditional
that inspects INSTALLED_VERSION and GOLANGCI_LINT_VERSION so it exits when
INSTALLED_VERSION is greater-than-or-equal-to the target, preserving the current
behavior in run-lint.sh.
- Around line 226-257: The script's copy_config function writes .golangci.yml
(LOCAL_CONFIG) into the repo root which creates uncommitted changes; change
copy_config to write the config to a temporary path (e.g. use mktemp or
/tmp/golangci-lint-config) and update any callers/logic that check LOCAL_CONFIG
to prefer that temp file when present (keep CONFIG_SOURCE and CONFIG_FILE names
but avoid creating LOCAL_CONFIG in the repo), or alternatively add logic to
append LOCAL_CONFIG to .gitignore before writing; modify the branch that calls
copy_config and the EXISTING CONFIG check to use the temp location to prevent
dirty working trees in CI.

In `@ci/lint/run-lint.sh`:
- Around line 1-2: The script currently uses "set -e" which allows pipeline
failures to be masked; update the shell options to include pipefail by replacing
the "set -e" invocation with a setting that enables pipefail (e.g., "set -e -o
pipefail" or "set -eo pipefail") so pipelines like "curl ... | sh -s ..." will
surface errors; locate the "set -e" line near the top of the script
(ci/lint/run-lint.sh) and change it accordingly.
🧹 Nitpick comments (5)
pkg/cloudevents/generic/options/grpc/options.go (1)

299-301: Redundant intermediate slice — clientOpts can be passed directly.

opts is created only to hold a copy of clientOpts and is then immediately spread into NewProtocol. You can eliminate the allocation entirely:

♻️ Suggested simplification
-	opts := make([]protocol.Option, 0, len(clientOpts))
-	opts = append(opts, clientOpts...)
-	return protocol.NewProtocol(conn, opts...)
+	return protocol.NewProtocol(conn, clientOpts...)
ci/lint/README-golangci-lint.md (1)

9-13: Security note: piping curl to bash in the Quick Start example.

The recommended curl -sSL ... | bash pattern executes remote code without integrity verification. This is a common CI convenience, but consider noting that users should pin to a specific commit SHA rather than main for reproducibility and supply-chain safety (e.g., https://raw.githubusercontent.com/.../\<commit-sha\>/ci/lint/run-lint.sh).

ci/lint/golangci-v2.yml (1)

87-91: Excluding all test files from linting is a broad exclusion.

_test\.go is excluded from all linters via paths. This means tests won't benefit from govet, errcheck, staticcheck, etc. While this reduces initial noise, it also means bugs in test code (e.g., unchecked errors, incorrect vet findings) will go undetected. Consider moving test exclusions to specific noisy linters only, or plan to remove this blanket exclusion once the test files are cleaned up.

ci/lint/run-lint.sh (1)

103-123: install_lint duplicates logic already in install-golangci-lint.sh.

Both this function and ci/lint/install-golangci-lint.sh implement Go version detection, version selection, and installation via curl. Divergence between the two is likely over time. Consider having run-lint.sh delegate to install-golangci-lint.sh for installation, or consolidate the logic in one place.

ci/lint/install-golangci-lint.sh (1)

115-145: Platform normalization is redundant when go env is available.

Lines 116-117 already call go env GOOS and go env GOARCH (which return normalized values), then lines 120-145 re-normalize the same values. The uname fallback is the only case needing normalization. Consider simplifying:

Suggested simplification
-GOOS="${GOOS:-$(go env GOOS 2>/dev/null || uname -s | tr '[:upper:]' '[:lower:]')}"
-GOARCH="${GOARCH:-$(go env GOARCH 2>/dev/null || uname -m)}"
-
-# Normalize architecture names
-case "${GOARCH}" in
-    x86_64|amd64)
-        GOARCH="amd64"
-        ;;
-    aarch64|arm64)
-        GOARCH="arm64"
-        ;;
-    *)
-        echo "Unsupported architecture: ${GOARCH}"
-        exit 1
-        ;;
-esac
-
-# Normalize OS names
-case "${GOOS}" in
-    Darwin|darwin)
-        GOOS="darwin"
-        ;;
-    Linux|linux)
-        GOOS="linux"
-        ;;
-    *)
-        echo "Unsupported OS: ${GOOS}"
-        exit 1
-        ;;
-esac
+GOOS="${GOOS:-$(go env GOOS 2>/dev/null || uname -s | tr '[:upper:]' '[:lower:]')}"
+GOARCH="${GOARCH:-$(go env GOARCH 2>/dev/null || uname -m)}"
+
+# Normalize values that may come from uname fallback or user override
+case "${GOARCH}" in
+    x86_64) GOARCH="amd64" ;;
+    aarch64) GOARCH="arm64" ;;
+    amd64|arm64) ;; # already normalized
+    *) echo "Unsupported architecture: ${GOARCH}"; exit 1 ;;
+esac
+
+case "${GOOS}" in
+    Darwin) GOOS="darwin" ;;
+    Linux) GOOS="linux" ;;
+    darwin|linux) ;; # already normalized
+    *) echo "Unsupported OS: ${GOOS}"; exit 1 ;;
+esac

xuezhaojun and others added 2 commits February 13, 2026 21:15
Add early return for empty input to maintain nil return value,
which was broken by the prealloc optimization (make returns
non-nil empty slice).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: xuezhaojun <zxue@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: xuezhaojun <zxue@redhat.com>
@xuezhaojun
Copy link
Member Author

/assign @zhujian7

Please take a review, I'm thinking we can apply the same pattern for envtest setup.

@qiujian16
Copy link
Member

/approve
/lgtm

@openshift-ci openshift-ci bot added the lgtm label Feb 25, 2026
@openshift-ci
Copy link

openshift-ci bot commented Feb 25, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: qiujian16, xuezhaojun

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot openshift-merge-bot bot merged commit 57fc6b2 into open-cluster-management-io:main Feb 25, 2026
12 checks passed
@xuezhaojun xuezhaojun deleted the add-golangci-lint-v2 branch February 25, 2026 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants