Let's Go Further Building, versioning and quality control › Quality-controlling code
Previous · Contents · Next
Chapter 19.3.

Quality-controlling code

In this chapter we’re going to add new audit and tidy rules to our Makefile to check, test and tidy up our codebase automatically. It’s useful to have rules like these that you can routinely run before you commit changes into your version control system or build any binaries.

The audit rule won’t make any changes to our codebase, but will simply report any problems. In particular it will:

In contrast, the tidy rule will actually make changes to the codebase. It will:

If you’re following along, use the go get -tool command to add the latest version of staticcheck as a tool dependency to your go.mod file. Like so:

$ go get -tool honnef.co/go/tools/cmd/staticcheck@latest
go: downloading honnef.co/go/tools v0.6.0
go: downloading golang.org/x/tools v0.30.0
go: downloading github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c
go: downloading golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678
go: downloading golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
go: downloading golang.org/x/mod v0.23.0
go: downloading golang.org/x/sync v0.11.0
go: added github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c
go: added golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678
go: upgraded golang.org/x/mod v0.17.0 => v0.23.0
go: upgraded golang.org/x/sync v0.10.0 => v0.11.0
go: upgraded golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d => v0.30.0
go: added honnef.co/go/tools v0.6.0

Once that’s finished, you should now be able to execute staticcheck using the go tool command, like so:

$ go tool staticcheck --version
staticcheck 2025.1 (0.6.0)

$ go tool staticcheck ./...

Now let’s go ahead and create the new tidy and audit rules in our makefile. While we’re at it, let’s also add some comment blocks to help organize and clarify the purpose of our different makefile rules, like so:

File: Makefile
include .envrc

# ==================================================================================== #
# HELPERS
# ==================================================================================== #

## help: print this help message
.PHONY: help
help:
	@echo 'Usage:'
	@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' |  sed -e 's/^/ /'

.PHONY: confirm
confirm:
	@echo -n 'Are you sure? [y/N] ' && read ans && [ $${ans:-N} = y ]

# ==================================================================================== #
# DEVELOPMENT
# ==================================================================================== #

## run/api: run the cmd/api application
.PHONY: run/api
run/api:
	go run ./cmd/api -db-dsn=${GREENLIGHT_DB_DSN}

## db/psql: connect to the database using psql
.PHONY: db/psql
db/psql:
	psql ${GREENLIGHT_DB_DSN}

## db/migrations/new name=$1: create a new database migration
.PHONY: db/migrations/new
db/migrations/new:
	@echo 'Creating migration files for ${name}...'
	migrate create -seq -ext=.sql -dir=./migrations ${name}

## db/migrations/up: apply all up database migrations
.PHONY: db/migrations/up
db/migrations/up: confirm
	@echo 'Running up migrations...'
	migrate -path ./migrations -database ${GREENLIGHT_DB_DSN} up

# ==================================================================================== #
# QUALITY CONTROL
# ==================================================================================== #

## tidy: tidy module dependencies and format all .go files
.PHONY: tidy
tidy:
	@echo 'Tidying module dependencies...'
	go mod tidy
	@echo 'Formatting .go files...'
	go fmt ./...

## audit: run quality control checks
.PHONY: audit
audit:
	@echo 'Checking module dependencies...'
	go mod tidy -diff
	go mod verify
	@echo 'Vetting code...'
	go vet ./...
	go tool staticcheck ./...
	@echo 'Running tests...'
	go test -race -vet=off ./...

Now that’s done, all you need to do is type make tidy and make audit to execute these checks. Let’s give it a try.

If you’ve been following along closely, the output should look very similar to this:

$ make tidy
Tidying module dependencies...
go mod tidy
go: downloading github.com/google/go-cmp v0.6.0
Formatting .go files...
go fmt ./...

$ make audit
Checking module dependencies...
go mod tidy -diff
go mod verify
all modules verified
Vetting code...
go vet ./...
go tool staticcheck ./...
Running tests...
go test -race -vet=off ./...
?       greenlight.alexedwards.net/cmd/api      [no test files]
?       greenlight.alexedwards.net/cmd/examples/cors/preflight  [no test files]
?       greenlight.alexedwards.net/cmd/examples/cors/simple     [no test files]
?       greenlight.alexedwards.net/internal/data        [no test files]
?       greenlight.alexedwards.net/internal/jsonlog     [no test files]
?       greenlight.alexedwards.net/internal/mailer      [no test files]
?       greenlight.alexedwards.net/internal/validator   [no test files]

That’s looking good. The make tidy command resulted in some additional packages needing to be downloaded, but apart from that, all the checks completed successfully without any problems.


Additional information

Testing

We covered the topic of testing in a lot of detail in the first Let’s Go book, and the same principles apply again here. If you like, feel free to revisit the testing section of Let’s Go and reimplement some of those same patterns in your API. For example, you might like to try: