Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add lint target to makefile #101

Merged
merged 13 commits into from
Nov 8, 2022
Merged

feat: add lint target to makefile #101

merged 13 commits into from
Nov 8, 2022

Conversation

hessjcg
Copy link
Collaborator

@hessjcg hessjcg commented Nov 3, 2022

Introduce a new makefile target lint which will run generate and all lint checks
Introduce a lint check for go using golanci-lint
Introduce a lint check target for terraform using terraform fmt
Update the lint github action to use the new pr_check_lint target in the makefile

@hessjcg hessjcg marked this pull request as ready for review November 4, 2022 20:53
@hessjcg hessjcg requested review from a team, kurtisvg, enocom and shubha-rajan November 4, 2022 20:53
Comment on lines 39 to 40
- name: Verify no changes from lint tools. If you're reading this and the check has failed, run `make -f operator.mk pr_check_lint`.
run: make -f operator.mk pr_check_lint
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this step happen after we remove the label?

cc @jackwotherspoon

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Looks like I copied an older version of the workflow from cloud-sql-proxy. I'll move the remove label step up.

@@ -36,8 +36,8 @@ jobs:
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Set up build.env with phony secrets.
run: cp build.sample.env build.env
- name: Verify no changes from lint tools. If you're reading this and the check has failed, run `make pre_commit`.
run: make github_lint
- name: Verify no changes from lint tools. If you're reading this and the check has failed, run `make -f operator.mk pr_check_lint`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this just be generate? Won't generate lint everything?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

generate only generates code. It does not run golangci-lint.

Copy link
Contributor

Choose a reason for hiding this comment

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

Generate is itself a lint because it verifies that the code used to generate the other code is correct... IIRC it also runs go vet which is itself a lint check.

There's no reason to separate lint into it's own check because there is no reason for the user to run lint on it's own. After they make changes they will need to generate, and that should flag if something is wrong that would prevent them from getting into a "valid state" to check in.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. All lint targets are now run as part of generate.

operator.mk Outdated
Comment on lines 140 to 144
.PHONY: pr_check_lint
pr_check_lint: git_workdir_clean lint # Used in the Github Action PR check to ensure generate does not introduce changes and lint passes
git diff --stat HEAD
@git diff --exit-code --stat HEAD || (echo ; echo ; echo "ERROR: Lint tools caused changes to the working dir. "; echo " Please review the changes before you commit."; echo ; exit 1)
@echo "PR lint checks OK"
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like it could just happen in the workflow - does it need to be in the makefile?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My experience with software projects that are more than 10 years old is this: the build tool in the source (ant, mvn, make, npm, etc) has outlived several changes of the CI tool.

As a result, I have found that it is much easier to develop and maintain reliable validation and release processes run by CI when the most of the logic is written in the build tool.

I wrote all the steps needed to for the lint pr check into Makefile here. The lint.yaml is minimal: it simply calls make.

This makes it faster for me and any other developer to dial in the exact build process to check make, because I can test it my local dev machine. Also it reinforces the pattern for this project: build-related code is always in the Makefile.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's already too much stuff in the Makefile - we need to keep it slim and avoid bloat so that it is maintainable and approachable. Putting too much stuff in a single place just adds indirection and means going down the rabbit hole to find where the actual logic lives.

It's also significantly more streamlined to put it in the workflow: It's one-line (make generate && git diff --exit-code) and makes it super clear what it's checking - it's running the generate step and throwing the error if there are any changes.

Copy link
Collaborator Author

@hessjcg hessjcg Nov 7, 2022

Choose a reason for hiding this comment

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

I agree that that the makefile is getting long and we may want to break it up for readability. I disagree with your analysis of the tradeoffs about which approach is more maintainable.

Why we need a separate 'generate' and 'lint' target:
The golangci-lint check is not included in the generate target because it takes ~45 seconds to run. We use generate all over the place and running a full golangci-lint on every build is unnecessary and slows the developer down.

Why put the CI lint check logic into the Makefile
For me, when I join on an old project with existing build and CI infrastructure, my first step to contributing is to figure out how to pass the PR checks. This is easiest when all the CI and build stuff in one language, in one place.

Generally if a PR check fails, I need to go digging the documentation and CI tooling to find answers to these questions:

  1. What CI tool is building this project?
  2. Do I have access to that CI tool?
  3. What build actually failed?
  4. What file controls that build, and how do I read that file?
  5. What commands are being run?
  6. How do I reproduce those commands on my laptop so I can figure out what is wrong?

In this PR, the lint CI job fails with an error that instructs the contributor run make pr_check_lint. All the interesting build logic used by the pr check is in the makefile. The new developer can easily figure out what is required of them in one file that they already know how to use.

If, as you propose, we start adding specific incantations of commands to the github workflow files like lint.yaml, then the developer has to go digging through those files, and we have to keep one more piece of information in the onboarding docs in sync with the code. In the long run, this will be harder to maintain than a makefile with an extra 4-line target in it.

Copy link
Contributor

@kurtisvg kurtisvg Nov 7, 2022

Choose a reason for hiding this comment

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

The golangci-lint check is not included in the generate target because it takes ~45 seconds to run.

Golang CI is a combination of multiple linters, including goimports and go vet. It's claim to fame is that it's fast and does the lints using parallelism and caching. If it's really a significant amount of time to run, I think we should investigate if we need cache the earlier generation steps better so they aren't voiding the cache golangci-lint is using.

If, as you propose, we start adding specific incantations of commands to the github workflow files like lint.yaml, then the developer has to go digging through those files,

The developer doesn't need to understand how the presubmits work. It should clearly indicate what is wrong so that they can fix it. In the case of the linter, we should give them an error that says "run make generate to pass this check".

Copy link
Collaborator Author

@hessjcg hessjcg Nov 8, 2022

Choose a reason for hiding this comment

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

Fixed. lint is now part of generate and specific pr checks are now in the lint.yaml github action.

@hessjcg hessjcg requested a review from kurtisvg November 7, 2022 16:02
@hessjcg hessjcg merged commit 9f3d81b into main Nov 8, 2022
@hessjcg hessjcg deleted the release-lint branch November 18, 2022 17:56
This was referenced Dec 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants