Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ jobs:
- name: Install golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: latest
# Pinned (not `latest`) for determinism. MUST match GOLANGCI_VERSION in
# the Makefile and the `version:` in .golangci.yml's schema. `latest`
# drifts between releases and shifts the default linter set, which is a
# "passes locally, fails CI" trap. Bump all three together.
version: v2.12.2

- name: Run linting
run: make lint
Expand Down
17 changes: 17 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# golangci-lint configuration (schema v2).
#
# DETERMINISM, not stricter-than-today: this is exactly golangci-lint v2.12.2's
# enabled-by-default linter set, encoded explicitly so a binary bump can't
# silently shift it. Keep in sync with GOLANGCI_VERSION in the Makefile.
# See README "Before you push" for the full pinning/parity rationale.
version: "2"

linters:
# `default: none` + the explicit list below pins the enabled set.
default: none
enable:
- errcheck
- govet
- ineffassign
- staticcheck
- unused
38 changes: 33 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ SOLC_EVM_VERSION := paris
# Falls back to grepping go.mod if `go list` is unavailable.
GETH_VERSION := $(shell go list -m -f '{{.Version}}' github.com/ethereum/go-ethereum 2>/dev/null || grep -E 'github.com/ethereum/go-ethereum ' go.mod | awk '{print $$2}')

# Pinned golangci-lint version. Keep in sync with the workflow `version:` and
# `.golangci.yml` (bump all three together); an unpinned `latest` drifts into a
# "passes locally, fails CI" trap. See README "Before you push".
GOLANGCI_VERSION := 2.12.2

# Find all .sol files in contracts directory
SOL_FILES := $(wildcard $(CONTRACTS_DIR)/*.sol)
CONTRACT_NAMES := $(basename $(notdir $(SOL_FILES)))
Expand All @@ -52,23 +57,29 @@ BIN_FILES := $(addprefix $(BUILD_DIR)/, $(addsuffix .bin, $(CONTRACT_NAMES)))
BINDING_FILES := $(addprefix $(BINDINGS_DIR)/, $(addsuffix .go, $(CONTRACT_NAMES)))
SCENARIO_TEMPLATE_FILES := $(addprefix $(SCENARIOS_DIR)/, $(addsuffix .go, $(CONTRACT_NAMES)))

.PHONY: generate generate-bindings check-bindings install-abigen clean help build-cli install setup-node build test lint
.PHONY: generate generate-bindings check-bindings install-abigen install-lint clean help build-cli install setup-node build test lint verify

# Default target
help:
@echo "Available targets:"
@echo " verify - Run exactly what CI gates on: lint + test + check-bindings"
@echo " build - Build the seiload CLI (alias for build-cli)"
@echo " test - Run tests with coverage"
@echo " lint - Run linting and static analysis"
@echo " test - Run tests with coverage (race detector enabled)"
@echo " lint - Run linting and static analysis (golangci-lint $(GOLANGCI_VERSION))"
@echo " setup-node - Install nvm, Node.js 20, and solc"
@echo " generate - Generate Go bindings and scenario templates for all contracts"
@echo " generate-bindings - Regenerate ONLY the Go bindings (no scenarios/factory)"
@echo " check-bindings - Fail if committed bindings are out of sync with contracts"
@echo " install-tools - Install the full pinned toolchain (solc, abigen, golangci-lint)"
@echo " install-abigen - Install abigen pinned to the go.mod go-ethereum version"
@echo " install-lint - Install golangci-lint pinned to $(GOLANGCI_VERSION)"
@echo " clean - Remove generated files"
@echo " help - Show this help message"
@echo " build-cli - Build the seiload CLI"
@echo " install - Install the seiload CLI"
@echo ""
@echo "Before pushing: run 'make verify' (local CI parity). Run 'make install-tools'"
@echo "first to get the pinned toolchain (golangci-lint $(GOLANGCI_VERSION) etc.)."

# Setup Node.js environment with nvm
setup-node:
Expand Down Expand Up @@ -187,8 +198,15 @@ check-bindings:
fi
@echo "✅ Bindings are in sync with contracts"

# Install golangci-lint pinned to GOLANGCI_VERSION for CI parity (CI pins the
# same version via golangci-lint-action).
install-lint:
@echo "📦 Installing golangci-lint@v$(GOLANGCI_VERSION) ..."
@go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v$(GOLANGCI_VERSION)
@echo "✅ Installed golangci-lint@v$(GOLANGCI_VERSION)"

# Install tools (optional convenience target)
install-tools: setup-node install-abigen
install-tools: setup-node install-abigen install-lint
@echo "✅ Tools installation complete"

# Build the seiload CLI binary
Expand All @@ -215,8 +233,18 @@ test:
@go tool cover -func=coverage.out
@echo "✅ Tests passed"

# Run linting and static analysis
# Run linting. Expects golangci-lint == GOLANGCI_VERSION (`make install-lint`);
# warns (not fails) on a mismatch, since a different binary can shift results.
lint:
@echo "🔍 Running linting and static analysis..."
@have=$$(golangci-lint version --short 2>/dev/null || golangci-lint --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1); \
if [ -n "$$have" ] && [ "$$have" != "$(GOLANGCI_VERSION)" ]; then \
echo "⚠️ golangci-lint $$have on PATH != pinned $(GOLANGCI_VERSION). Run 'make install-lint' for CI parity."; \
fi
@golangci-lint run
@echo "✅ Linting and static analysis passed"

# Local CI parity: lint + test + check-bindings — the gating jobs in
# build-and-test.yml + bindings-check.yml. Green = those CI jobs pass.
verify: lint test check-bindings
@echo "✅ verify passed (lint + test + check-bindings) — local CI parity"
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,36 @@ blocks height=5191 time(p50=2s p99=5s max=8s) gas(p50=21000 p99=50000 max=100000

## Development

### Before you push

Run the full local CI gate in one command:

```bash
make verify # lint + test + check-bindings (exactly what CI gates on)
```

A green `make verify` means the gating CI jobs (`build-and-test`, `bindings-check`)
will pass. Install the pinned toolchain once first so your local results match CI:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify omits build job steps

Medium Severity

make verify runs only lint, test, and check-bindings, but the README and Makefile say a green run means the build-and-test job will pass. That workflow also runs make build, --help, and a dry-run smoke test, and the root main package has no tests so go test ./... may not compile it.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 58e0dfc. Configure here.


```bash
make install-tools # full toolchain: Node (via nvm), solc, abigen, golangci-lint (pinned to v2.12.2)
# or, for the linter only:
make install-lint # golangci-lint pinned to v2.12.2
```

`golangci-lint` is pinned to a specific version (Makefile `GOLANGCI_VERSION`,
the workflow's `golangci-lint-action` `version:`, and `.golangci.yml`); `make lint`
warns if the binary on your PATH differs. A drifting/unpinned linter is the usual
"passes locally, fails CI" trap — `make install-lint` gives you the exact CI version.

### Build
```bash
make build
```

### Test
```bash
make test
make test # runs with -race
```

### Lint
Expand Down
Loading