diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index da1854d..c6d097d 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -27,12 +27,13 @@ jobs: ~/Library/Caches/Homebrew /usr/local/Cellar/shfmt /usr/local/Cellar/shellcheck - key: ${{ runner.os }}-brew-quality-${{ hashFiles('**/Brewfile') }} + /usr/local/Cellar/golangci-lint + key: ${{ runner.os }}-brew-quality-v2-${{ hashFiles('**/Brewfile') }} restore-keys: | - ${{ runner.os }}-brew-quality- + ${{ runner.os }}-brew-quality-v2- - name: Install tools - run: brew install shfmt shellcheck + run: brew install shfmt shellcheck golangci-lint - name: Set up Go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v5 @@ -75,12 +76,18 @@ jobs: ~/Library/Caches/Homebrew /usr/local/Cellar/shfmt /usr/local/Cellar/shellcheck - key: ${{ runner.os }}-brew-quality-${{ hashFiles('**/Brewfile') }} + /usr/local/Cellar/golangci-lint + key: ${{ runner.os }}-brew-quality-v2-${{ hashFiles('**/Brewfile') }} restore-keys: | - ${{ runner.os }}-brew-quality- + ${{ runner.os }}-brew-quality-v2- - name: Install tools - run: brew install shfmt shellcheck + run: brew install shfmt shellcheck golangci-lint + + - name: Set up Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v5 + with: + go-version: '1.24.6' - name: Run check script run: ./scripts/check.sh --no-format diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..2fcc338 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,56 @@ +# golangci-lint configuration for Mole +# https://golangci-lint.run/usage/configuration/ + +run: + timeout: 5m + # Only lint Go code in cmd directory + modules-download-mode: readonly + +linters: + disable-all: true + enable: + # Default linters + - govet + - staticcheck + - gosimple + - ineffassign + - unused + # Additional useful linters + - errcheck + - gofmt + - goimports + +linters-settings: + govet: + enable-all: true + disable: + - fieldalignment # struct field alignment optimization is noisy + errcheck: + # Don't check for errors on these functions (common patterns) + exclude-functions: + - (io.Closer).Close + - (*os/exec.Cmd).Run + - (*os/exec.Cmd).Start + staticcheck: + checks: ["all"] + goimports: + local-prefixes: github.com/tw93/Mole + +issues: + # Don't limit the number of issues per linter + max-issues-per-linter: 0 + max-same-issues: 0 + + exclude-rules: + # Ignore certain patterns in test files + - path: _test\.go + linters: + - errcheck + # Ignore errors from os.Remove in cleanup code + - text: "Error return value of `os.Remove` is not checked" + linters: + - errcheck + # Allow unchecked errors on deferred Close calls + - text: "Error return value of .*.Close" + linters: + - errcheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c2654a..09577a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ ```bash # Install development tools -brew install shfmt shellcheck bats-core +brew install shfmt shellcheck bats-core golangci-lint ``` ## Development diff --git a/scripts/check.sh b/scripts/check.sh index d4fbc50..aff9965 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -102,7 +102,27 @@ if [[ "$MODE" != "check" ]]; then fi fi -echo -e "${YELLOW}3. Running ShellCheck...${NC}" +echo -e "${YELLOW}3. Running Go linters...${NC}" +if command -v golangci-lint > /dev/null 2>&1; then + if golangci-lint run ./cmd/...; then + echo -e "${GREEN}${ICON_SUCCESS} golangci-lint passed${NC}\n" + else + echo -e "${RED}${ICON_ERROR} golangci-lint failed${NC}\n" + exit 1 + fi +elif command -v go > /dev/null 2>&1; then + echo -e "${YELLOW}${ICON_WARNING} golangci-lint not installed, falling back to go vet${NC}" + if go vet ./cmd/...; then + echo -e "${GREEN}${ICON_SUCCESS} go vet passed${NC}\n" + else + echo -e "${RED}${ICON_ERROR} go vet failed${NC}\n" + exit 1 + fi +else + echo -e "${YELLOW}${ICON_WARNING} Go not installed, skipping Go checks${NC}\n" +fi + +echo -e "${YELLOW}4. Running ShellCheck...${NC}" if command -v shellcheck > /dev/null 2>&1; then if shellcheck mole bin/*.sh lib/*/*.sh scripts/*.sh; then echo -e "${GREEN}${ICON_SUCCESS} ShellCheck passed${NC}\n" @@ -114,7 +134,7 @@ else echo -e "${YELLOW}${ICON_WARNING} shellcheck not installed, skipping${NC}\n" fi -echo -e "${YELLOW}4. Running syntax check...${NC}" +echo -e "${YELLOW}5. Running syntax check...${NC}" if ! bash -n mole; then echo -e "${RED}${ICON_ERROR} Syntax check failed (mole)${NC}\n" exit 1 @@ -133,7 +153,7 @@ find lib -name "*.sh" | while read -r script; do done echo -e "${GREEN}${ICON_SUCCESS} Syntax check passed${NC}\n" -echo -e "${YELLOW}5. Checking optimizations...${NC}" +echo -e "${YELLOW}6. Checking optimizations...${NC}" OPTIMIZATION_SCORE=0 TOTAL_CHECKS=0