Skip to content

fix: add default tag name if was missed from configuration#158

Merged
nnicora merged 5 commits into
mainfrom
fix/some-defaults
Mar 17, 2026
Merged

fix: add default tag name if was missed from configuration#158
nnicora merged 5 commits into
mainfrom
fix/some-defaults

Conversation

@nnicora
Copy link
Copy Markdown
Contributor

@nnicora nnicora commented Mar 17, 2026

Summary by CodeRabbit

  • Refactor

    • Default tags are now assigned for cluster, Kubernetes, and Linkerd resources before processing, ensuring consistent tagging across health checks.
  • Chores

    • Removed the explicit version entry from CI/config metadata to simplify configuration files.

@push-tags-from-workflow push-tags-from-workflow Bot added the bug Something isn't working label Mar 17, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 17, 2026

Walkthrough

Set default Tag values for cluster, Kubernetes, and Linkerd resources when empty, and rename the local service variable to cluster in healthcheck processing. Defaults are assigned inside goroutines before invoking resource processing. Removed version: 2 from .coderabbit.yaml.

Changes

Cohort / File(s) Summary
Health Check Processing
internal/healthcheck/check.go
Renamed local service to cluster. In goroutines, ensure Tag is non-empty by defaulting cluster.Tag"cluster", k8s.Tag"kubernetes", and linkerd.Tag"linkerd" before calling their respective processing functions.
CI/Config
.coderabbit.yaml
Removed the version: 2 line from the config file; no other config edits.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided, failing to meet the required template structure with essential sections like 'What this PR does' and 'Release note'. Add a detailed description explaining why default tags are needed, the impact of this change, and provide appropriate release notes.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding default tag names when missing from configuration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/some-defaults
📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link
Copy Markdown

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/healthcheck/check.go`:
- Around line 25-27: The code is mutating input structs' Tag fields
(cluster.Tag, k8s.Tag, linkerd.Tag) inside goroutines which can cause data
races; compute local effective tag values before spawning each goroutine instead
of assigning into the input structs. For each place where you currently do "if
cluster.Tag == "" { cluster.Tag = "cluster" }" (and the similar k8s/linkerd
blocks) in refresh(), create a local variable (e.g., clusterTag, k8sTag,
linkerdTag), set it to the existing Tag or the default ("cluster", "k8s",
"linkerd") and use that local variable inside the goroutine closures; do not
write back to cluster.Tag, k8s.Tag, or linkerd.Tag. Ensure all goroutines
reference these locals so no input structs are mutated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2f5e8173-51ab-4b50-b826-fbe518e20361

📥 Commits

Reviewing files that changed from the base of the PR and between 6e38f83 and 7908186.

📒 Files selected for processing (1)
  • internal/healthcheck/check.go

Comment thread internal/healthcheck/check.go Outdated
Comment on lines +25 to +27
if cluster.Tag == "" {
cluster.Tag = "cluster"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Find process method and callsites"
rg -nP --type=go '\(\s*ch\s+\*CachedResponses\s*\)\s*process\s*\(|\.process\s*\(' -C2

echo
echo "2) Check whether process is invoked from goroutines"
rg -nP --type=go 'go\s+.*process\s*\(' -C3

echo
echo "3) Check shared Healthcheck pointer reuse patterns"
rg -nP --type=go '\*config\.Healthcheck|config\.Healthcheck' -C2

Repository: openkcm/checker

Length of output: 641


🏁 Script executed:

# Check the context around the process call in cached.go
sed -n '75,100p' internal/healthcheck/cached.go

# Also check if there are goroutines spawning at the cached.go level
rg -nP --type=go 'go\s+' internal/healthcheck/cached.go -C3

Repository: openkcm/checker

Length of output: 725


🏁 Script executed:

# Check the full process method to understand goroutine lifecycle
sed -n '15,60p' internal/healthcheck/check.go

Repository: openkcm/checker

Length of output: 960


🏁 Script executed:

# Find all callers of refresh method
rg -nP --type=go 'refresh\s*\(' internal/healthcheck/

# Check if there are other public methods that might trigger concurrent access
rg -nP --type=go 'func\s*\(\s*ch\s+\*CachedResponses\s*\)\s*[A-Z]' internal/healthcheck/check.go

Repository: openkcm/checker

Length of output: 291


🏁 Script executed:

# Check if Tag fields are accessed elsewhere in the codebase
rg -nP --type=go '\.Tag\s*=' internal/healthcheck/ 

# Check for concurrent accesses or locks around config mutation
rg -nP --type=go 'mu\s*(Sync|RW|Lock)' internal/healthcheck/

Repository: openkcm/checker

Length of output: 413


🏁 Script executed:

# View the context around refresh calls to understand execution flow
sed -n '20,50p' internal/healthcheck/cached.go

Repository: openkcm/checker

Length of output: 660


🏁 Script executed:

# Check all public methods of CachedResponses to see if there's concurrent access
rg -nP --type=go 'func\s*\(\s*ch\s+\*CachedResponses\s*\)\s*[A-Z]' internal/healthcheck/

Repository: openkcm/checker

Length of output: 406


🏁 Script executed:

# Check if there are any other goroutines spawning that might call process or access config
rg -nP --type=go 'go\s+func' internal/healthcheck/ -C2

Repository: openkcm/checker

Length of output: 670


🏁 Script executed:

# Verify there are no other concurrent callers by checking HTTP handlers or public APIs
rg -nP --type=go 'func.*\(.*\*http' internal/healthcheck/ 

# Check the package exports and public API surface
rg -nP --type=go 'func\s+[A-Z]' internal/healthcheck/cached.go

Repository: openkcm/checker

Length of output: 150


Avoid mutating input parameter fields inside goroutines for clarity and defensive safety

While the current code is not subject to concurrent access (single-threaded ticker loop), mutating cluster.Tag, k8s.Tag, and linkerd.Tag inside goroutines is poor practice and creates fragility. If refresh() is ever called concurrently or the pattern is reused elsewhere, this becomes a data race. Compute effective tag values before spawning each goroutine.

Proposed refactor
 	cluster := &cfg.Cluster
 	if cluster.Enabled && len(cluster.Resources) > 0 {
+		clusterCfg := *cluster
+		if clusterCfg.Tag == "" {
+			clusterCfg.Tag = "cluster"
+		}
 		wg.Go(func() {
-			if cluster.Tag == "" {
-				cluster.Tag = "cluster"
-			}
-
-			ch.processResources(ctx, cluster, verifyServiceResource, resultCollector)
+			ch.processResources(ctx, &clusterCfg, verifyServiceResource, resultCollector)
 		})
 	}
@@
 	k8s := &cfg.Kubernetes
 	if k8s.Enabled && len(k8s.Resources) > 0 {
+		k8sCfg := *k8s
+		if k8sCfg.Tag == "" {
+			k8sCfg.Tag = "kubernetes"
+		}
 		wg.Go(func() {
-			if k8s.Tag == "" {
-				k8s.Tag = "kubernetes"
-			}
-
-			ch.processResources(ctx, k8s, verifyK8SResource, resultCollector)
+			ch.processResources(ctx, &k8sCfg, verifyK8SResource, resultCollector)
 		})
 	}
@@
 	linkerd := &cfg.Linkerd
 	if linkerd.Enabled {
+		linkerdCfg := *linkerd
+		if linkerdCfg.Tag == "" {
+			linkerdCfg.Tag = "linkerd"
+		}
 		wg.Go(func() {
-			if linkerd.Tag == "" {
-				linkerd.Tag = "linkerd"
-			}
-
-			ch.processLinkerdResources(ctx, linkerd, resultCollector)
+			ch.processLinkerdResources(ctx, &linkerdCfg, resultCollector)
 		})
 	}

Also applies to: 36-38, 47-49

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/healthcheck/check.go` around lines 25 - 27, The code is mutating
input structs' Tag fields (cluster.Tag, k8s.Tag, linkerd.Tag) inside goroutines
which can cause data races; compute local effective tag values before spawning
each goroutine instead of assigning into the input structs. For each place where
you currently do "if cluster.Tag == "" { cluster.Tag = "cluster" }" (and the
similar k8s/linkerd blocks) in refresh(), create a local variable (e.g.,
clusterTag, k8sTag, linkerdTag), set it to the existing Tag or the default
("cluster", "k8s", "linkerd") and use that local variable inside the goroutine
closures; do not write back to cluster.Tag, k8s.Tag, or linkerd.Tag. Ensure all
goroutines reference these locals so no input structs are mutated.

Copy link
Copy Markdown

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/healthcheck/check.go`:
- Around line 24-29: Add a blank line before each wg.Go(...) call to satisfy the
linter: locate the wg.Go invocations that call ch.processResources(ctx, cluster,
verifyServiceResource, resultCollector) (and the other wg.Go call around lines
34-39) and insert a single empty line between the preceding closing brace and
the wg.Go(...) expression so there is whitespace above the expression statement.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 08d6142c-c49d-401f-bb48-c354fd17cd33

📥 Commits

Reviewing files that changed from the base of the PR and between a2df9b1 and ad8b94f.

📒 Files selected for processing (1)
  • internal/healthcheck/check.go

Comment thread internal/healthcheck/check.go
Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
internal/healthcheck/check.go (1)

22-30: 🛠️ Refactor suggestion | 🟠 Major

Avoid mutating shared input config when applying default tags.

Line 24, Line 35, and Line 46 write defaults back into cfg-backed structs. This is still fragile for concurrent callers of process/refresh; prefer local copies (or local effective tag values) and pass those into goroutines.

Proposed refactor
-	cluster := &cfg.Cluster
-	if cluster.Enabled && len(cluster.Resources) > 0 {
-		if cluster.Tag == "" {
-			cluster.Tag = "cluster"
-		}
+	clusterCfg := cfg.Cluster
+	if clusterCfg.Enabled && len(clusterCfg.Resources) > 0 {
+		if clusterCfg.Tag == "" {
+			clusterCfg.Tag = "cluster"
+		}
 
 		wg.Go(func() {
-			ch.processResources(ctx, cluster, verifyServiceResource, resultCollector)
+			ch.processResources(ctx, &clusterCfg, verifyServiceResource, resultCollector)
 		})
 	}
@@
-	k8s := &cfg.Kubernetes
-	if k8s.Enabled && len(k8s.Resources) > 0 {
-		if k8s.Tag == "" {
-			k8s.Tag = "kubernetes"
-		}
+	k8sCfg := cfg.Kubernetes
+	if k8sCfg.Enabled && len(k8sCfg.Resources) > 0 {
+		if k8sCfg.Tag == "" {
+			k8sCfg.Tag = "kubernetes"
+		}
 
 		wg.Go(func() {
-			ch.processResources(ctx, k8s, verifyK8SResource, resultCollector)
+			ch.processResources(ctx, &k8sCfg, verifyK8SResource, resultCollector)
 		})
 	}
@@
-	linkerd := &cfg.Linkerd
-	if linkerd.Enabled {
-		if linkerd.Tag == "" {
-			linkerd.Tag = "linkerd"
-		}
+	linkerdCfg := cfg.Linkerd
+	if linkerdCfg.Enabled {
+		if linkerdCfg.Tag == "" {
+			linkerdCfg.Tag = "linkerd"
+		}
 
 		wg.Go(func() {
-			ch.processLinkerdResources(ctx, linkerd, resultCollector)
+			ch.processLinkerdResources(ctx, &linkerdCfg, resultCollector)
 		})
 	}

Verification goal: confirm whether process can run concurrently and whether mutating cfg.*.Tag can race in current call paths.

#!/bin/bash
set -euo pipefail

echo "1) Locate process() definition and call sites"
rg -nP --type=go '\(\s*ch\s+\*CachedResponses\s*\)\s*process\s*\(|\.process\s*\(' -C3

echo
echo "2) Find refresh() and its scheduling/concurrency context"
rg -nP --type=go '\(\s*ch\s+\*CachedResponses\s*\)\s*refresh\s*\(|\.refresh\s*\(' -C3

echo
echo "3) Check for goroutine-based invocations around healthcheck flows"
rg -nP --type=go 'go\s+func|go\s+.*\.(process|refresh)\s*\(' internal/healthcheck -C3

echo
echo "4) Enumerate Tag assignments in healthcheck package"
rg -nP --type=go '\.(Tag)\s*=' internal/healthcheck -C2

As per coding guidelines "**/*.go: Prioritize identifying security vulnerabilities, unhandled errors, and concurrency issues (e.g., goroutine leaks, race conditions)."

Also applies to: 35-40, 46-51

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/healthcheck/check.go` around lines 22 - 30, The code mutates
cfg-backed structs (e.g., cfg.Cluster.Tag) before spawning goroutines which can
race; instead compute a local effectiveTag (or copy the struct) and pass that
into the goroutine rather than writing back into cfg. For example, when handling
cfg.Cluster use a local variable like effectiveTag := cluster.Tag; if empty set
effectiveTag = "cluster" (or deep-copy cluster into localCluster with
localCluster.Tag set) and call ch.processResources(ctx, localCluster,
verifyServiceResource, resultCollector) or pass effectiveTag into
processResources; apply the same change for other instances that set cfg.*.Tag
(the other Tag assignments referenced) and avoid mutating shared cfg from within
the goroutine setup (wg.Go / processResources).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@internal/healthcheck/check.go`:
- Around line 22-30: The code mutates cfg-backed structs (e.g., cfg.Cluster.Tag)
before spawning goroutines which can race; instead compute a local effectiveTag
(or copy the struct) and pass that into the goroutine rather than writing back
into cfg. For example, when handling cfg.Cluster use a local variable like
effectiveTag := cluster.Tag; if empty set effectiveTag = "cluster" (or deep-copy
cluster into localCluster with localCluster.Tag set) and call
ch.processResources(ctx, localCluster, verifyServiceResource, resultCollector)
or pass effectiveTag into processResources; apply the same change for other
instances that set cfg.*.Tag (the other Tag assignments referenced) and avoid
mutating shared cfg from within the goroutine setup (wg.Go / processResources).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f6260511-6d74-4464-8e1e-606dcf534d15

📥 Commits

Reviewing files that changed from the base of the PR and between ad8b94f and 48cd576.

📒 Files selected for processing (1)
  • internal/healthcheck/check.go

@nnicora nnicora merged commit 124fe30 into main Mar 17, 2026
10 checks passed
@nnicora nnicora deleted the fix/some-defaults branch March 17, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant