Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces golangci-lint to the repository (config + CI job) and updates Go code/tests to satisfy the newly-enabled linters (error handling, type-assert linting, header canonicalization, comment/style tweaks).
Changes:
- Add
.golangci.ymland a new GitHub Actionslintjob running golangci-lint. - Refactor various functions to avoid naked returns, improve error comparisons (
errors.Is/As), and make error strings/comment text linter-friendly. - Update tests/benchmarks to properly ignore checked errors, use canonical HTTP header keys, and add helper markers (
t.Helper/b.Helper).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| utils.go | Simplifies DEBUG var declaration (now a single var). |
| stream.go | Removes var block, removes naked returns, tweaks docs and error creation. |
| spdy_test.go | Canonicalizes header keys, switches to errors.Is, and explicitly ignores returned errors. |
| spdy_bench_test.go | Adds b.Helper(), reorders helper args, and explicitly ignores returned errors. |
| spdy/write.go | Removes named returns/naked returns and adds explicit error returns; refactors header block writer signature. |
| spdy/types.go | Fixes/aligns doc comments and removes redundant []byte(...) conversions for header dictionary. |
| spdy/spdy_test.go | Uses errors.Is/As, ignores unused return values, and adds t.Helper(). |
| spdy/read.go | Uses errors.Is for EOF checks and removes redundant []byte(...) conversions. |
| priority_test.go | Adds forcetypeassert suppression and avoids repeated type assertions. |
| priority.go | Adds forcetypeassert suppression and minor increment simplification. |
| handlers.go | Explicitly ignores io.Copy/Close errors; fixes handler comment casing. |
| connection.go | Normalizes error strings, improves EOF checking, explicitly ignores some return values, and updates docs. |
| .golangci.yml | Adds golangci-lint configuration (enabled linters, exclusions, formatter). |
| .github/workflows/ci.yaml | Adds a new lint job that runs golangci-lint in CI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR adds golangci-lint to CI and updates the Go codebase to satisfy stricter linting rules (error handling, doc comments, formatting, and test robustness).
Changes:
- Add
.golangci.ymland a new CIlintjob running golangci-lint. - Refactor multiple code paths to avoid naked returns, use
errors.Is/As, and addresserrcheck/forcetypeassertfindings. - Improve/standardize GoDoc and comments for exported identifiers and public-facing behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| utils.go | Simplifies DEBUG var declaration (lint-related cleanup). |
| stream.go | Adds GoDoc for ErrUnreadPartialData and removes naked returns. |
| spdy_test.go | Updates tests for canonical headers and stronger error comparisons; addresses unchecked errors. |
| spdy_bench_test.go | Cleans up benchmarks (helper usage, unchecked errors, signature changes). |
| spdy/write.go | Refactors many writers to return explicit errors (avoid naked returns, appease linters). |
| spdy/types.go | Fixes comments/identifiers and removes unnecessary []byte() conversions. |
| spdy/spdy_test.go | Improves test error matching (errors.Is/As) and marks helpers. |
| spdy/read.go | Uses errors.Is for EOF comparisons and removes redundant conversions. |
| priority_test.go | Tightens type assertions (with linter suppression where appropriate). |
| priority.go | Addresses forcetypeassert and simplifies increment logic. |
| handlers.go | Checks/ignores return values explicitly and fixes NoOp naming in comment. |
| connection.go | Refines error strings/comments; replaces some error comparisons with errors.Is; avoids naked returns. |
| .golangci.yml | Introduces golangci-lint configuration and enabled linters/formatters. |
| .github/workflows/ci.yaml | Adds a new lint job running golangci-lint in CI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Some of these should probably be looked at, but removing error returns
from the signature results in code-churn that may have to be changed
if these should produce errors.
connection.go:517:66: (*Connection).handleReplyFrame - result 0 (error) is always nil (unparam)
func (s *Connection) handleReplyFrame(frame *spdy.SynReplyFrame) error {
^
connection.go:541:67: (*Connection).handleResetFrame - result 0 (error) is always nil (unparam)
func (s *Connection) handleResetFrame(frame *spdy.RstStreamFrame) error {
^
connection.go:563:66: (*Connection).handleHeaderFrame - result 0 (error) is always nil (unparam)
func (s *Connection) handleHeaderFrame(frame *spdy.HeadersFrame) error {
^
connection.go:634:65: (*Connection).handleGoAwayFrame - result 0 (error) is always nil (unparam)
func (s *Connection) handleGoAwayFrame(frame *spdy.GoAwayFrame) error {
^
spdy/write.go:155:57: writeHeaderValueBlock - result n is never used (unparam)
func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
There was a problem hiding this comment.
Pull request overview
This PR introduces golangci-lint to CI and applies a set of code/test adjustments across the repository to satisfy new linting and formatting rules (e.g., errcheck, errorlint, forcetypeassert, nakedret, header canonicalization).
Changes:
- Add
golangci-lintconfiguration and a dedicated CI “lint” job. - Refactor production Go code to remove naked returns, improve error handling patterns, and satisfy type-assertion lint rules.
- Update tests/benchmarks to check/ignore errors consistently, use
errors.Is/As, and follow canonical header key conventions.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
utils.go |
Simplifies DEBUG declaration to satisfy style/lint expectations. |
stream.go |
Improves docs and replaces naked returns with explicit returns / errors.New. |
spdy_test.go |
Updates tests for errors.Is, header canonicalization, errcheck compliance, and safer hijacking. |
spdy_bench_test.go |
Bench helper signature cleanup, adds b.Helper(), and errcheck compliance. |
spdy/write.go |
Refactors multiple write methods to avoid naked returns; adjusts header block writer signature/returns. |
spdy/types.go |
Fixes comments/typos, aligns terminology, and removes redundant []byte() conversions. |
spdy/spdy_test.go |
Updates assertions to errors.As/Is and marks helper functions appropriately. |
spdy/read.go |
Uses errors.Is for EOF comparisons and removes redundant dictionary conversions. |
priority_test.go |
Adjusts type assertions to satisfy forcetypeassert. |
priority.go |
Adds checked type assertions to satisfy forcetypeassert; minor increment simplification. |
handlers.go |
Errcheck compliance for io.Copy, Close, and SendReply; fixes GoDoc name. |
connection.go |
Error string normalization, errcheck cleanups, errors.Is/As usage, and minor style fixes. |
.golangci.yml |
Adds golangci-lint v2 config enabling specific linters/formatters and exclusions. |
.github/workflows/ci.yaml |
Adds a CI lint job running golangci-lint alongside tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var frame spdy.Frame | ||
| if f, ok := heap.Pop(q.queue).(*prioritizedFrame); ok { | ||
| frame = f.frame | ||
| } | ||
| q.c.Signal() | ||
| return frame |
There was a problem hiding this comment.
PriorityFrameQueue.Pop() silently returns a nil frame if the heap.Pop() result isn't a *prioritizedFrame. Returning nil here is risky because callers treat nil as the drain/stop signal (see frameHandler), so an unexpected type would make workers exit early and drop frames. Consider failing fast (e.g., panic like frameQueue.Push does) or otherwise handling the impossible case explicitly rather than returning nil.
| var frame spdy.Frame | |
| if f, ok := heap.Pop(q.queue).(*prioritizedFrame); ok { | |
| frame = f.frame | |
| } | |
| q.c.Signal() | |
| return frame | |
| f, ok := heap.Pop(q.queue).(*prioritizedFrame) | |
| if !ok || f == nil { | |
| panic("PriorityFrameQueue.Pop: unexpected value") | |
| } | |
| q.c.Signal() | |
| return f.frame |
| var sid spdy.StreamId | ||
| if frame, ok := queue.Pop().(*spdy.DataFrame); ok { | ||
| sid = frame.StreamId | ||
| } | ||
| if sid != i { | ||
| t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", sid, i) |
There was a problem hiding this comment.
In this test, the type assertion result is ignored when queue.Pop() doesn't return *spdy.DataFrame (it just leaves sid at 0). If the queue returns an unexpected type, this will produce a misleading ordering failure (or could even pass for i==0) rather than clearly indicating the wrong type. Consider failing the test immediately when the assertion fails (or use t.Helper() + a small helper) so the failure message points to the real issue.
| var sid spdy.StreamId | ||
| if frame, ok := queue.Pop().(*spdy.DataFrame); ok { | ||
| sid = frame.StreamId | ||
| } | ||
| if sid != i { | ||
| t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", sid, i) |
There was a problem hiding this comment.
Same issue as above: if queue.Pop() doesn't return *spdy.DataFrame, the test silently proceeds with sid == 0, which can hide the actual problem and give a confusing failure. Prefer failing immediately when the type assertion fails so the test reports an unexpected type rather than an ordering mismatch.
| } | ||
| if !f.headerCompressionDisabled { | ||
| f.headerCompressor.Flush() | ||
| _ = f.headerCompressor.Flush() |
There was a problem hiding this comment.
zlib.Writer.Flush() can return an error. Assigning it to _ satisfies errcheck but discards potentially important write/compression failures, which could lead to corrupted frames being sent without reporting an error. Consider returning the flush error (or wrapping it) so WriteFrame callers can handle it.
| _ = f.headerCompressor.Flush() | |
| if err := f.headerCompressor.Flush(); err != nil { | |
| return err | |
| } |
| hj, ok := w.(http.Hijacker) | ||
| if !ok { | ||
| t.Fatal("ResponseWriter should be a http.Hijacker") | ||
| } | ||
| netconn, _, err := hj.Hijack() | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } |
There was a problem hiding this comment.
This HTTP handler runs in its own goroutine, so calling t.Fatal here can cause the handler goroutine to exit without unblocking the main test (e.g., stream := <-streamCh), potentially hanging the test. Prefer reporting the error back to the main goroutine via a channel (and failing the test there), or use t.Error plus closing/signaling channels so the test can terminate cleanly.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
connection.go:282:3: assignOp: replace `s.pingId = s.pingId - 0x7ffffffe` with `s.pingId -= 0x7ffffffe` (gocritic)
s.pingId = s.pingId - 0x7ffffffe
^
connection.go:284:3: assignOp: replace `s.pingId = s.pingId + 2` with `s.pingId += 2` (gocritic)
s.pingId = s.pingId + 2
^
connection.go:934:2: assignOp: replace `s.nextStreamId = s.nextStreamId + 2` with `s.nextStreamId += 2` (gocritic)
s.nextStreamId = s.nextStreamId + 2
^
priority.go:90:2: assignOp: replace `q.nextInsertId = q.nextInsertId + 1` with `q.nextInsertId++` (gocritic)
q.nextInsertId = q.nextInsertId + 1
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
priority.go:50:2: right hand must be only type assertion (forcetypeassert)
*fq = append(*fq, x.(*prioritizedFrame))
^
priority.go:104:2: type assertion must be checked (forcetypeassert)
frame := heap.Pop(q.queue).(*prioritizedFrame).frame
^
priority_test.go:66:6: type assertion must be checked (forcetypeassert)
if frame.(*spdy.DataFrame).StreamId != i {
^
priority_test.go:67:55: type assertion must be checked (forcetypeassert)
t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
^
priority_test.go:89:6: type assertion must be checked (forcetypeassert)
if frame.(*spdy.DataFrame).StreamId != i {
^
priority_test.go:90:55: type assertion must be checked (forcetypeassert)
t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
^
spdy_test.go:847:3: right hand must be only type assertion (forcetypeassert)
netconn, _, _ := w.(http.Hijacker).Hijack()
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
No description provided.