Skip to content

fix(feature): resolve lint failures in feature package#221

Merged
skevetter merged 1 commit into
mainfrom
skevetter/fix-feature-lint
May 5, 2026
Merged

fix(feature): resolve lint failures in feature package#221
skevetter merged 1 commit into
mainfrom
skevetter/fix-feature-lint

Conversation

@skevetter

@skevetter skevetter commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes goconst, gosec, cyclop, lll, modernize, revive, and funlen lint failures introduced in the OCI annotations PR (#218). Refactors GetExtendedBuildInfo to use a params struct to satisfy the revive argument-limit rule, extracts helper functions from findContainerUsers to reduce cyclomatic complexity, uses strings.Builder in getFeatureLayers, and applies filepath.Clean to os.Open calls for gosec compliance.

Summary by CodeRabbit

  • Bug Fixes

    • Added integrity verification for cached feature downloads to ensure downloaded content is reliable.
  • Refactor

    • Improved internal architecture for feature extension and configuration handling.

@netlify

netlify Bot commented May 4, 2026

Copy link
Copy Markdown

Deploy Preview for devsydev canceled.

Name Link
🔨 Latest commit 07e31dc
🔍 Latest deploy log https://app.netlify.com/projects/devsydev/deploys/69f94c738f8b7b000807f997

@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR refactors the GetExtendedBuildInfo API to accept a single struct parameter instead of multiple positional arguments, updates call sites in build and compose modules, rewrites feature layer assembly logic, adds SHA-256 cache integrity checks for direct-tar features, and introduces test constants to reduce duplication.

Changes

Feature Extension Refactoring

Layer / File(s) Summary
API Shape Change
pkg/devcontainer/feature/extend.go
ExtendedBuildParams struct introduced; GetExtendedBuildInfo signature changed from six positional parameters to a single struct pointer, extracting fields (Ctx, ImageBuildInfo, Target, DevContainerConfig, ForceBuild, SecretOpts) during execution.
Call Site Updates
pkg/devcontainer/build.go, pkg/devcontainer/compose.go
Both extendImage and buildAndExtendImage in build.go (lines 74–81, 156–163) and buildAndExtendDockerCompose in compose.go (lines 685–695) now instantiate feature.ExtendedBuildParams and pass it to the refactored GetExtendedBuildInfo.
Internal Refactoring
pkg/devcontainer/feature/extend.go
getFeatureLayers rewritten using strings.Builder and an envFile constant for cleaner script assembly; container user resolution split into usersFromMetadata and applyUserFallback helpers; resolveFeatureDependency annotated with //nolint:cyclop.
Cache Integrity & File I/O
pkg/devcontainer/feature/features.go
processDirectTarFeature now verifies cached tarball integrity via verifyCacheIntegrity (with feature.sha256 sidecar) and stores the hash via storeIntegrityHash after download; file operations in pullAndExtractOCIFeature, writeLayerToFile, and tryDownload use filepath.Clean() for path normalization.
Test Updates
pkg/devcontainer/feature/extend_test.go, pkg/devcontainer/feature/annotations_test.go, pkg/devcontainer/feature/collection_test.go
extend_test.go adds test constants (testFeatureA, testFeatureB, testFeatureC) and featureWithDeps helper to reduce hardcoded strings; dependency-order and override tests refactored to use constants; annotations_test.go introduces annotation key constants; collection_test.go adds //nolint:goconst suppression.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • devsy-org/devsy#210: Modifies pkg/devcontainer/feature/extend.go for version-aware changes in feature extension and dependency resolution, directly related to this PR's GetExtendedBuildInfo refactoring and resolveFeatureDependency updates.
  • devsy-org/devsy#89: Introduces SHA-256 integrity checks for direct-tar feature caching with a feature.sha256 sidecar in pkg/devcontainer/feature/features.go, directly aligned with this PR's cache verification implementation.
  • devsy-org/devsy#135: Modifies feature download functions (processDirectTarFeature, processOCIFeature) in pkg/devcontainer/feature/features.go for logging adjustments, related to this PR's file I/O cleanup and cache handling changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main objective of the PR: fixing lint failures in the feature package, which aligns with the primary changes across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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


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.

@skevetter
skevetter marked this pull request as ready for review May 4, 2026 21:54
@skevetter
skevetter enabled auto-merge (squash) May 4, 2026 21:54
@github-actions github-actions Bot added the size/l label May 4, 2026
Fix goconst, gosec, cyclop, lll, modernize, revive, and funlen lint
issues introduced by the OCI annotations PR. Refactors
GetExtendedBuildInfo to use a params struct (revive argument-limit),
extracts helper functions from findContainerUsers (cyclop), uses
strings.Builder in getFeatureLayers (modernize), and adds filepath.Clean
to os.Open calls (gosec G304).
@skevetter
skevetter force-pushed the skevetter/fix-feature-lint branch from da0df62 to 07e31dc Compare May 5, 2026 01:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
pkg/devcontainer/feature/extend.go (1)

260-301: 💤 Low value

Helper extraction reads well.

Splitting metadata-derived users from fallback resolution makes the precedence (metadata → compose service user → image user) explicit and unit-testable. Behavior is unchanged.

One small note: usersFromMetadata dereferences meta.Config without a nil guard on meta. All current call paths populate imageBuildInfo.Metadata via metadata.GetImageMetadata, so this isn't reachable today, but a defensive if meta == nil { return "", "" } would harden the helper against future callers. Optional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/devcontainer/feature/extend.go` around lines 260 - 301, Add a nil-check
at the top of usersFromMetadata to avoid dereferencing meta when nil: if meta ==
nil { return "", "" }, because usersFromMetadata currently calls
config.ReverseSlice(meta.Config) and will panic if meta is nil; update the
function (usersFromMetadata) to return empty containerUser and remoteUser when
meta is nil so callers like findContainerUsers remain safe.
pkg/devcontainer/feature/features.go (1)

419-464: 💤 Low value

Integrity check flow looks reasonable; one consideration on backward-compat behavior.

verifyCacheIntegrity returning true when the feature.sha256 sidecar is missing is appropriate for caches populated before this change. Just be aware that if storeIntegrityHash ever fails to write the sidecar (only logged at error level), subsequent runs will silently fall back to the backward-compat path and skip verification for that cache entry indefinitely. If you want stricter enforcement once a feature has been re-downloaded post-upgrade, consider treating a write failure here as a signal to invalidate the cache (e.g., remove feature.tgz) so the next run re-downloads and re-attempts the sidecar write.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/devcontainer/feature/features.go` around lines 419 - 464, The current
flow lets verifyCacheIntegrity accept missing sidecars; to avoid silently
skipping integrity after storeIntegrityHash fails to write the sidecar, update
storeIntegrityHash to treat a failed os.WriteFile as a cache-invalidation event:
on write failure (in storeIntegrityHash) delete or move the corresponding
tarball (tarballPath or filepath.Join(featureFolder,"feature.tgz")) so the
cached artifact is removed and the next run must re-download and reattempt
writing the sidecar; keep the error log but also add a log entry indicating the
cache invalidation action and ensure verifyCacheIntegrity remains unchanged.
pkg/devcontainer/feature/extend_test.go (1)

10-14: ⚡ Quick win

Consider extending the const block to consolidate repeated test feature IDs.

The new testFeatureA/B/C constants clean up duplication effectively. However, the literal "ghcr.io/devcontainers/features/node" appears 20 times throughout the file and triggers //nolint:goconst suppressions at lines 63, 572, 635, 645, 676, and 689. Adding testFeatureNodeRef = "ghcr.io/devcontainers/features/node" to the const block would eliminate these suppressions and improve maintainability.

Additionally, testFeatureNode is used in this file (lines 56–71) but defined in collection_test.go. While both files are in the same package and the constant is accessible, adding testFeatureNode = "node" to the local const block would make the dependency explicit and match the pattern of testFeatureA/B/C.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/devcontainer/feature/extend_test.go` around lines 10 - 14, The const
block defining testFeatureA/B/C should be extended to include testFeatureNodeRef
= "ghcr.io/devcontainers/features/node" and testFeatureNode = "node" so the
repeated literal and external dependency are declared locally; update references
in tests to use these new constants (replacing the 20 literal occurrences and
the uses that currently rely on testFeatureNode from collection_test.go) and
then remove the corresponding //nolint:goconst suppressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/devcontainer/feature/extend_test.go`:
- Around line 10-14: The const block defining testFeatureA/B/C should be
extended to include testFeatureNodeRef = "ghcr.io/devcontainers/features/node"
and testFeatureNode = "node" so the repeated literal and external dependency are
declared locally; update references in tests to use these new constants
(replacing the 20 literal occurrences and the uses that currently rely on
testFeatureNode from collection_test.go) and then remove the corresponding
//nolint:goconst suppressions.

In `@pkg/devcontainer/feature/extend.go`:
- Around line 260-301: Add a nil-check at the top of usersFromMetadata to avoid
dereferencing meta when nil: if meta == nil { return "", "" }, because
usersFromMetadata currently calls config.ReverseSlice(meta.Config) and will
panic if meta is nil; update the function (usersFromMetadata) to return empty
containerUser and remoteUser when meta is nil so callers like findContainerUsers
remain safe.

In `@pkg/devcontainer/feature/features.go`:
- Around line 419-464: The current flow lets verifyCacheIntegrity accept missing
sidecars; to avoid silently skipping integrity after storeIntegrityHash fails to
write the sidecar, update storeIntegrityHash to treat a failed os.WriteFile as a
cache-invalidation event: on write failure (in storeIntegrityHash) delete or
move the corresponding tarball (tarballPath or
filepath.Join(featureFolder,"feature.tgz")) so the cached artifact is removed
and the next run must re-download and reattempt writing the sidecar; keep the
error log but also add a log entry indicating the cache invalidation action and
ensure verifyCacheIntegrity remains unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ada0723-026c-440e-9bd3-c29fab4460f2

📥 Commits

Reviewing files that changed from the base of the PR and between c9e438d and 07e31dc.

📒 Files selected for processing (7)
  • pkg/devcontainer/build.go
  • pkg/devcontainer/compose.go
  • pkg/devcontainer/feature/annotations_test.go
  • pkg/devcontainer/feature/collection_test.go
  • pkg/devcontainer/feature/extend.go
  • pkg/devcontainer/feature/extend_test.go
  • pkg/devcontainer/feature/features.go

@skevetter
skevetter merged commit c368e1e into main May 5, 2026
54 checks passed
@skevetter
skevetter deleted the skevetter/fix-feature-lint branch May 5, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant