diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..29c3b3e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,130 @@ +name: CI + +env: + # Database to connect to that can create other databases with `CREATE DATABASE`. + ADMIN_DATABASE_URL: postgres://postgres:postgres@localhost:5432 + + # A suitable URL for the test database. + DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/riverui_dev?sslmode=disable + +on: + push: + branches: + - master + pull_request: + +jobs: + go_build_and_test: + runs-on: ubuntu-latest + strategy: + matrix: + go-version: + - "1.22" + postgres-version: [16, 15] + fail-fast: false + timeout-minutes: 5 + + services: + postgres: + image: postgres:${{ matrix.postgres-version }} + env: + POSTGRES_PASSWORD: postgres + options: >- + --health-cmd pg_isready + --health-interval 2s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Setup Go ${{ matrix.go-version }} + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Display Go version + run: go version + + - name: Install dependencies + run: | + echo "::group::go get" + go get -t ./... + echo "::endgroup::" + + - name: Install goose + run: go install github.com/pressly/goose/v3/cmd/goose@latest + + - name: Set up test DBs + run: goose postgres "user=postgres password=postgres dbname=riverui_dev sslmode=disable" up + working-directory: ./internal/db + env: + PGHOST: 127.0.0.1 + PGPORT: 5432 + PGUSER: postgres + PGPASSWORD: postgres + PGSSLMODE: disable + + - name: Test + working-directory: . + run: go test -race ./... -timeout 2m + + golangci: + name: go_lint + runs-on: ubuntu-latest + env: + GOLANGCI_LINT_VERSION: v1.56 + permissions: + contents: read + # allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + + steps: + - uses: actions/setup-go@v5 + with: + go-version: "stable" + check-latest: true + + - name: Checkout + uses: actions/checkout@v4 + + # ensure that there is a file in `ui/dist` to prevent a lint error about + # it during CI when there is nothing there: + - name: touch file in ui/dist + run: touch ui/dist/keepfile.txt + + - name: Lint + uses: golangci/golangci-lint-action@v4 + with: + # golangci-lint needs to be run separately for every Go module, and + # its GitHub Action doesn't provide any way to do that. Have it fetch + # the golangci-lint binary, trick it into not running by sending only + # `--help`, then run the full set of lints below. DO NOT run separate + # modules as separate golangci-lint-action steps. Its post run caching + # can be extremely slow, and that's amplified in a very painful way if + # it needs to be run multiple times. + args: --help + version: ${{ env.GOLANGCI_LINT_VERSION }} + + - name: Run lint + run: make lint + + sqlc_generates: + runs-on: ubuntu-latest + timeout-minutes: 2 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup sqlc + uses: sqlc-dev/setup-sqlc@v4 + with: + sqlc-version: "1.25.0" + + - name: Run sqlc diff + run: | + echo "Please make sure that all sqlc changes are checked in!" + make verify diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..84c8c67 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,95 @@ +issues: + exclude: + - 'Error return value of .(\w+\.Rollback(.*)). is not checked' + +linters: + presets: + - bugs + - comment + - format + - performance + - style + - test + - unused + + disable: + # disabled, but which we should enable with discussion + - wrapcheck # checks that errors are wrapped; currently not done anywhere + + # disabled because we're not compliant, but which we should think about + - exhaustruct # checks that properties in structs are exhaustively defined; may be a good idea + - testpackage # requires tests in test packages like `river_test` + + # disabled because they're annoying/bad + - interfacebloat # we do in fact want >10 methods on the Adapter interface or wherever we see fit. + - godox # bans TODO statements; total non-starter at the moment + - goerr113 # wants all errors to be defined as variables at the package level; quite obnoxious + - gomnd # detects "magic numbers", which it defines as any number; annoying + - ireturn # bans returning interfaces; questionable as is, but also buggy as hell; very, very annoying + - lll # restricts maximum line length; annoying + - nlreturn # requires a blank line before returns; annoying + - wsl # a bunch of style/whitespace stuff; annoying + +linters-settings: + depguard: + rules: + all: + files: ["$all"] + allow: + deny: + - desc: "Use `github.com/google/uuid` package for UUIDs instead." + pkg: "github.com/xtgo/uuid" + + forbidigo: + forbid: + - msg: "Use `require` variants instead." + p: '^assert\.' + - msg: "Use `Func` suffix for function variables instead." + p: 'Fn\b' + - msg: "Use built-in `max` function instead." + p: '\bmath\.Max\b' + - msg: "Use built-in `min` function instead." + p: '\bmath\.Min\b' + + gci: + sections: + - Standard + - Default + - Prefix(github.com/riverqueue) + + gomoddirectives: + replace-local: true + + gosec: + excludes: + - G404 # use of non-crypto random; overly broad for our use case + + revive: + rules: + - name: unused-parameter + disabled: true + + tagliatelle: + case: + rules: + json: snake + + testifylint: + enable-all: true + disable: + - go-require + + varnamelen: + ignore-names: + - db + - eg + - f + - i + - id + - j + - mu + - sb # common convention for string builder + - t + - tt # common convention for table tests + - tx + - wg diff --git a/Makefile b/Makefile index 0a9bf7b..ce4ae02 100644 --- a/Makefile +++ b/Makefile @@ -5,3 +5,19 @@ generate: generate/sqlc .PHONY: generate/sqlc generate/sqlc: cd internal/db && sqlc generate + +.PHONY: lint +lint: + cd . && golangci-lint run --fix + +.PHONY: test +test: + cd . && go test ./... + +.PHONY: verify +verify: +verify: verify/sqlc + +.PHONY: verify/sqlc +verify/sqlc: + cd internal/db && sqlc diff