Skip to content

feat(speedtest): add result URL support for LibreSpeed#216

Open
s0up4200 wants to merge 6 commits into
developfrom
feat/librespeed-result-url
Open

feat(speedtest): add result URL support for LibreSpeed#216
s0up4200 wants to merge 6 commits into
developfrom
feat/librespeed-result-url

Conversation

@s0up4200

@s0up4200 s0up4200 commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator

Captures the shareable link from librespeed-cli --share, stores it in a new result_url column, and shows it as a clickable icon next to the server name in the results table.

The --share flag is opt-in since it sends telemetry to librespeed.org. Enable it by setting share_results = true under [speedtest.librespeed] in your config, or via the LIBRESPEED_SHARE_RESULTS=true env var. Disabled by default.

Closes #159

Summary by CodeRabbit

  • New Features

    • Added a configurable toggle to enable/disable sharing speed test results to librespeed.org.
    • Speed test listings show a shareable external link when a result URL is available.
  • Database

    • Added a nullable result_url column to persist shareable result links.
  • Documentation

    • Documented the new LibreSpeed share-results configuration option.
  • Tests

    • Added unit, integration, and migration tests covering result URL handling and migrations.

Capture the shareable link returned by librespeed-cli --share, persist it
in a new result_url column, and render it as a clickable icon in the
results table. The --share flag is opt-in via share_results config.
@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

This PR was authored by the user configured for CodeRabbit reviews. CodeRabbit does not review PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0335b2a1-c2ce-4253-94c8-79353552b09d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

This PR implements opt-in result sharing for LibreSpeed speed tests by adding a share_results configuration toggle, capturing shareable URLs from the LibreSpeed CLI, persisting them to the database, and displaying clickable links in the web UI.

Changes

Librespeed Result Sharing Feature

Layer / File(s) Summary
Configuration and Database Schema
README.md, internal/database/migrations/sqlite/022_add_result_url.sql, internal/database/migrations/postgres/022_add_result_url_postgres.sql
New share_results config key (defaults to false) and environment variable documented; schema migrations add nullable result_url column to speed_tests table for both SQLite and Postgres.
Type Contracts Across Stack
internal/speedtest/types.go, web/src/types/types.ts
Result struct adds ResultURL string field; backend SpeedTestResult adds optional ResultURL *string pointer; frontend SpeedTestResult interface adds optional resultUrl?: string property for JSON serialization.
LibreSpeed CLI and Result Parsing
internal/speedtest/librespeed.go, internal/speedtest/librespeed_test.go
Runner conditionally appends --share flag when config.ShareResults is enabled; captures stdout/stderr separately and extracts JSON from stdout using extractJSONArray; normalizes share URL via sanitizeResultURL to validate http/https schemes; unit tests verify --share flag toggling and URL validation/normalization including scheme detection and host validation.
Result Persistence and Database
internal/speedtest/result_handler_test.go, internal/database/speedtest_integration_test.go
Result handler captures ResultURL and converts empty strings to nil pointers before persisting; integration test verifies round-trip behavior for both populated and nil ResultURL values through save/retrieve cycle.
Frontend UI Components
web/src/components/speedtest/columns.tsx
Desktop and mobile table cells conditionally render external-link icons that open result URLs in new tabs when resultUrl is present; styling uses inline-flex layout with proper accessibility attributes (aria-label, title) and click propagation control.
Migration Validation
internal/database/migrations/migrations_test.go
New test validates all migration filenames contain numeric version prefixes and no two migrations share the same version, preventing silent skip-over during upgrades.

Sequence Diagram

sequenceDiagram
  participant Runner as LibrespeedRunner
  participant CLI as librespeed-cli
  participant Extract as extractJSONArray
  participant Sanitize as sanitizeResultURL
  Runner->>CLI: execCmd with --share flag (if config.ShareResults)
  CLI-->>Runner: stdout with JSON array, stderr
  Runner->>Extract: extract JSON from stdout
  Extract-->>Runner: JSON slice from first [
  Runner->>Runner: unmarshal JSON to librespeedResult
  Runner->>Sanitize: sanitizeResultURL(librespeedResult.Share)
  Sanitize-->>Runner: normalized http/https URL or empty string
  Runner-->>Runner: set Result.ResultURL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops through configs bright,
Where sharing flags now come to light,
Test results dance with speedy URLs,
Displayed with links that curl and whirl,
Shareable swiftness, ready to send! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description explains what, why, and how the feature works, but does not follow the provided template structure with Summary, Why, Testing, and Checklist sections. Restructure the description to follow the template format with labeled sections: Summary, Why, Testing checklist, and Checklist items for verification.
Out of Scope Changes check ❓ Inconclusive All changes are directly related to implementing result URL support; however, a migration duplicate-check test was added that is tangentially related but not core to the issue. Clarify whether the duplicate migration version test is necessary for this feature or should be addressed separately to maintain narrow PR scope.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding result URL support for LibreSpeed with proper scope and specificity.
Linked Issues check ✅ Passed The PR fully addresses issue #159 by capturing shareable links from librespeed-cli, storing them in a result_url column, and displaying them as clickable icons in the results table UI.

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


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

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/speedtest/librespeed_test.go (1)

32-58: Consolidate the share-flag tests into a single table-driven test.

Line 32 through Line 58 add two near-identical cases that differ only by ShareResults and expectation. A table-driven test will keep this path easier to extend and maintain.

♻️ Proposed refactor
-func TestBuildArgsIncludesShareWhenEnabled(t *testing.T) {
-	runner := NewLibrespeedRunner(config.LibrespeedConfig{
-		ServersPath:  "/tmp/local-servers.json",
-		ShareResults: true,
-	})
-
-	args := runner.buildArgs(&types.TestOptions{
-		IsPublicServer: true,
-		ServerIDs:      []string{"123"},
-	})
-
-	assert.Contains(t, args, "--share")
-}
-
-func TestBuildArgsExcludesShareWhenDisabled(t *testing.T) {
-	runner := NewLibrespeedRunner(config.LibrespeedConfig{
-		ServersPath:  "/tmp/local-servers.json",
-		ShareResults: false,
-	})
-
-	args := runner.buildArgs(&types.TestOptions{
-		IsPublicServer: true,
-		ServerIDs:      []string{"123"},
-	})
-
-	assert.NotContains(t, args, "--share")
-}
+func TestBuildArgsShareFlag(t *testing.T) {
+	tests := []struct {
+		name        string
+		share       bool
+		shouldShare bool
+	}{
+		{name: "includes --share when enabled", share: true, shouldShare: true},
+		{name: "excludes --share when disabled", share: false, shouldShare: false},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			runner := NewLibrespeedRunner(config.LibrespeedConfig{
+				ServersPath:  "/tmp/local-servers.json",
+				ShareResults: tt.share,
+			})
+
+			args := runner.buildArgs(&types.TestOptions{
+				IsPublicServer: true,
+				ServerIDs:      []string{"123"},
+			})
+
+			if tt.shouldShare {
+				assert.Contains(t, args, "--share")
+			} else {
+				assert.NotContains(t, args, "--share")
+			}
+		})
+	}
+}

Based on learnings: Applies to **/*_test.go : Prefer table-driven tests for new backend logic.

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

In `@internal/speedtest/librespeed_test.go` around lines 32 - 58, The two
near-identical tests TestBuildArgsIncludesShareWhenEnabled and
TestBuildArgsExcludesShareWhenDisabled should be consolidated into a single
table-driven test: create a slice of cases that set
config.LibrespeedConfig.ShareResults to true/false with an expectedContains
bool, construct the runner via NewLibrespeedRunner, call runner.buildArgs with
the same TestOptions, and for each case assert that args contains "--share" when
expectedContains is true and does not contain it when false; keep references to
the same TestOptions (IsPublicServer/serverIDs) and use t.Run with a descriptive
name per case.
🤖 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/speedtest/librespeed.go`:
- Line 154: The code is assigning external data librespeedResult.Share directly
into ResultURL; validate and sanitize this URL before persisting by parsing
librespeedResult.Share with net/url (url.Parse), verify the scheme is http or
https and the Host is non-empty, reject or clear the value if parsing fails or
the scheme/host are invalid, and optionally re-encode with url.URL.String() to
ensure a normalized safe form; update the assignment to use the
validated/sanitized value (the place where ResultURL is set from
librespeedResult.Share).

In `@web/src/components/speedtest/columns.tsx`:
- Around line 76-84: The icon-only result links in columns.tsx (the anchor using
row.original.resultUrl and the ExternalLink icon) lack a reliable accessible
name; add an aria-label (e.g., aria-label="View result on LibreSpeed") to those
<a> elements or include visually hidden text inside the anchor so screen readers
can identify the action; update both occurrences (the one referencing
row.original.resultUrl and the second occurrence around lines 176-184) to
include the aria-label or hidden text while keeping the existing title and
stopPropagation behavior.

---

Nitpick comments:
In `@internal/speedtest/librespeed_test.go`:
- Around line 32-58: The two near-identical tests
TestBuildArgsIncludesShareWhenEnabled and TestBuildArgsExcludesShareWhenDisabled
should be consolidated into a single table-driven test: create a slice of cases
that set config.LibrespeedConfig.ShareResults to true/false with an
expectedContains bool, construct the runner via NewLibrespeedRunner, call
runner.buildArgs with the same TestOptions, and for each case assert that args
contains "--share" when expectedContains is true and does not contain it when
false; keep references to the same TestOptions (IsPublicServer/serverIDs) and
use t.Run with a descriptive name per case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23a6a50a-4f22-4d26-96e6-9cbcd93eea05

📥 Commits

Reviewing files that changed from the base of the PR and between bf756a6 and cca65ef.

📒 Files selected for processing (13)
  • config/config.toml
  • internal/config/config.go
  • internal/database/migrations/postgres/021_add_result_url_postgres.sql
  • internal/database/migrations/sqlite/021_add_result_url.sql
  • internal/database/speedtest.go
  • internal/speedtest/librespeed.go
  • internal/speedtest/librespeed_test.go
  • internal/speedtest/result_handler.go
  • internal/speedtest/result_handler_test.go
  • internal/speedtest/types.go
  • internal/types/types.go
  • web/src/components/speedtest/columns.tsx
  • web/src/types/types.ts

Comment thread internal/speedtest/librespeed.go Outdated
Comment thread web/src/components/speedtest/columns.tsx
…n test

Validate librespeed share URLs with net/url before persisting (reject
non-http(s) or missing host). Add aria-label to icon-only result links
for screen readers. Consolidate share flag tests into table-driven form.

@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 (1)
internal/speedtest/librespeed.go (1)

338-350: Consider trimming whitespace for defensive parsing.

While JSON unmarshaling typically doesn't introduce leading/trailing whitespace, adding strings.TrimSpace would make the function more robust against malformed CLI output.

♻️ Optional hardening
 func sanitizeResultURL(raw string) string {
-	if raw == "" {
+	raw = strings.TrimSpace(raw)
+	if raw == "" {
 		return ""
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/speedtest/librespeed.go` around lines 338 - 350, The
sanitizeResultURL function should defensively trim leading/trailing whitespace
before parsing to avoid url.Parse errors on malformed CLI output; update
sanitizeResultURL (and add strings import if missing) to call
strings.TrimSpace(raw) and then parse the trimmed string, preserving the same
scheme/host checks and return behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/speedtest/librespeed.go`:
- Around line 338-350: The sanitizeResultURL function should defensively trim
leading/trailing whitespace before parsing to avoid url.Parse errors on
malformed CLI output; update sanitizeResultURL (and add strings import if
missing) to call strings.TrimSpace(raw) and then parse the trimmed string,
preserving the same scheme/host checks and return behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de91d21c-0797-4bfc-9058-18566a30833c

📥 Commits

Reviewing files that changed from the base of the PR and between cca65ef and b20e8f9.

📒 Files selected for processing (3)
  • internal/speedtest/librespeed.go
  • internal/speedtest/librespeed_test.go
  • web/src/components/speedtest/columns.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/speedtest/librespeed_test.go
  • web/src/components/speedtest/columns.tsx

librespeed-cli prints telemetry error text to stdout before the JSON
when --share is used. Find the JSON array start before unmarshaling.
@s0up4200 s0up4200 marked this pull request as draft March 31, 2026 21:21
s0up4200 added 2 commits May 31, 2026 18:41
…ipped on upgrade)

develop already ships 021_packetloss_history_summary_index, and the migrator
applies migrations by position relative to the applied count (it never reads
migration names back). The duplicate 021_add_result_url sorted before the
already-applied packetloss index, so on existing databases it was silently
skipped: result_url was never created and every SaveSpeedTest/GetSpeedTests
then failed on the missing column (speed test history broke after upgrade).
Fresh installs applied all migrations in order, masking the bug in CI.

Renumber to 022 for both dialects so the new migration always sorts last and
is applied on upgrade. Add a migrations test rejecting duplicate version
prefixes, plus a DB round-trip test for result_url.

Also fixes other review findings for this PR:
- speedtest: read librespeed-cli output from stdout instead of CombinedOutput
  so stderr telemetry errors (e.g. an IPv6 endpoint with '[') can't corrupt
  JSON parsing; extract the JSON-array trimming into a tested helper.
- speedtest: replace the tautological result-URL test with one that exercises
  DefaultResultHandler.SaveResult; pin sanitizeResultURL normalization cases.
- web: keep server-name ellipsis when a result link is present (move truncate
  to a shrinkable child of the inline-flex container; was clipping without '…').
- docs: document NETRONOME__LIBRESPEED_SHARE_RESULTS.
@s0up4200 s0up4200 marked this pull request as ready for review May 31, 2026 19:43

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

Actionable comments posted: 2

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

Inline comments:
In `@internal/speedtest/librespeed.go`:
- Line 133: The log call currently emits raw librespeed-cli stdout/stderr
(log.Error().Err(err).Str("stdout", stdout.String()).Str("stderr",
stderr.String()).Msg("librespeed-cli failed")), which can leak
client-identifying JSON and share URLs; update the error handling in the
function that invokes the LibreSpeed CLI to stop logging full stdout/stderr —
either remove those .Str("stdout", ...) and .Str("stderr", ...) fields entirely,
or replace them with a sanitized/limited value (e.g., a short truncated string
or a redacted/sanitizer function that strips URLs and known client fields) and
keep the Err(err) and contextual message; ensure the change touches the same
variables (stdout, stderr) and the LibreSpeed invocation site so no raw payloads
are written to logs.
- Line 134: Wrap the returned error using %w so callers can unwrap the original
error (replace fmt.Errorf("...%v...", err, ...) with fmt.Errorf("...: %w", err)
in the function that invokes the librespeed-cli return), and remove any logging
that prints raw libre­speed-cli stdout/stderr (do not log
strings.TrimSpace(stderr.String()) or stdout contents); instead log a
non-sensitive message such as the command exit status or an anonymized failure
note from the same function (identify and update the error return and the
logging statements around the librespeed-cli invocation in
internal/speedtest/librespeed.go).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cf76f7df-11d2-4aed-95d6-8f0d0bd1011c

📥 Commits

Reviewing files that changed from the base of the PR and between 2d83cd0 and 5b9fabd.

📒 Files selected for processing (11)
  • README.md
  • internal/database/migrations/migrations_test.go
  • internal/database/migrations/postgres/022_add_result_url_postgres.sql
  • internal/database/migrations/sqlite/022_add_result_url.sql
  • internal/database/speedtest_integration_test.go
  • internal/speedtest/librespeed.go
  • internal/speedtest/librespeed_test.go
  • internal/speedtest/result_handler_test.go
  • internal/types/types.go
  • web/src/components/speedtest/columns.tsx
  • web/src/types/types.ts
💤 Files with no reviewable changes (2)
  • internal/database/migrations/postgres/022_add_result_url_postgres.sql
  • internal/database/migrations/sqlite/022_add_result_url.sql
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • web/src/types/types.ts
  • internal/database/speedtest_integration_test.go
  • internal/types/types.go
  • web/src/components/speedtest/columns.tsx
  • internal/speedtest/result_handler_test.go

cmd.Stderr = &stderr

if err := cmd.Run(); err != nil {
log.Error().Err(err).Str("stdout", stdout.String()).Str("stderr", stderr.String()).Msg("librespeed-cli failed")

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 | ⚡ Quick win

Avoid logging raw LibreSpeed stdout/stderr payloads.

Line 133 and Line 139 log full process output. That output can include client-identifying JSON fields and share URLs, which is a privacy/compliance risk in logs.

Suggested hardening
-		log.Error().Err(err).Str("stdout", stdout.String()).Str("stderr", stderr.String()).Msg("librespeed-cli failed")
+		log.Error().
+			Err(err).
+			Int("stdout_bytes", stdout.Len()).
+			Int("stderr_bytes", stderr.Len()).
+			Str("stderr", strings.TrimSpace(stderr.String())).
+			Msg("librespeed-cli failed")
@@
-	log.Debug().Str("stdout", stdout.String()).Str("stderr", stderr.String()).Msg("librespeed-cli output")
+	log.Debug().
+		Int("stdout_bytes", stdout.Len()).
+		Int("stderr_bytes", stderr.Len()).
+		Msg("librespeed-cli output captured")

Also applies to: 139-139

🤖 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 `@internal/speedtest/librespeed.go` at line 133, The log call currently emits
raw librespeed-cli stdout/stderr (log.Error().Err(err).Str("stdout",
stdout.String()).Str("stderr", stderr.String()).Msg("librespeed-cli failed")),
which can leak client-identifying JSON and share URLs; update the error handling
in the function that invokes the LibreSpeed CLI to stop logging full
stdout/stderr — either remove those .Str("stdout", ...) and .Str("stderr", ...)
fields entirely, or replace them with a sanitized/limited value (e.g., a short
truncated string or a redacted/sanitizer function that strips URLs and known
client fields) and keep the Err(err) and contextual message; ensure the change
touches the same variables (stdout, stderr) and the LibreSpeed invocation site
so no raw payloads are written to logs.


if err := cmd.Run(); err != nil {
log.Error().Err(err).Str("stdout", stdout.String()).Str("stderr", stderr.String()).Msg("librespeed-cli failed")
return nil, fmt.Errorf("librespeed-cli failed: %v: %s", err, strings.TrimSpace(stderr.String()))

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 | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify non-wrapping fmt.Errorf usages where an error variable is formatted with %v/%s.
rg -nP --type=go 'fmt\.Errorf\([^)]*%[vs][^)]*,\s*err\b'

Repository: autobrr/netronome

Length of output: 1178


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the error site and nearby stdout/stderr handling
sed -n '110,170p' internal/speedtest/librespeed.go

# Also show any logging around where stdout/stderr is handled, if farther away
rg -n 'stdout|stderr|TrimSpace\(stderr\.String\(\)\)|TrimSpace\(stdout\.String\(\)\)|librespeed-cli' internal/speedtest/librespeed.go -n

Repository: autobrr/netronome

Length of output: 4013


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show LibrespeedResult definition
rg -n "type LibrespeedResult|LibrespeedResult struct" internal/speedtest/librespeed.go
sed -n '170,260p' internal/speedtest/librespeed.go
sed -n '260,420p' internal/speedtest/librespeed.go

Repository: autobrr/netronome

Length of output: 6431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the LibrespeedResult struct and related types near the top of the file
sed -n '1,120p' internal/speedtest/librespeed.go

# Confirm which client-identifying fields exist in the JSON struct
rg -n --fixed-strings 'json:"ip"' internal/speedtest/librespeed.go
rg -n --fixed-strings 'json:"hostname"' internal/speedtest/librespeed.go
rg -n --fixed-strings 'json:"location"' internal/speedtest/librespeed.go
rg -n 'Share|share' internal/speedtest/librespeed.go

Repository: autobrr/netronome

Length of output: 3476


Fix error wrapping and stop logging sensitive librespeed output

  • Wrap err with %w (line 134) so callers can unwrap the original failure.
  • Don’t log raw librespeed-cli stdout/stderr (lines 133 and 139): the CLI JSON includes client details (ip, hostname, city/region/country, loc, etc.) and share, which can leak into logs.
Suggested fix
-		return nil, fmt.Errorf("librespeed-cli failed: %v: %s", err, strings.TrimSpace(stderr.String()))
+		return nil, fmt.Errorf("librespeed-cli failed: %w: %s", err, strings.TrimSpace(stderr.String()))
📝 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 nil, fmt.Errorf("librespeed-cli failed: %v: %s", err, strings.TrimSpace(stderr.String()))
return nil, fmt.Errorf("librespeed-cli failed: %w: %s", err, strings.TrimSpace(stderr.String()))
🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 134-134: non-wrapping format verb for fmt.Errorf. Use %w to format errors

(errorlint)

🤖 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 `@internal/speedtest/librespeed.go` at line 134, Wrap the returned error using
%w so callers can unwrap the original error (replace fmt.Errorf("...%v...", err,
...) with fmt.Errorf("...: %w", err) in the function that invokes the
librespeed-cli return), and remove any logging that prints raw libre­speed-cli
stdout/stderr (do not log strings.TrimSpace(stderr.String()) or stdout
contents); instead log a non-sensitive message such as the command exit status
or an anonymized failure note from the same function (identify and update the
error return and the logging statements around the librespeed-cli invocation in
internal/speedtest/librespeed.go).

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.

FR: Add public link to speedtest results if server supports it

1 participant