Remove GPL dependencies via golangci-lint binary distribution#15050
Remove GPL dependencies via golangci-lint binary distribution#15050
Conversation
- Remove golangci-lint from tools.go and go.mod (GPL dependencies eliminated) - Add install-golangci-lint Makefile target for binary downloads - Update CI workflow to use binary installation instead of go install - Update daily-perf-improver action to use binary installation - Version: v2.8.0 (consistent with previous usage) This change eliminates all GPL-licensed transitive dependencies: - github.com/OpenPeeDeeP/depguard/v2 (GPL-3.0) - github.com/ldez/structtags (GPL-3.0) - github.com/firefart/nonamedreturns (GPL-3.0) - github.com/xen0n/gosmopolitan (GPL-1.0-or-later AND GPL-3.0) - github.com/denis-tingaikin/go-header (GPL-3.0) - github.com/leonklingele/grouper (GPL-3.0) Binary installation maintains clean MIT licensing while preserving full golangci-lint functionality. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR removes golangci-lint from the Go module dependency graph (to eliminate GPL-licensed transitive dependencies) and replaces go install usage with a pinned prebuilt golangci-lint binary download in local dev setup and CI.
Changes:
- Remove
github.com/golangci/golangci-lint/v2fromtools.go/go.modand prune the resultinggo.sumentries. - Add a Makefile target to install a pinned
golangci-lintrelease binary and wire it intodeps-dev. - Update CI and the daily perf improver composite action to install
golangci-lintvia GitHub release artifacts instead ofgo install.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tools.go |
Removes the golangci-lint blank import and notes binary-based installation. |
go.mod |
Drops the golangci-lint/v2 requirement and prunes many indirect linter deps. |
go.sum |
Removes checksums for golangci-lint and numerous transitive linter modules. |
Makefile |
Adds install-golangci-lint target and includes it in deps-dev. |
.github/workflows/ci.yml |
Switches lint-go job to download/install the prebuilt golangci-lint binary. |
.github/actions/daily-perf-improver/build-steps/action.yml |
Switches tool setup to download/install the prebuilt golangci-lint binary. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| DOWNLOAD_URL="https://github.com/golangci/golangci-lint/releases/download/$$GOLANGCI_LINT_VERSION/golangci-lint-$${GOLANGCI_LINT_VERSION#v}-$$GOOS-$$GOARCH.tar.gz"; \ | ||
| TEMP_DIR=$$(mktemp -d); \ | ||
| trap "rm -rf $$TEMP_DIR" EXIT; \ | ||
| echo "Downloading golangci-lint $$GOLANGCI_LINT_VERSION for $$GOOS/$$GOARCH..."; \ | ||
| if curl -sSL "$$DOWNLOAD_URL" | tar -xz -C "$$TEMP_DIR"; then \ | ||
| mkdir -p "$$GOPATH/bin"; \ | ||
| mv "$$TEMP_DIR"/golangci-lint-*/$$BINARY_NAME "$$GOPATH/bin/$$BINARY_NAME"; \ | ||
| chmod +x "$$GOPATH/bin/$$BINARY_NAME"; \ | ||
| echo "✓ golangci-lint $$GOLANGCI_LINT_VERSION installed to $$GOPATH/bin/$$BINARY_NAME"; \ | ||
| else \ | ||
| echo "Error: Failed to download golangci-lint from $$DOWNLOAD_URL"; \ |
There was a problem hiding this comment.
The golangci-lint installer downloads and executes a prebuilt binary without verifying integrity (e.g., SHA-256 checksum/signature). Since this is part of the dev toolchain, it’s still a supply-chain risk. Consider fetching the release checksums file and validating the archive before extracting (similar to the checksum tooling in install-gh-aw.sh).
| DOWNLOAD_URL="https://github.com/golangci/golangci-lint/releases/download/$$GOLANGCI_LINT_VERSION/golangci-lint-$${GOLANGCI_LINT_VERSION#v}-$$GOOS-$$GOARCH.tar.gz"; \ | |
| TEMP_DIR=$$(mktemp -d); \ | |
| trap "rm -rf $$TEMP_DIR" EXIT; \ | |
| echo "Downloading golangci-lint $$GOLANGCI_LINT_VERSION for $$GOOS/$$GOARCH..."; \ | |
| if curl -sSL "$$DOWNLOAD_URL" | tar -xz -C "$$TEMP_DIR"; then \ | |
| mkdir -p "$$GOPATH/bin"; \ | |
| mv "$$TEMP_DIR"/golangci-lint-*/$$BINARY_NAME "$$GOPATH/bin/$$BINARY_NAME"; \ | |
| chmod +x "$$GOPATH/bin/$$BINARY_NAME"; \ | |
| echo "✓ golangci-lint $$GOLANGCI_LINT_VERSION installed to $$GOPATH/bin/$$BINARY_NAME"; \ | |
| else \ | |
| echo "Error: Failed to download golangci-lint from $$DOWNLOAD_URL"; \ | |
| TARBALL_NAME="golangci-lint-$${GOLANGCI_LINT_VERSION#v}-$$GOOS-$$GOARCH.tar.gz"; \ | |
| DOWNLOAD_URL="https://github.com/golangci/golangci-lint/releases/download/$$GOLANGCI_LINT_VERSION/$$TARBALL_NAME"; \ | |
| CHECKSUMS_URL="https://github.com/golangci/golangci-lint/releases/download/$$GOLANGCI_LINT_VERSION/golangci-lint-$${GOLANGCI_LINT_VERSION#v}-checksums.txt"; \ | |
| TEMP_DIR=$$(mktemp -d); \ | |
| trap "rm -rf $$TEMP_DIR" EXIT; \ | |
| echo "Downloading golangci-lint $$GOLANGCI_LINT_VERSION for $$GOOS/$$GOARCH..."; \ | |
| if ! curl -sSL -o "$$TEMP_DIR/$$TARBALL_NAME" "$$DOWNLOAD_URL"; then \ | |
| echo "Error: Failed to download golangci-lint from $$DOWNLOAD_URL"; \ | |
| exit 1; \ | |
| fi; \ | |
| echo "Downloading checksums from $$CHECKSUMS_URL..."; \ | |
| if ! curl -sSL -o "$$TEMP_DIR/checksums.txt" "$$CHECKSUMS_URL"; then \ | |
| echo "Error: Failed to download checksums from $$CHECKSUMS_URL"; \ | |
| exit 1; \ | |
| fi; \ | |
| EXPECTED_CHECKSUM=$$(grep " $$TARBALL_NAME$$" "$$TEMP_DIR/checksums.txt" | awk '{print $$1}'); \ | |
| if [ -z "$$EXPECTED_CHECKSUM" ]; then \ | |
| echo "Error: Checksum for $$TARBALL_NAME not found in checksums file"; \ | |
| exit 1; \ | |
| fi; \ | |
| if command -v sha256sum >/dev/null 2>&1; then \ | |
| ACTUAL_CHECKSUM=$$(sha256sum "$$TEMP_DIR/$$TARBALL_NAME" | awk '{print $$1}'); \ | |
| elif command -v shasum >/dev/null 2>&1; then \ | |
| ACTUAL_CHECKSUM=$$(shasum -a 256 "$$TEMP_DIR/$$TARBALL_NAME" | awk '{print $$1}'); \ | |
| else \ | |
| echo "Error: Neither sha256sum nor shasum is available to verify checksums"; \ | |
| exit 1; \ | |
| fi; \ | |
| if [ "$$EXPECTED_CHECKSUM" != "$$ACTUAL_CHECKSUM" ]; then \ | |
| echo "Error: Checksum verification failed for $$TARBALL_NAME"; \ | |
| echo "Expected: $$EXPECTED_CHECKSUM"; \ | |
| echo "Actual: $$ACTUAL_CHECKSUM"; \ | |
| exit 1; \ | |
| fi; \ | |
| if tar -xz -C "$$TEMP_DIR" -f "$$TEMP_DIR/$$TARBALL_NAME"; then \ | |
| mkdir -p "$$GOPATH/bin"; \ | |
| mv "$$TEMP_DIR"/golangci-lint-*/$$BINARY_NAME "$$GOPATH/bin/$$BINARY_NAME"; \ | |
| chmod +x "$$GOPATH/bin/$$BINARY_NAME"; \ | |
| echo "✓ golangci-lint $$GOLANGCI_LINT_VERSION installed to $$GOPATH/bin/$$BINARY_NAME"; \ | |
| else \ | |
| echo "Error: Failed to extract $$TEMP_DIR/$$TARBALL_NAME"; \ |
| run: | | ||
| GOLANGCI_LINT_VERSION="v2.8.0" | ||
| GOOS=$(go env GOOS) | ||
| GOARCH=$(go env GOARCH) | ||
| GOPATH=$(go env GOPATH) | ||
| BINARY_NAME="golangci-lint" | ||
|
|
||
| echo "Installing golangci-lint $GOLANGCI_LINT_VERSION for $GOOS/$GOARCH..." | ||
| DOWNLOAD_URL="https://github.com/golangci/golangci-lint/releases/download/$GOLANGCI_LINT_VERSION/golangci-lint-${GOLANGCI_LINT_VERSION#v}-$GOOS-$GOARCH.tar.gz" | ||
|
|
||
| curl -sSL "$DOWNLOAD_URL" | tar -xz -C /tmp | ||
| mkdir -p "$GOPATH/bin" | ||
| mv /tmp/golangci-lint-*/$BINARY_NAME "$GOPATH/bin/$BINARY_NAME" | ||
| chmod +x "$GOPATH/bin/$BINARY_NAME" |
There was a problem hiding this comment.
This CI step duplicates the golangci-lint download logic from the Makefile target and extracts into a shared /tmp path. To reduce drift and avoid collisions/leftovers, prefer calling make install-golangci-lint here and have the Makefile handle temp dirs/cleanup (and checksum verification).
See below for a potential fix:
# Delegate installation to the Makefile to avoid duplication and handle temp dirs/checksums.
- name: Install golangci-lint
run: |
make install-golangci-lint
| curl -sSL "$DOWNLOAD_URL" | tar -xz -C /tmp 2>&1 | tee -a build-steps.log | ||
| mkdir -p "$GOPATH/bin" | ||
| mv /tmp/golangci-lint-*/$BINARY_NAME "$GOPATH/bin/$BINARY_NAME" 2>&1 | tee -a build-steps.log | ||
| chmod +x "$GOPATH/bin/$BINARY_NAME" | ||
|
|
There was a problem hiding this comment.
This installs golangci-lint by downloading and extracting an archive to /tmp without integrity verification or cleanup. For better supply-chain safety and to avoid /tmp collisions, download into a unique temp dir, verify checksums/signatures, then move the binary into place (or reuse the Makefile install target).
| curl -sSL "$DOWNLOAD_URL" | tar -xz -C /tmp 2>&1 | tee -a build-steps.log | |
| mkdir -p "$GOPATH/bin" | |
| mv /tmp/golangci-lint-*/$BINARY_NAME "$GOPATH/bin/$BINARY_NAME" 2>&1 | tee -a build-steps.log | |
| chmod +x "$GOPATH/bin/$BINARY_NAME" | |
| TMP_DIR="$(mktemp -d)" | |
| echo "Using temporary directory: $TMP_DIR" | tee -a build-steps.log | |
| ARCHIVE_PATH="$TMP_DIR/golangci-lint.tar.gz" | |
| CHECKSUM_PATH="$TMP_DIR/golangci-lint.tar.gz.sha256" | |
| echo "Downloading golangci-lint archive..." | tee -a build-steps.log | |
| curl -sSL -o "$ARCHIVE_PATH" "$DOWNLOAD_URL" 2>&1 | tee -a build-steps.log | |
| echo "Downloading golangci-lint checksum..." | tee -a build-steps.log | |
| curl -sSL -o "$CHECKSUM_PATH" "${DOWNLOAD_URL}.sha256" 2>&1 | tee -a build-steps.log | |
| echo "Verifying golangci-lint archive checksum..." | tee -a build-steps.log | |
| (cd "$TMP_DIR" && sha256sum -c "$(basename "$CHECKSUM_PATH")") 2>&1 | tee -a build-steps.log | |
| echo "Extracting golangci-lint archive..." | tee -a build-steps.log | |
| tar -xzf "$ARCHIVE_PATH" -C "$TMP_DIR" 2>&1 | tee -a build-steps.log | |
| mkdir -p "$GOPATH/bin" | |
| mv "$TMP_DIR"/golangci-lint-*/"$BINARY_NAME" "$GOPATH/bin/$BINARY_NAME" 2>&1 | tee -a build-steps.log | |
| chmod +x "$GOPATH/bin/$BINARY_NAME" | |
| echo "Cleaning up temporary directory..." | tee -a build-steps.log | |
| rm -rf "$TMP_DIR" | |
| // Package tools tracks build-time tool dependencies. | ||
| // Import tools here with blank imports to include them in go.mod. | ||
| // This ensures consistent tool versions across development and CI. | ||
| // Note: golangci-lint is installed via binary distribution to avoid GPL dependencies |
There was a problem hiding this comment.
Minor: end this sentence with a period for consistency with the surrounding comment style.
| // Note: golangci-lint is installed via binary distribution to avoid GPL dependencies | |
| // Note: golangci-lint is installed via binary distribution to avoid GPL dependencies. |
The development dependency
golangci-lintpulled in 6 GPL-licensed transitive dependencies incompatible with our MIT license. This blocks enterprise adoption and creates SBOM compliance issues.Changes
Dependency removal
golangci-lintfromtools.goandgo.moddepguard,structtags,nonamedreturns,gosmopolitan,go-header,groupergo.sumBinary installation
install-golangci-lintMakefile target that downloads pre-built binaries from GitHub releasesCI/CD updates
.github/workflows/ci.ymlto use binary installation.github/actions/daily-perf-improver/build-steps/action.ymlInstallation
No configuration changes to
.golangci.yml. Full linting functionality preserved.Verification
Original prompt
This section details on the original issue you should resolve
<issue_title>[gpl-dependency]Remove GPL dependencies from golangci-lint (6 GPL-licensed linters)</issue_title>
<issue_description>## Summary
The development dependency
github.com/golangci/golangci-lint/v2introduces GPL-licensed transitive dependencies that are incompatible with our MIT license. While golangci-lint itself is open-source, it bundles several linters licensed under GPL-3.0, creating license compliance risks for the project.Dependency Chain
GPL License Details
Primary GPL Dependency: depguard
github.com/OpenPeeDeeP/depguard/v2v2.2.1Additional GPL Dependencies
Current Usage
Where It's Used
The direct dependency
github.com/golangci/golangci-lint/v2is imported in:tools.go- Build-time tool dependency tracking (blank import)Functionality Required
We use
golangci-lintfor:make lint,make golint)GPL Linters Usage Analysis
depguard linter: ❌ NOT configured or enabled in
.golangci.ymlOther GPL linters: ❌ NOT explicitly configured
Direct GPL Usage
Analysis shows the GPL modules:
.golangci.ymlLegal & Security Implications
GPL-3.0 License Restrictions
Risk Assessment
Risk Level: MEDIUM-HIGH
Rationale:
go installorgo buildRemoval/Replacement Options
Option 1: Disable GPL Linters in golangci-lint
Approach: Continue using golangci-lint but explicitly disable GPL-licensed linters
Steps:
.golangci.ymldisable listComplexity: Low
Breaking Changes: No - We're not using these linters currently
Pros:
Cons:
Option 2: Migrate to Alternative Linting Tools [RECOMMENDED]
Approach: Replace golangci-lint with MIT/Apache-licensed alternatives
Alternative Packages:
staticcheck (MIT)
revive (MIT)
go vet...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.