Skip to content

[sync] go-build: 10 commits from Forge#1

Merged
Snider merged 14 commits intomainfrom
dev
Mar 17, 2026
Merged

[sync] go-build: 10 commits from Forge#1
Snider merged 14 commits intomainfrom
dev

Conversation

@Snider
Copy link
Copy Markdown
Contributor

@Snider Snider commented Mar 17, 2026

Forge → GitHub Sync

Commits: 10
Files changed: 44

Automated sync from Forge (forge.lthn.ai) to GitHub mirror.


Co-Authored-By: Virgil virgil@lethean.io

Summary by CodeRabbit

Release Notes

  • New Features

    • Added internationalisation (i18n) support with English translations for all commands and error messages.
    • Added new prerelease flag to the release command for managing pre-release versions.
  • Improvements

    • Enhanced command help text and descriptions through i18n framework integration.
    • Improved error messages with consistent, structured formatting across the application.
  • Dependencies

    • Updated core library modules and tooling dependencies to latest versions, including OpenAPI and build tooling enhancements.

Snider and others added 12 commits March 15, 2026 15:37
Co-Authored-By: Virgil <virgil@lethean.io>
- aur.go: initialize → initialise in comment and error string
- ci.go: already_initialized → already_initialised i18n key
- diff.go: add comment noting GetUncolorizedText is upstream oasdiff API

Co-Authored-By: Virgil <virgil@lethean.io>
Replace all fmt.Errorf and errors.New calls across 32 production files
with coreerr.E("caller.Method", "message", err) from go-log, matching
the convention already established in publishers/scoop.go and
publishers/homebrew.go.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Virgil <virgil@lethean.io>
132 translation keys for build, ci, sdk commands.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Virgil <virgil@lethean.io>
SDK diff.go used getkin/kin-openapi but oasdiff v1.12+ uses its own
fork. Switched import to match. Restores full CLI binary compilation.

Co-Authored-By: Virgil <virgil@lethean.io>
Move i18n.T() calls out of package-level var declarations (which run
at import time, before i18n is initialised) into setXxxI18n() functions
called from AddXxxCommands at registration time.

Co-Authored-By: Virgil <virgil@lethean.io>
- CLAUDE.md: update error wrapping convention from fmt.Errorf to coreerr.E()
- cmd/build: fix RegisterCommands API mismatch (cli v0.3.5 compat)
- locales: self-register translations via i18n.RegisterLocales in init()
- cmd/sdk: replace fmt.Printf with cli.Print for consistent output
- cmd/build/cmd_pwa: replace os.Stat with coreio.Local.IsDir
- pkg/build/builders: replace os.Stat with io.Local.IsFile for CLI checks
- pkg/release/publishers/scoop: replace os.Stat with coreio.Local.IsDir
- pkg/api: add tests for getBuilder, resolveDir, and medium initialisation

Co-Authored-By: Virgil <virgil@lethean.io>
…LAUDE.md — update any outdate...' (#1) from agent/dx-audit-and-fix--1--review-claude-md into main
@Snider
Copy link
Copy Markdown
Contributor Author

Snider commented Mar 17, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

Warning

Rate limit exceeded

@Snider has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 30 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7bb3eb49-cc3e-4ce3-90a0-15dce4fe7114

📥 Commits

Reviewing files that changed from the base of the PR and between 356e531 and 2ea54f4.

📒 Files selected for processing (17)
  • CLAUDE.md
  • cmd/build/cmd_build.go
  • cmd/build/cmd_pwa.go
  • cmd/sdk/cmd.go
  • locales/embed.go
  • pkg/api/provider_test.go
  • pkg/build/builders/docker.go
  • pkg/build/builders/linuxkit.go
  • pkg/build/builders/taskfile.go
  • pkg/build/builders/wails.go
  • pkg/build/signing/codesign.go
  • pkg/build/signing/sign.go
  • pkg/release/publishers/chocolatey.go
  • pkg/release/publishers/github.go
  • pkg/release/publishers/npm.go
  • pkg/release/publishers/npm_test.go
  • pkg/release/publishers/scoop.go
📝 Walkthrough

Walkthrough

This pull request systematically replaces standard error handling across multiple modules with a centralized core error wrapper (coreerr.E) for consistent error construction. It introduces internationalization infrastructure through locales filesystem embedding, wires i18n initialization into command setup functions, and upgrades multiple Go module dependencies.

Changes

Cohort / File(s) Summary
Command i18n initialization
cmd/build/cmd_build.go, cmd/build/cmd_release.go, cmd/build/cmd_sdk.go, cmd/ci/ci.go, cmd/ci/cmd.go, cmd/sdk/cmd.go
Defers command Short/Long text population to new i18n setup functions (setBuildI18n, setReleaseI18n, setCII18n, setSDKI18n) invoked at command registration. Adds flag initialization for release (new prerelease flag) and CI modules. Adjusts command metadata initialization from declaration-time to runtime population.
Error handling in build command layer
cmd/build/cmd_project.go, cmd/build/cmd_pwa.go
Replaces fmt.Errorf and os.Errorf constructions with coreerr.E wrapper. Introduces coreio.Local file operations in PWA module. Standardizes error context strings for project type detection, config loading, and PWA build steps.
Error handling in build archive and builders
pkg/build/archive.go, pkg/build/builders/cpp.go, pkg/build/builders/docker.go, pkg/build/builders/go.go, pkg/build/builders/linuxkit.go, pkg/build/builders/taskfile.go, pkg/build/builders/wails.go
Replaces errors and fmt.Errorf with coreerr.E across archive creation, builder config validation, and build execution paths. Removes direct errors package usage and standardises error context formatting with module-qualified identifiers.
Error handling in build utilities
pkg/build/checksum.go, pkg/build/config.go, pkg/build/signing/codesign.go, pkg/build/signing/gpg.go, pkg/build/signing/sign.go
Replaces standard error construction with coreerr.E in checksum calculation, config file operations, and code signing paths. Removes fmt and errors imports; applies consistent error context naming conventions.
Error handling in release core and config
pkg/release/changelog.go, pkg/release/config.go, pkg/release/release.go, pkg/release/sdk.go, pkg/release/version.go
Replaces fmt.Errorf and errors.New with coreerr.E across config loading/writing, release publishing, SDK generation, and version parsing. Removes direct errors package usage.
Error handling in release publishers
pkg/release/publishers/aur.go, pkg/release/publishers/chocolatey.go, pkg/release/publishers/docker.go, pkg/release/publishers/github.go, pkg/release/publishers/homebrew.go, pkg/release/publishers/linuxkit.go, pkg/release/publishers/npm.go, pkg/release/publishers/scoop.go
Replaces standard error wrapping with coreerr.E. Introduces coreio.Medium abstraction to replace io.Medium in method signatures for AUR, Homebrew, NPM, and Scoop publishers. Updates filesystem operations to use coreio.Local helpers (DeleteAll, EnsureDir, Write).
Error handling in SDK modules
pkg/sdk/detect.go, pkg/sdk/diff.go, pkg/sdk/generators/go.go, pkg/sdk/generators/php.go, pkg/sdk/generators/python.go, pkg/sdk/generators/typescript.go, pkg/sdk/sdk.go
Replaces fmt.Errorf and errors.New with coreerr.E across OpenAPI spec detection, diff computation, and code generator output directory creation. Removes direct errors and fmt imports; applies consistent error-wrapping patterns.
Localization infrastructure
locales/embed.go, locales/en.json
Adds new package-level locales with embedded filesystem (FS variable) containing JSON translations. Introduces comprehensive English localizations for commands (build, CI, SDK, PWA, release) and subcommands with translations for flags, messages, and error descriptions.
Dependency upgrades
go.mod
Updates forge.lthn.ai/core modules (api, cli, go-i18n, go-io, go-log, go-ws), OpenAPI tooling (kin-openapi, oasdiff), and transitive dependencies (golang.org/x/*, go-openapi/*, otel components). Introduces redis/go-redis/v9 and additional OpenAPI-related indirect dependencies.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title '[sync] go-build: 10 commits from Forge' is vague and generic, using non-descriptive terms that do not clearly convey the primary changes. Provide a more specific title that describes the main changes, such as 'Sync from Forge: add i18n support, adopt coreerr error handling, and update dependencies'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 84.48% which is sufficient. The required threshold is 80.00%.

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

📝 Coding Plan
  • Generate coding plan for human review comments

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 5

Caution

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

⚠️ Outside diff range comments (7)
pkg/release/publishers/chocolatey.go (1)

231-254: ⚠️ Potential issue | 🟡 Minor

Consider API key exposure in process listings.

The API key passed via --api-key command-line argument (line 249) is visible in process listings (ps aux, /proc/<pid>/cmdline). Whilst this is the standard choco CLI pattern and the key already exists in the environment, command-line arguments have broader visibility on multi-user systems.

If this is a concern for your deployment environment, consider:

  • Using choco apikey --set during CI setup to store the key in Chocolatey's config beforehand, then omitting --api-key from the push command.
  • Documenting that builds should run in isolated environments.

This is informational rather than a blocker, as the current approach aligns with common CI/CD practices.

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

In `@pkg/release/publishers/chocolatey.go` around lines 231 - 254, The
pushToChocolatey function currently passes CHOCOLATEY_API_KEY on the choco push
command line (visible in process listings); instead, set the API key in
Chocolatey config prior to pushing and omit the --api-key argument: call choco
apikey (e.g. the equivalent of "choco apikey --set"/"choco apikey --key") using
the CHOCOLATEY_API_KEY env var (referencing CHOCOLATEY_API_KEY,
pushToChocolatey, cmd and nupkgPath) and then change the choco push invocation
to remove the "--api-key" flag so the key is not exposed in process arguments;
optionally document that CI should run in isolated environments if you keep the
current approach.
pkg/release/publishers/npm.go (1)

240-245: ⚠️ Potential issue | 🟡 Minor

Silent error swallowing may hide custom template failures.

If m.IsFile(customPath) returns true but m.Read(customPath) subsequently fails (e.g., permissions, encoding issues), the error is silently ignored and the embedded template is used instead. Users won't be aware their custom template wasn't applied.

Consider logging a warning or returning an error when a custom template exists but cannot be read.

🛠️ Suggested fix
 	customPath := filepath.Join(".core", name)
 	if m != nil && m.IsFile(customPath) {
 		customContent, err := m.Read(customPath)
-		if err == nil {
+		if err != nil {
+			return "", coreerr.E("npm.renderTemplate", "failed to read custom template "+customPath, err)
+		}
+		if customContent != "" {
 			content = []byte(customContent)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/npm.go` around lines 240 - 245, The code silently
ignores errors from m.Read(customPath), so when m.IsFile(customPath) is true but
m.Read fails the custom template silently falls back to embedded content; update
the branch that calls m.Read(customPath) to handle err != nil explicitly: either
return the error up from the current function or emit a warning via the package
logger including customPath and err, and only overwrite content on successful
read (keep using content variable only when err == nil). Ensure you modify the
snippet that calls m.IsFile and m.Read (and the surrounding function that uses
content) so callers/users are informed when a custom template exists but cannot
be read.
cmd/build/cmd_release.go (1)

35-46: ⚠️ Potential issue | 🟠 Major

Guard flag initialisation to prevent duplicate-flag panics.

Line 35-40 is called from AddReleaseCommand (Line 44-45). If AddReleaseCommand is invoked more than once in the same process, these flag registrations will panic due to duplicate names.

Suggested fix
 import (
 	"context"
 	"os"
+	"sync"
@@
 )
@@
 var (
 	releaseVersion     string
 	releaseDraft       bool
 	releasePrerelease  bool
 	releaseGoForLaunch bool
+	releaseFlagsOnce   sync.Once
 )
@@
 func initReleaseFlags() {
-	releaseCmd.Flags().BoolVar(&releaseGoForLaunch, "we-are-go-for-launch", false, i18n.T("cmd.build.release.flag.go_for_launch"))
-	releaseCmd.Flags().StringVar(&releaseVersion, "version", "", i18n.T("cmd.build.release.flag.version"))
-	releaseCmd.Flags().BoolVar(&releaseDraft, "draft", false, i18n.T("cmd.build.release.flag.draft"))
-	releaseCmd.Flags().BoolVar(&releasePrerelease, "prerelease", false, i18n.T("cmd.build.release.flag.prerelease"))
+	releaseFlagsOnce.Do(func() {
+		releaseCmd.Flags().BoolVar(&releaseGoForLaunch, "we-are-go-for-launch", false, i18n.T("cmd.build.release.flag.go_for_launch"))
+		releaseCmd.Flags().StringVar(&releaseVersion, "version", "", i18n.T("cmd.build.release.flag.version"))
+		releaseCmd.Flags().BoolVar(&releaseDraft, "draft", false, i18n.T("cmd.build.release.flag.draft"))
+		releaseCmd.Flags().BoolVar(&releasePrerelease, "prerelease", false, i18n.T("cmd.build.release.flag.prerelease"))
+	})
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/build/cmd_release.go` around lines 35 - 46, The flag registrations in
initReleaseFlags() (releaseCmd.Flags().BoolVar / StringVar etc.) can panic if
called more than once; make initialization idempotent by guarding it with a
package-level sync.Once (e.g., releaseFlagsInitOnce) or a boolean guard and call
that guard from AddReleaseCommand before calling initReleaseFlags() and
setReleaseI18n(); ensure initReleaseFlags() only runs once so duplicate calls to
AddReleaseCommand won't re-register flags on releaseCmd.
cmd/build/cmd_project.go (1)

348-356: ⚠️ Potential issue | 🟡 Minor

Reject empty OS/architecture tokens in target parsing.

Line 354 and Line 355 can still be empty after trimming. Inputs like linux/ or /amd64 pass current validation and fail later with less actionable errors. Validate both fields before appending.

💡 Proposed fix
 		osArch := strings.Split(part, "/")
 		if len(osArch) != 2 {
 			return nil, coreerr.E("build.parseTargets", "invalid target format (expected os/arch): "+part, nil)
 		}
+		osVal := strings.TrimSpace(osArch[0])
+		archVal := strings.TrimSpace(osArch[1])
+		if osVal == "" || archVal == "" {
+			return nil, coreerr.E("build.parseTargets", "invalid target format (expected non-empty os/arch): "+part, nil)
+		}
 
 		targets = append(targets, build.Target{
-			OS:   strings.TrimSpace(osArch[0]),
-			Arch: strings.TrimSpace(osArch[1]),
+			OS:   osVal,
+			Arch: archVal,
 		})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/build/cmd_project.go` around lines 348 - 356, When parsing targets into
os/arch pairs (the osArch split used to build build.Target entries), the code
currently only checks len(osArch) == 2 but does not reject empty tokens; trim
both parts (os := strings.TrimSpace(osArch[0]); arch :=
strings.TrimSpace(osArch[1])) and validate they are non-empty before appending
to targets. If either os or arch is empty, return a coreerr.E error (consistent
with the existing "build.parseTargets" error style) describing the invalid
target format so inputs like "linux/" or "/amd64" fail early with a clear
message.
pkg/build/builders/cpp.go (1)

205-213: ⚠️ Potential issue | 🟠 Major

Replace os.Stat() with the injected filesystem method.

The function receives an fs io.Medium parameter and uses it for IsDir() and List() operations (lines 180 and 184), but line 206 switches to os.Stat(fullPath). This breaks the filesystem abstraction and causes silent data loss: entries returned by fs.List() will be silently skipped because os.Stat() cannot access paths on non-local mediums.

Fix
-			info, err := os.Stat(fullPath)
+			info, err := fs.Stat(fullPath)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/build/builders/cpp.go` around lines 205 - 213, Replace the direct call to
os.Stat(fullPath) with the injected filesystem on the function's io.Medium
parameter (use fs.Stat or the equivalent Stat method on the io.Medium) so the
code uses the same abstracted medium used by fs.IsDir() and fs.List(); keep the
existing logic that checks info.Mode()&0111 for executability and continue on
error, but obtain info from fs.Stat(fullPath) (respecting the io.Medium API)
instead of os.Stat.
pkg/build/archive.go (1)

223-249: ⚠️ Potential issue | 🔴 Critical

Propagate archive writer finalisation errors.

Ignoring Close() errors on lines 225, 229, and 275 allows the function to return success whilst leaving a corrupt archive on disk. The gzip.Writer.Close(), tar.Writer.Close(), and zip.Writer.Close() calls write critical metadata: GZIP footer (CRC and uncompressed size), tar footer (two 512-byte zero blocks), and ZIP central directory respectively.

Check these errors before returning nil:

Example fix for createTarGzArchive
-	gzWriter := gzip.NewWriter(dstFile)
-	defer func() { _ = gzWriter.Close() }()
+	gzWriter := gzip.NewWriter(dstFile)

-	tarWriter := tar.NewWriter(gzWriter)
-	defer func() { _ = tarWriter.Close() }()
+	tarWriter := tar.NewWriter(gzWriter)
 
 	// ... file content operations ...
 
-	return nil
+	if err := tarWriter.Close(); err != nil {
+		return coreerr.E("build.createTarGzArchive", "failed to close tar writer", err)
+	}
+	if err := gzWriter.Close(); err != nil {
+		return coreerr.E("build.createTarGzArchive", "failed to close gzip writer", err)
+	}
+	return nil

Apply the same pattern to createZipArchive for zipWriter.Close() and the destination file close.

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

In `@pkg/build/archive.go` around lines 223 - 249, The Close() errors from archive
writers and the destination file are currently ignored, which can leave corrupt
archives; update createTarGzArchive and createZipArchive to capture and check
the errors returned from gzWriter.Close(), tarWriter.Close(), zipWriter.Close()
and dstFile.Close() (and any srcFile.Close() if deferred closures return errors)
and return a coreerr.E with a clear message (e.g., "failed to finalize
gzip/tar/zip archive" or "failed to close destination file") when those Close()
calls fail instead of discarding the error; make sure to call Close() in the
correct order (flush writers before closing the underlying file) and propagate
the first non-nil error back to the caller.
cmd/build/cmd_pwa.go (1)

206-214: ⚠️ Potential issue | 🔴 Critical

Validate asset paths to prevent writing outside the destination directory.

The path construction using filepath.Join(destDir, filepath.FromSlash(u.Path)) is vulnerable to directory traversal. Since u.Path is extracted from a remote manifest URL and can contain .. segments (e.g., a manifest listing an asset with path ../../etc/passwd), an attacker can craft a manifest that writes arbitrary files outside destDir. Go's filepath.Join is not a security boundary—it normalises paths but does not prevent escaping.

Recommended fix: For Go 1.21+, use filepath.IsLocal(filepath.FromSlash(u.Path)) to reject any path containing .., absolute components, or other escape sequences before joining. Alternatively, validate the final path explicitly:

Path validation example
cleanPath := filepath.Clean(filepath.Join(destDir, filepath.FromSlash(u.Path)))
cleanDestDir := filepath.Clean(destDir)
if cleanPath != cleanDestDir && !strings.HasPrefix(cleanPath, cleanDestDir+string(filepath.Separator)) {
    return coreerr.E("pwa.downloadAsset", "asset path escapes destination directory", nil)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/build/cmd_pwa.go` around lines 206 - 214, The code currently joins
destDir and filepath.FromSlash(u.Path) (used before calling
coreio.Local.EnsureDir and os.Create) which allows directory-traversal via `..`;
validate and reject paths that escape destDir before creating directories or
files. Replace the naive join with a check that either uses
filepath.IsLocal(filepath.FromSlash(u.Path)) on Go 1.21+ to reject unsafe
inputs, or compute a cleaned absolute path (cleanPath :=
filepath.Clean(filepath.Join(destDir, filepath.FromSlash(u.Path)))) and ensure
it equals cleanDestDir or has cleanDestDir+separator as a prefix; if the check
fails return a descriptive error (e.g., using the existing pwa download error
path like coreerr.E("pwa.downloadAsset", "asset path escapes destination
directory", nil)). Ensure the validation happens prior to calling
coreio.Local.EnsureDir and os.Create.
🧹 Nitpick comments (6)
pkg/release/publishers/npm.go (1)

133-133: Unused parameter cfg.

The cfg *NpmConfig parameter is not used within dryRunPublish. Consider removing it if it's not needed for API consistency, or prefix with _ to indicate intentional non-use.

♻️ Suggested fix
-func (p *NpmPublisher) dryRunPublish(m coreio.Medium, data npmTemplateData, cfg *NpmConfig) error {
+func (p *NpmPublisher) dryRunPublish(m coreio.Medium, data npmTemplateData, _ *NpmConfig) error {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/npm.go` at line 133, The method signature for
NpmPublisher.dryRunPublish includes an unused parameter cfg *NpmConfig; remove
this parameter from the function signature and all call sites if API
compatibility allows, otherwise rename it to _cfg (or _ in the parameter list)
to mark it intentionally unused; update references to the function (calls and
any interface definitions) to match the new signature and run tests to ensure no
call sites are left with the removed argument.
pkg/build/signing/sign.go (1)

93-93: Include the checksum file path in the error message.

Using checksumFile in this message would make failures easier to pinpoint in multi-artifact runs.

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

In `@pkg/build/signing/sign.go` at line 93, Update the error returned from
signing.SignChecksums so it includes the checksum file path (checksumFile) in
the message; replace the current coreerr.E("signing.SignChecksums", "failed to
sign checksums", err) with a message that embeds checksumFile (e.g. "failed to
sign checksums for <checksumFile>") so failures clearly identify which checksum
file failed to sign.
pkg/build/signing/codesign.go (1)

45-45: Make the unavailable error reason explicit.

codesign not available hides whether the blocker is OS, identity, or missing binary. Returning a specific reason here makes failures actionable.

Proposed refactor
 func (s *MacOSSigner) Sign(ctx context.Context, fs io.Medium, binary string) error {
-	if !s.Available() {
-		return coreerr.E("codesign.Sign", "codesign not available", nil)
-	}
+	if runtime.GOOS != "darwin" {
+		return coreerr.E("codesign.Sign", "codesign requires darwin", nil)
+	}
+	if s.config.Identity == "" {
+		return coreerr.E("codesign.Sign", "missing codesign identity", nil)
+	}
+	if _, err := exec.LookPath("codesign"); err != nil {
+		return coreerr.E("codesign.Sign", "codesign binary not found", err)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/build/signing/codesign.go` at line 45, The current return
coreerr.E("codesign.Sign", "codesign not available", nil) hides the actual
cause; update the codesign.Sign path to detect and include the specific reason
(unsupported OS, missing codesign binary, or absent signing identity) in the
error message and attach any underlying error/inspect details to coreerr.E so
the returned error reads e.g. "codesign not available: missing binary" or
"codesign not available: no signing identity" and preserves the original error
value instead of nil; locate the call site in the Sign function and replace the
generic message with a reasoned message and underlying error passed into
coreerr.E.
pkg/release/publishers/scoop.go (1)

256-261: Consider distinguishing file-not-found from other read errors.

When m.Read(customPath) fails, the error is silently discarded and the code falls back to the embedded template. This is reasonable for missing files, but could mask permission errors or I/O failures that the user should be aware of.

💡 Optional: Log non-existent vs failed reads
 	customPath := filepath.Join(".core", name)
 	if m != nil && m.IsFile(customPath) {
 		customContent, err := m.Read(customPath)
 		if err == nil {
 			content = []byte(customContent)
+		} else {
+			// Log warning: custom template exists but couldn't be read
+			fmt.Fprintf(os.Stderr, "Warning: failed to read custom template %s, using default: %v\n", customPath, err)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/scoop.go` around lines 256 - 261, The code currently
swallows all errors from m.Read(customPath) and silently falls back to the
embedded template; change it so only a "file not found" error is treated as a
fallback: call m.Read(customPath), and if err == nil assign customContent to
content, but if err != nil check whether the error indicates the file is missing
(e.g. os.IsNotExist(err) or the equivalent error from the filesystem
implementation) and only ignore that case; for any other error (permission, I/O,
etc.) return or propagate/log the error so the caller of the scoop publisher
(the code path using m.Read, customPath, and content) can handle it
appropriately. Ensure you reference m.Read and customPath in the updated logic.
pkg/build/builders/wails.go (1)

145-151: Inconsistent error handling: raw errors returned without coreerr.E wrapping.

These error paths return raw errors directly, unlike the other error cases in this file which use coreerr.E. For consistency with the rest of the migration, consider wrapping these errors as well.

♻️ Suggested fix for consistency
 	// Simple copy using the medium
 	content, err := cfg.FS.Read(sourcePath)
 	if err != nil {
-		return build.Artifact{}, err
+		return build.Artifact{}, coreerr.E("WailsBuilder.buildV2Target", "failed to read source artifact", err)
 	}
 	if err := cfg.FS.Write(destPath, content); err != nil {
-		return build.Artifact{}, err
+		return build.Artifact{}, coreerr.E("WailsBuilder.buildV2Target", "failed to write artifact to output", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/build/builders/wails.go` around lines 145 - 151, The Read/Write error
paths currently return raw errors from cfg.FS.Read and cfg.FS.Write (inside the
code that returns build.Artifact{}), which is inconsistent with other error
handling in this file; update these returns to wrap the errors with coreerr.E
(e.g., return build.Artifact{}, coreerr.E(err) or coreerr.E("failed to read
source", err)) so they match the rest of the file's error-wrapping style and
include contextual message for cfg.FS.Read and cfg.FS.Write calls.
pkg/release/publishers/github.go (1)

150-159: Preserve underlying gh execution errors.

Line 151 and Line 158 currently pass nil as the cause, which drops useful diagnostics from exec.

Suggested fix
 	if err := cmd.Run(); err != nil {
-		return coreerr.E("github.validateGhCli", "gh CLI not found. Install it from https://cli.github.com", nil)
+		return coreerr.E("github.validateGhCli", "gh CLI not found. Install it from https://cli.github.com", err)
 	}
@@
 	output, err := cmd.CombinedOutput()
 	if err != nil {
-		return coreerr.E("github.validateGhCli", "not authenticated with gh CLI. Run 'gh auth login' first", nil)
+		return coreerr.E("github.validateGhCli", "not authenticated with gh CLI. Run 'gh auth login' first", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/github.go` around lines 150 - 159, The checks that run
the gh CLI use coreerr.E with a nil cause, dropping the underlying exec errors;
update the error returns in the cmd.Run() failure and the cmd.CombinedOutput()
failure to pass the actual exec error (and optionally the command output for
richer context) as the cause so diagnostics are preserved—modify the branch that
calls cmd.Run() and the branch that calls cmd.CombinedOutput() to return
coreerr.E("github.validateGhCli", "<message>", err) (or include fmt.Errorf("%s:
%w", string(output), err) as the cause) instead of nil.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/build/builders/docker.go`:
- Line 190: The wrapped errors in DockerBuilder.validateDockerCli currently drop
the underlying command failure by passing nil as the cause; update both
coreerr.E calls that return the "docker CLI not found..." and "docker daemon not
running..." errors to pass the actual error variable (err) returned from
cmd.Run() as the third argument so the original cmd.Run() failure is preserved
in the wrapped error (locate the coreerr.E calls inside validateDockerCli and
replace the nil cause with err).

In `@pkg/release/publishers/docker.go`:
- Around line 274-279: The docker CLI validation in validateDockerCli discards
the underlying error from cmd.Run(); capture the returned err and pass it into
the coreerr.E wrapper so diagnostics include the original error (i.e., when
cmd.Run() returns non-nil, return coreerr.E("docker.validateDockerCli", "docker
CLI not found. Install it from https://docs.docker.com/get-docker/", err)). This
preserves the original error context for troubleshooting while keeping the
existing message and error code.
- Around line 253-256: The error from exec.CommandContext(...).Run() is being
discarded; update the error return so the original err is passed into coreerr.E
instead of nil. Locate the docker buildx check (where cmd :=
exec.CommandContext(ctx, "docker", "buildx", "version") and if err := cmd.Run();
err != nil { ... }) and change the return to return
coreerr.E("docker.ensureBuildx", "buildx is not available. Install it from
https://docs.docker.com/buildx/working-with-buildx/", err) so the underlying
diagnostic is preserved.

In `@pkg/release/publishers/github.go`:
- Line 201: The error currently returned in github.parseGitHubRepo includes the
raw remote URL which may leak credentials; change the return in parseGitHubRepo
(the coreerr.E call) to avoid embedding the raw url by using a generic message
like "not a GitHub URL" or redacting the URL first (e.g., replace userinfo with
"<redacted>") before including it. Update the coreerr.E invocation in github.go
to either remove the "+url" concatenation or call a small helper (e.g.,
redactRemote(url)) to sanitize the value so no sensitive auth data is logged.

In `@pkg/release/publishers/linuxkit.go`:
- Around line 301-303: The linuxkit CLI validation currently discards the
underlying error returned by cmd.Run(); update the error wrap so the actual err
is passed into coreerr.E(...) instead of nil. Locate the block where cmd.Run()
is executed (the validation around linuxkit version) and change the coreerr.E
call to include the caught err as the third argument so the original failure is
preserved for diagnostics.

---

Outside diff comments:
In `@cmd/build/cmd_project.go`:
- Around line 348-356: When parsing targets into os/arch pairs (the osArch split
used to build build.Target entries), the code currently only checks len(osArch)
== 2 but does not reject empty tokens; trim both parts (os :=
strings.TrimSpace(osArch[0]); arch := strings.TrimSpace(osArch[1])) and validate
they are non-empty before appending to targets. If either os or arch is empty,
return a coreerr.E error (consistent with the existing "build.parseTargets"
error style) describing the invalid target format so inputs like "linux/" or
"/amd64" fail early with a clear message.

In `@cmd/build/cmd_pwa.go`:
- Around line 206-214: The code currently joins destDir and
filepath.FromSlash(u.Path) (used before calling coreio.Local.EnsureDir and
os.Create) which allows directory-traversal via `..`; validate and reject paths
that escape destDir before creating directories or files. Replace the naive join
with a check that either uses filepath.IsLocal(filepath.FromSlash(u.Path)) on Go
1.21+ to reject unsafe inputs, or compute a cleaned absolute path (cleanPath :=
filepath.Clean(filepath.Join(destDir, filepath.FromSlash(u.Path)))) and ensure
it equals cleanDestDir or has cleanDestDir+separator as a prefix; if the check
fails return a descriptive error (e.g., using the existing pwa download error
path like coreerr.E("pwa.downloadAsset", "asset path escapes destination
directory", nil)). Ensure the validation happens prior to calling
coreio.Local.EnsureDir and os.Create.

In `@cmd/build/cmd_release.go`:
- Around line 35-46: The flag registrations in initReleaseFlags()
(releaseCmd.Flags().BoolVar / StringVar etc.) can panic if called more than
once; make initialization idempotent by guarding it with a package-level
sync.Once (e.g., releaseFlagsInitOnce) or a boolean guard and call that guard
from AddReleaseCommand before calling initReleaseFlags() and setReleaseI18n();
ensure initReleaseFlags() only runs once so duplicate calls to AddReleaseCommand
won't re-register flags on releaseCmd.

In `@pkg/build/archive.go`:
- Around line 223-249: The Close() errors from archive writers and the
destination file are currently ignored, which can leave corrupt archives; update
createTarGzArchive and createZipArchive to capture and check the errors returned
from gzWriter.Close(), tarWriter.Close(), zipWriter.Close() and dstFile.Close()
(and any srcFile.Close() if deferred closures return errors) and return a
coreerr.E with a clear message (e.g., "failed to finalize gzip/tar/zip archive"
or "failed to close destination file") when those Close() calls fail instead of
discarding the error; make sure to call Close() in the correct order (flush
writers before closing the underlying file) and propagate the first non-nil
error back to the caller.

In `@pkg/build/builders/cpp.go`:
- Around line 205-213: Replace the direct call to os.Stat(fullPath) with the
injected filesystem on the function's io.Medium parameter (use fs.Stat or the
equivalent Stat method on the io.Medium) so the code uses the same abstracted
medium used by fs.IsDir() and fs.List(); keep the existing logic that checks
info.Mode()&0111 for executability and continue on error, but obtain info from
fs.Stat(fullPath) (respecting the io.Medium API) instead of os.Stat.

In `@pkg/release/publishers/chocolatey.go`:
- Around line 231-254: The pushToChocolatey function currently passes
CHOCOLATEY_API_KEY on the choco push command line (visible in process listings);
instead, set the API key in Chocolatey config prior to pushing and omit the
--api-key argument: call choco apikey (e.g. the equivalent of "choco apikey
--set"/"choco apikey --key") using the CHOCOLATEY_API_KEY env var (referencing
CHOCOLATEY_API_KEY, pushToChocolatey, cmd and nupkgPath) and then change the
choco push invocation to remove the "--api-key" flag so the key is not exposed
in process arguments; optionally document that CI should run in isolated
environments if you keep the current approach.

In `@pkg/release/publishers/npm.go`:
- Around line 240-245: The code silently ignores errors from m.Read(customPath),
so when m.IsFile(customPath) is true but m.Read fails the custom template
silently falls back to embedded content; update the branch that calls
m.Read(customPath) to handle err != nil explicitly: either return the error up
from the current function or emit a warning via the package logger including
customPath and err, and only overwrite content on successful read (keep using
content variable only when err == nil). Ensure you modify the snippet that calls
m.IsFile and m.Read (and the surrounding function that uses content) so
callers/users are informed when a custom template exists but cannot be read.

---

Nitpick comments:
In `@pkg/build/builders/wails.go`:
- Around line 145-151: The Read/Write error paths currently return raw errors
from cfg.FS.Read and cfg.FS.Write (inside the code that returns
build.Artifact{}), which is inconsistent with other error handling in this file;
update these returns to wrap the errors with coreerr.E (e.g., return
build.Artifact{}, coreerr.E(err) or coreerr.E("failed to read source", err)) so
they match the rest of the file's error-wrapping style and include contextual
message for cfg.FS.Read and cfg.FS.Write calls.

In `@pkg/build/signing/codesign.go`:
- Line 45: The current return coreerr.E("codesign.Sign", "codesign not
available", nil) hides the actual cause; update the codesign.Sign path to detect
and include the specific reason (unsupported OS, missing codesign binary, or
absent signing identity) in the error message and attach any underlying
error/inspect details to coreerr.E so the returned error reads e.g. "codesign
not available: missing binary" or "codesign not available: no signing identity"
and preserves the original error value instead of nil; locate the call site in
the Sign function and replace the generic message with a reasoned message and
underlying error passed into coreerr.E.

In `@pkg/build/signing/sign.go`:
- Line 93: Update the error returned from signing.SignChecksums so it includes
the checksum file path (checksumFile) in the message; replace the current
coreerr.E("signing.SignChecksums", "failed to sign checksums", err) with a
message that embeds checksumFile (e.g. "failed to sign checksums for
<checksumFile>") so failures clearly identify which checksum file failed to
sign.

In `@pkg/release/publishers/github.go`:
- Around line 150-159: The checks that run the gh CLI use coreerr.E with a nil
cause, dropping the underlying exec errors; update the error returns in the
cmd.Run() failure and the cmd.CombinedOutput() failure to pass the actual exec
error (and optionally the command output for richer context) as the cause so
diagnostics are preserved—modify the branch that calls cmd.Run() and the branch
that calls cmd.CombinedOutput() to return coreerr.E("github.validateGhCli",
"<message>", err) (or include fmt.Errorf("%s: %w", string(output), err) as the
cause) instead of nil.

In `@pkg/release/publishers/npm.go`:
- Line 133: The method signature for NpmPublisher.dryRunPublish includes an
unused parameter cfg *NpmConfig; remove this parameter from the function
signature and all call sites if API compatibility allows, otherwise rename it to
_cfg (or _ in the parameter list) to mark it intentionally unused; update
references to the function (calls and any interface definitions) to match the
new signature and run tests to ensure no call sites are left with the removed
argument.

In `@pkg/release/publishers/scoop.go`:
- Around line 256-261: The code currently swallows all errors from
m.Read(customPath) and silently falls back to the embedded template; change it
so only a "file not found" error is treated as a fallback: call
m.Read(customPath), and if err == nil assign customContent to content, but if
err != nil check whether the error indicates the file is missing (e.g.
os.IsNotExist(err) or the equivalent error from the filesystem implementation)
and only ignore that case; for any other error (permission, I/O, etc.) return or
propagate/log the error so the caller of the scoop publisher (the code path
using m.Read, customPath, and content) can handle it appropriately. Ensure you
reference m.Read and customPath in the updated logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 22eb7003-8627-4296-a381-c3989219b74a

📥 Commits

Reviewing files that changed from the base of the PR and between 86bf184 and 356e531.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (43)
  • cmd/build/cmd_build.go
  • cmd/build/cmd_project.go
  • cmd/build/cmd_pwa.go
  • cmd/build/cmd_release.go
  • cmd/build/cmd_sdk.go
  • cmd/ci/ci.go
  • cmd/ci/cmd.go
  • cmd/sdk/cmd.go
  • go.mod
  • locales/embed.go
  • locales/en.json
  • pkg/build/archive.go
  • pkg/build/builders/cpp.go
  • pkg/build/builders/docker.go
  • pkg/build/builders/go.go
  • pkg/build/builders/linuxkit.go
  • pkg/build/builders/taskfile.go
  • pkg/build/builders/wails.go
  • pkg/build/checksum.go
  • pkg/build/config.go
  • pkg/build/signing/codesign.go
  • pkg/build/signing/gpg.go
  • pkg/build/signing/sign.go
  • pkg/release/changelog.go
  • pkg/release/config.go
  • pkg/release/publishers/aur.go
  • pkg/release/publishers/chocolatey.go
  • pkg/release/publishers/docker.go
  • pkg/release/publishers/github.go
  • pkg/release/publishers/homebrew.go
  • pkg/release/publishers/linuxkit.go
  • pkg/release/publishers/npm.go
  • pkg/release/publishers/scoop.go
  • pkg/release/release.go
  • pkg/release/sdk.go
  • pkg/release/version.go
  • pkg/sdk/detect.go
  • pkg/sdk/diff.go
  • pkg/sdk/generators/go.go
  • pkg/sdk/generators/php.go
  • pkg/sdk/generators/python.go
  • pkg/sdk/generators/typescript.go
  • pkg/sdk/sdk.go

Comment thread pkg/build/builders/docker.go Outdated
Comment on lines 253 to 256
cmd := exec.CommandContext(ctx, "docker", "buildx", "version")
if err := cmd.Run(); err != nil {
return errors.New("docker: buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/")
return coreerr.E("docker.ensureBuildx", "buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/", nil)
}
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 | 🟡 Minor

Consider preserving the original error for diagnostics.

The error from cmd.Run() is discarded by passing nil as the third argument. This loses potentially useful diagnostic information (e.g., permission issues, PATH problems). Line 266 in the same function correctly wraps its error.

🔧 Suggested fix
 	cmd := exec.CommandContext(ctx, "docker", "buildx", "version")
 	if err := cmd.Run(); err != nil {
-		return coreerr.E("docker.ensureBuildx", "buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/", nil)
+		return coreerr.E("docker.ensureBuildx", "buildx is not available. Install it from https://docs.docker.com/buildx/working-with-buildx/", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/docker.go` around lines 253 - 256, The error from
exec.CommandContext(...).Run() is being discarded; update the error return so
the original err is passed into coreerr.E instead of nil. Locate the docker
buildx check (where cmd := exec.CommandContext(ctx, "docker", "buildx",
"version") and if err := cmd.Run(); err != nil { ... }) and change the return to
return coreerr.E("docker.ensureBuildx", "buildx is not available. Install it
from https://docs.docker.com/buildx/working-with-buildx/", err) so the
underlying diagnostic is preserved.

Comment on lines 274 to 279
func validateDockerCli() error {
cmd := exec.Command("docker", "--version")
if err := cmd.Run(); err != nil {
return errors.New("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
return coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from https://docs.docker.com/get-docker/", nil)
}
return nil
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 | 🟡 Minor

Consider preserving the original error for diagnostics.

Same issue as in ensureBuildx: the error from cmd.Run() is discarded. Wrapping it would provide useful context when debugging why the docker CLI check failed.

🔧 Suggested fix
 func validateDockerCli() error {
 	cmd := exec.Command("docker", "--version")
 	if err := cmd.Run(); err != nil {
-		return coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from https://docs.docker.com/get-docker/", nil)
+		return coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from https://docs.docker.com/get-docker/", err)
 	}
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func validateDockerCli() error {
cmd := exec.Command("docker", "--version")
if err := cmd.Run(); err != nil {
return errors.New("docker: docker CLI not found. Install it from https://docs.docker.com/get-docker/")
return coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from https://docs.docker.com/get-docker/", nil)
}
return nil
func validateDockerCli() error {
cmd := exec.Command("docker", "--version")
if err := cmd.Run(); err != nil {
return coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from https://docs.docker.com/get-docker/", err)
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/docker.go` around lines 274 - 279, The docker CLI
validation in validateDockerCli discards the underlying error from cmd.Run();
capture the returned err and pass it into the coreerr.E wrapper so diagnostics
include the original error (i.e., when cmd.Run() returns non-nil, return
coreerr.E("docker.validateDockerCli", "docker CLI not found. Install it from
https://docs.docker.com/get-docker/", err)). This preserves the original error
context for troubleshooting while keeping the existing message and error code.

}

return "", fmt.Errorf("not a GitHub URL: %s", url)
return "", coreerr.E("github.parseGitHubRepo", "not a GitHub URL: "+url, nil)
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

Do not include raw remote URLs in error text.

Line 201 can leak credentials if the remote is tokenised (e.g. HTTPS remotes with embedded auth). Keep the message generic or redact before logging.

Suggested fix
-	return "", coreerr.E("github.parseGitHubRepo", "not a GitHub URL: "+url, nil)
+	return "", coreerr.E("github.parseGitHubRepo", "not a supported GitHub URL", nil)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return "", coreerr.E("github.parseGitHubRepo", "not a GitHub URL: "+url, nil)
return "", coreerr.E("github.parseGitHubRepo", "not a supported GitHub URL", nil)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/github.go` at line 201, The error currently returned
in github.parseGitHubRepo includes the raw remote URL which may leak
credentials; change the return in parseGitHubRepo (the coreerr.E call) to avoid
embedding the raw url by using a generic message like "not a GitHub URL" or
redacting the URL first (e.g., replace userinfo with "<redacted>") before
including it. Update the coreerr.E invocation in github.go to either remove the
"+url" concatenation or call a small helper (e.g., redactRemote(url)) to
sanitize the value so no sensitive auth data is logged.

Comment on lines 301 to 303
if err := cmd.Run(); err != nil {
return errors.New("linuxkit: linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit")
return coreerr.E("linuxkit.validateLinuxKitCli", "linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit", nil)
}
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 | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the current implementation around validateLinuxKitCli and confirm whether the wrapped cause is nil.
awk 'NR>=299 && NR<=304 {print NR ":" $0}' pkg/release/publishers/linuxkit.go

Repository: dAppCore/go-build

Length of output: 349


🏁 Script executed:

find . -type f -name "*.go" | xargs grep -l "package coreerr" | head -5

Repository: dAppCore/go-build

Length of output: 43


🏁 Script executed:

rg "func \(E\|E\w+\)\(" --type go -A 3 | grep -A 3 "coreerr" | head -30

Repository: dAppCore/go-build

Length of output: 43


🏁 Script executed:

rg "coreerr\.E\(" --type go -B 1 -A 1 | head -50

Repository: dAppCore/go-build

Length of output: 2446


Preserve the underlying cmd.Run() error in CLI validation.

Line 302 currently wraps with nil, which drops the actual failure cause from linuxkit version and makes diagnosis harder. The established pattern in the codebase (e.g. typescript.Generate, go.generateNative) is to pass the caught error to coreerr.E() when available.

Suggested patch
 func validateLinuxKitCli() error {
 	cmd := exec.Command("linuxkit", "version")
 	if err := cmd.Run(); err != nil {
-		return coreerr.E("linuxkit.validateLinuxKitCli", "linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit", nil)
+		return coreerr.E("linuxkit.validateLinuxKitCli", "linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit", err)
 	}
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err := cmd.Run(); err != nil {
return errors.New("linuxkit: linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit")
return coreerr.E("linuxkit.validateLinuxKitCli", "linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit", nil)
}
func validateLinuxKitCli() error {
cmd := exec.Command("linuxkit", "version")
if err := cmd.Run(); err != nil {
return coreerr.E("linuxkit.validateLinuxKitCli", "linuxkit CLI not found. Install it from https://github.com/linuxkit/linuxkit", err)
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/release/publishers/linuxkit.go` around lines 301 - 303, The linuxkit CLI
validation currently discards the underlying error returned by cmd.Run(); update
the error wrap so the actual err is passed into coreerr.E(...) instead of nil.
Locate the block where cmd.Run() is executed (the validation around linuxkit
version) and change the coreerr.E call to include the caught err as the third
argument so the original failure is preserved for diagnostics.

Snider and others added 2 commits March 17, 2026 13:46
- chocolatey: pass API key via env var instead of CLI arg
- npm: remove unused cfg parameter from dryRunPublish
- signing: include checksums file path in error message
- codesign: provide specific reason when codesign unavailable
- scoop: handle error from custom template read
- wails: wrap Read/Write errors with coreerr.E
- github: include actual error in validateGhCli coreerr.E calls
- docker: include actual error in validate/buildx coreerr.E calls

Co-Authored-By: Virgil <virgil@lethean.io>
…fy each against current code, f...' (#2) from agent/fix-coderabbit-findings--verify-each-aga into main
@Snider
Copy link
Copy Markdown
Contributor Author

Snider commented Mar 17, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Snider Snider merged commit 83e4521 into main Mar 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant