Skip to content

v0.4.0: hardened backends, IsNonCritical, testable CLI#8

Merged
github-actions[bot] merged 4 commits into
mainfrom
dev
Jun 4, 2026
Merged

v0.4.0: hardened backends, IsNonCritical, testable CLI#8
github-actions[bot] merged 4 commits into
mainfrom
dev

Conversation

@mar0ls
Copy link
Copy Markdown
Owner

@mar0ls mar0ls commented Jun 4, 2026

Validated on macOS, Linux GNOME and Windows 11. Windows AutoConfigURL fix, KDE write, IsNonCritical, CLI refactor (coverage 64.6%→72.2%), README/GoDoc cleanup, CI cache fix.

mar0ls added 4 commits May 5, 2026 17:21
Validated on real macOS, Linux GNOME and Windows 11 machines.

Library:
- Add IsNonCritical(err) + nonCriticalError to distinguish a failed
  /etc/environment write (no root) from a hard failure on Linux
- Linux: write KDE proxy settings via kwriteconfig5 alongside gsettings,
  so hybrid GNOME/KDE setups work without desktop detection; return the
  /etc/environment failure as a non-critical error
- Windows: clear AutoConfigURL on set/unset so a previous PAC URL no
  longer persists after switching to manual proxy or unsetting

CLI:
- Extract dispatch into a testable run(argv, stdout, stderr) int instead
  of calling os.Exit directly; cmd/sysproxy coverage 12% -> 61%

Docs/tests:
- README: trim the alternatives table to a single named comparison and
  document SetPAC vs Get/GetConfig auto-proxy behavior
- Add IsNonCritical, CLI run() and example tests
- buildinfo: doc comment follows Go convention

Total coverage 64.6% -> 72.2%; golangci-lint clean; go test -race green.
Silences the 'Restore cache failed: Dependencies file is not found ... go.sum' warning on every job. The module has no external dependencies, so there is nothing to cache.
Copilot AI review requested due to automatic review settings June 4, 2026 16:15
@github-actions github-actions Bot merged commit 034fb8f into main Jun 4, 2026
25 checks passed
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 21.66667% with 47 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
sysproxy_linux.go 0.00% 47 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR prepares the v0.4.0 release by hardening OS-specific proxy backends, introducing a “non-critical error” classification for best-effort operations, and refactoring the sysproxy CLI to be unit-testable while improving JSON output/docs.

Changes:

  • Add IsNonCritical(err) and use it in Linux global set/unset when /etc/environment cannot be written/cleared (best-effort behavior).
  • Improve platform behavior: Windows clears AutoConfigURL when switching to manual proxy; Linux writes GNOME+KDE config without desktop detection; macOS clears stale host/port fields on unset.
  • Refactor CLI to a run(argv, stdout, stderr) entrypoint (testable), and adjust get --json to emit a per-protocol JSON object.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sysproxy.go Adds JSON tags to ProxyConfig to support stable --json output keys.
sysproxy_windows.go Clears AutoConfigURL when setting/unsetting manual proxy modes.
sysproxy_linux.go Removes desktop detection; applies GNOME+KDE config when tools exist; wraps /etc/environment failures as non-critical.
sysproxy_darwin.go Clears proxy host/port fields on unset to avoid stale values in System Settings UI.
README.md Documents PAC vs manual reporting behavior and updated Linux/non-critical semantics; adds comparison table.
internal/buildinfo/buildinfo.go Clarifies which variables are injected via -ldflags.
example_test.go Adds additional API usage examples (Get, GetConfig, SetPAC).
errors.go Introduces nonCriticalError and exported IsNonCritical.
errors_test.go Adds unit tests validating non-critical error detection and unwrap behavior.
cmd/sysproxy/main.go Refactors CLI into a testable run function; updates JSON output shape for get.
cmd/sysproxy/main_test.go Updates CLI integration tests for the new JSON output shape.
cmd/sysproxy/helpers_test.go Adds unit tests for CLI helpers and run dispatch/error paths.
.gitignore Ignores local smoke-test artifacts.
.github/workflows/test.yml Disables setup-go caching and removes Codecov token usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sysproxy_linux.go
Comment on lines +146 to +160
if isAvailable("gsettings") {
if cfg.HTTP != "" {
_ = runGsettings(ctx, "set", "org.gnome.system.proxy", "mode", "manual")
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.http", "host", hostFromURL(cfg.HTTP))
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.http", "port", portFromURL(cfg.HTTP))
}
if cfg.HTTPS != "" {
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.https", "host", hostFromURL(cfg.HTTPS))
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.https", "port", portFromURL(cfg.HTTPS))
}
if cfg.SOCKS != "" {
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.socks", "host", hostFromURL(cfg.SOCKS))
_ = runGsettings(ctx, "set", "org.gnome.system.proxy.socks", "port", portFromURL(cfg.SOCKS))
}
}
Comment thread cmd/sysproxy/main.go
Comment on lines 137 to +141
if err := sysproxy.SetContext(ctx, proxyURL, scope); err != nil {
dieJSON(jsonOut, "set failed: "+err.Error())
return dieJSON(jsonOut, "set failed: "+err.Error(), stdout, stderr)
}
printOK(jsonOut, map[string]any{"proxy": proxyURL, "scope": scope.String()})
printOK(jsonOut, map[string]any{"proxy": proxyURL, "scope": scope.String()}, stdout)
return 0
Comment thread cmd/sysproxy/main.go
Comment on lines 171 to +175
if err := sysproxy.UnsetContext(ctx, scope); err != nil {
dieJSON(jsonOut, "unset failed: "+err.Error())
return dieJSON(jsonOut, "unset failed: "+err.Error(), stdout, stderr)
}
printOK(jsonOut, map[string]any{"scope": scope.String()})
printOK(jsonOut, map[string]any{"scope": scope.String()}, stdout)
return 0
Comment thread cmd/sysproxy/main_test.go
Comment on lines +122 to 127
if _, hasErr := m["error"]; hasErr {
return
}
if _, hasHTTP := m["http"]; !hasHTTP {
t.Errorf("JSON output missing 'http' or 'error' key: %v", m)
}
Comment on lines +14 to +33
func captureStdout(t *testing.T, fn func()) string {
t.Helper()
orig := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("pipe: %v", err)
}
os.Stdout = w
t.Cleanup(func() {
os.Stdout = orig
})

fn()
_ = w.Close()

var buf bytes.Buffer
_, _ = io.Copy(&buf, r)
_ = r.Close()
return buf.String()
}
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.

2 participants