#!/bin/sh # script/lint-fix: run the linter's autofixer. Rewrites files in place # for every finding the enabled linters know how to fix; findings # without an autofix are reported but left alone. # # THIS IS A DEVELOPER CONVENIENCE AND NEVER A GATE. Nothing in # script/check, script/precommit or script/cibuild calls it, and no gate # reads its exit status. The gate is script/lint, which builds # Dockerfile.lint; run that afterwards to find out whether the tree is # actually clean. # # Unlike script/lint this cannot be a build step: a build step writes # into an image, and fixes have to land in the worktree. So it runs the # same pinned image as a container with the tree bind-mounted, which # means it needs a LOCAL docker daemon -- a remote daemon has no access # to these files, and this script will appear to do nothing there. The # image reference is parsed out of Dockerfile.lint's FROM line, so the # autofixer is always the same version as the linter that gates; fixes # written by a different version are not necessarily fixes for the # version that decides. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" DOCKERFILE="$ROOT/Dockerfile.lint" # The image reference from Dockerfile.lint, tag and digest included. lint_image() { awk '$1 == "FROM" { print $2; exit }' "$DOCKERFILE" } main() { cd "$ROOT" image="$(lint_image)" if [ -z "$image" ]; then echo "lint-fix: no FROM line found in $DOCKERFILE" >&2 exit 1 fi # Run as the invoking user so the rewritten files stay owned by # them. HOME is set because the Go and golangci-lint caches default # under it and that user has no home inside the container; those # caches are per-container and discarded with it. docker run --rm \ --user "$(id -u):$(id -g)" \ --env HOME=/tmp \ --env GOFLAGS=-buildvcs=false \ --volume "$ROOT:/src" \ --workdir /src \ "$image" \ golangci-lint run --config .golangci.yml --fix "$@" ./... } main "$@"