From 7f7d98ec03d9219626c1c627437150e10e61d157 Mon Sep 17 00:00:00 2001 From: Ilya Glebov Date: Mon, 9 Feb 2026 22:37:07 +0100 Subject: [PATCH] Add govulncheck, update dependencies and Go to 1.25 - Add govulncheck vulnerability scanning to CI and Makefile - Update Go to 1.25.7 and setup-go to v6 (fixes GO-2026-4337) - Upgrade golangci-lint to v2.8.0 with action v7 - Add .golangci.yml for v2 linter configuration - Update Go module dependencies to latest versions - Use t.Setenv in tests --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++-------- .github/workflows/release.yml | 4 ++-- .golangci.yml | 17 +++++++++++++++++ Makefile | 7 +++++-- go.mod | 12 ++++++------ go.sum | 20 ++++++++++---------- internal/cache/cache_test.go | 2 +- internal/config/config_test.go | 32 ++++++++------------------------ 8 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 .golangci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da2a1e3..861a6fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,9 +17,9 @@ jobs: run: sudo apt-get update && sudo apt-get install -y libasound2-dev - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: - go-version: "1.24" + go-version: "1.25.7" - name: Build run: go build -v ./... @@ -37,14 +37,31 @@ jobs: run: sudo apt-get update && sudo apt-get install -y libasound2-dev - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: - go-version: "1.24" + go-version: "1.25.7" - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: - version: latest + version: v2.8.0 + + vuln: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install ALSA dev libraries + run: sudo apt-get update && sudo apt-get install -y libasound2-dev + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "1.25.7" + + - name: Vulnerability check + run: go run golang.org/x/vuln/cmd/govulncheck@latest ./... goreleaser-check: runs-on: ubuntu-latest @@ -55,9 +72,9 @@ jobs: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: - go-version: "1.24" + go-version: "1.25.7" - name: Check GoReleaser config uses: goreleaser/goreleaser-action@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f24104..ba91af7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,9 +18,9 @@ jobs: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: - go-version: "1.24" + go-version: "1.25.7" - name: Install Linux audio dependencies (amd64 + arm64 cross-compile) run: | diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..0b22fcd --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,17 @@ +version: "2" + +linters: + default: standard + settings: + staticcheck: + checks: + - "all" + - "-ST1000" + - "-ST1003" + - "-QF*" + exclusions: + rules: + - text: "Error return value of .+Close" + linters: [errcheck] + - text: "Error return value of `os.Remove`" + linters: [errcheck] diff --git a/Makefile b/Makefile index 052b42d..d851454 100644 --- a/Makefile +++ b/Makefile @@ -17,11 +17,14 @@ test: lint: golangci-lint run -check: lint test build +vuln: + go run golang.org/x/vuln/cmd/govulncheck@latest ./... + +check: lint test vuln build goreleaser check clean: go clean rm -f $(BINARY_NAME) $(BINARY_NAME)-* -.PHONY: build build-all test lint check clean \ No newline at end of file +.PHONY: build build-all test lint vuln check clean \ No newline at end of file diff --git a/go.mod b/go.mod index b826b9f..b828e00 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/glebovdev/somafm-cli -go 1.24.0 +go 1.25.0 require ( - github.com/gdamore/tcell/v2 v2.13.6 + github.com/gdamore/tcell/v2 v2.13.8 github.com/go-resty/resty/v2 v2.17.1 github.com/gopxl/beep/v2 v2.1.1 github.com/rivo/tview v0.42.0 @@ -21,8 +21,8 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect + golang.org/x/net v0.50.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/term v0.40.0 // indirect + golang.org/x/text v0.34.0 // indirect ) diff --git a/go.sum b/go.sum index 6dcfe39..950a74d 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= -github.com/gdamore/tcell/v2 v2.13.6 h1:ZAKaC+z7EHtDlELEVw5qxvO560cCXOtn0Su4YqMahJM= -github.com/gdamore/tcell/v2 v2.13.6/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo= +github.com/gdamore/tcell/v2 v2.13.8 h1:Mys/Kl5wfC/GcC5Cx4C2BIQH9dbnhnkPgS9/wF3RlfU= +github.com/gdamore/tcell/v2 v2.13.8/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo= github.com/go-resty/resty/v2 v2.17.1 h1:x3aMpHK1YM9e4va/TMDRlusDDoZiQ+ViDu/WpA6xTM4= github.com/go-resty/resty/v2 v2.17.1/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -48,8 +48,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -63,20 +63,20 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/cache/cache_test.go b/internal/cache/cache_test.go index e65a10f..6ba0364 100644 --- a/internal/cache/cache_test.go +++ b/internal/cache/cache_test.go @@ -29,7 +29,7 @@ func TestHashURL(t *testing.T) { } for _, c := range result { - if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { t.Errorf("hashURL(%q) contains non-hex character: %c", tt.url, c) } } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index dd21dcb..4c6a774 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -24,9 +24,7 @@ func TestDefaultConfig(t *testing.T) { func TestConfigSaveAndLoad(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) testCfg := &Config{ Volume: 85, @@ -59,9 +57,7 @@ func TestConfigSaveAndLoad(t *testing.T) { func TestLoadNonExistentConfig(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) cfg, err := Load() if err != nil { @@ -94,9 +90,7 @@ func TestVolumeValidation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) testCfg := &Config{ Volume: tt.inputVolume, @@ -122,9 +116,7 @@ func TestVolumeValidation(t *testing.T) { func TestThemeDefaults(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) cfg, err := Load() if err != nil { @@ -150,9 +142,7 @@ func TestThemeDefaults(t *testing.T) { func TestThemePersistence(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) testCfg := &Config{ Volume: 70, @@ -414,9 +404,7 @@ func TestGetColor(t *testing.T) { func TestFavoritesPersistence(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) testCfg := &Config{ Volume: 70, @@ -448,9 +436,7 @@ func TestFavoritesPersistence(t *testing.T) { func TestAutostartPersistence(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) testCfg := &Config{ Volume: 70, @@ -476,9 +462,7 @@ func TestAutostartPersistence(t *testing.T) { func TestLoadInvalidYAML(t *testing.T) { tmpDir := t.TempDir() - originalHome := os.Getenv("HOME") - os.Setenv("HOME", tmpDir) - defer os.Setenv("HOME", originalHome) + t.Setenv("HOME", tmpDir) configDir := filepath.Join(tmpDir, ConfigDir) _ = os.MkdirAll(configDir, 0755)