[DX-2353] feat(ci): lint only changed modules#1858
Conversation
✅ API Diff Results - No breaking changes |
b888c10 to
ff2bf01
Compare
There was a problem hiding this comment.
Pull request overview
Updates the Go lint GitHub Actions workflow to reduce CI work by computing which Go modules were affected by a PR and linting only those modules, while also adjusting the matrix strategy behavior.
Changes:
- Replace “lint all modules” detection logic with
smartcontractkit/.github/actions/changed-modules-gooutput. - Gate the lint matrix job on whether any modules were detected as changed.
- Adjust matrix behavior to avoid fail-fast, and deepen checkout history for lint runs.
Comments suppressed due to low confidence (2)
.github/workflows/golangci_lint.yml:36
- The comment says we “Avoid running in merge queue”, but only
lint-moduleis gated;detect-moduleswill still run onmerge_groupevents because the workflow is triggered formerge_group. If the intent is to avoid merge queue entirely, consider also gatingdetect-modules(or removingmerge_groupfrom the workflow trigger) so the workflow doesn’t execute any jobs in merge queue runs.
# Avoid running in merge queue since we run in PR's and have an optional
# label to skip lint issues on a PR which would be ignored in the merge queue.
if: ${{ needs.detect-modules.outputs.modules != '[]' && github.event_name != 'merge_group' }}
.github/workflows/golangci_lint.yml:24
- This comment references
scheduled/workflow_dispatch, but this workflow currently only runs onpull_requestandmerge_group. Either add those triggers or adjust the comment so it describes the actual events that can hit this workflow.
# when scheduled/workflow_dispatch, run against all modules
no-change-behaviour: all
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| **/*.go | ||
| **/go.mod | ||
| **/go.sum |
There was a problem hiding this comment.
Is this sufficient? Or do we need to be sensitive to embedded file changes too? Usually they are significant, but maybe not as much in this case 🤔
There was a problem hiding this comment.
I think this is fine. Does golangci-lint, have rules for embedded files?
There was a problem hiding this comment.
Anything that gets linted by golangci-lint and/or can produce a linting error should be within this scope.
There was a problem hiding this comment.
IIUC the linter works by doing some kind of partial compilation, or equivalent introspection via tooling, which may understand something about embedded files. I am not certain though. I don't see any rules for embedded files specifically. Maybe we should do some experimenting?
There was a problem hiding this comment.
I looked into it, and couldn't find any indication that anything other than *.go files are linted. Only the existence of embedded files will be checked via the compiler and that should fail all the build/test pipelines if it is missing.
Seems like static analysis on any other file types need their own linting tools.
One thing we can do, is run cron'd lints on all modules, and if any new linting errors arise that should've been caught in a PR, we can investigate why it got past the filter?
There was a problem hiding this comment.
One gap I've noticed based on this conversation, is changed-modules-go should have a set of globs/files that should cause it to label all modules as changed. For example, if the workflow, or the lint config was modified, then all modules should be linted. Going to tackle this in a couple weeks.
I don't think this should be a blocker for this PR though.
There was a problem hiding this comment.
@jmank88 golangci-lint only does some basic package loading. This approach of only focusing on Go files does leave a tiny gap for embedded files, but the consequences are small, and should be caught by other methods.
- If you rename
x.txttoy.txtbut forget to update it in the Go file, the linter would catch this. But so would anything else that needs to do a basic build of the package, likego test. - Nope, I was wrong. See experiment below.
If you embed a file as a string (//go:embed x.txt var content string), certain linters (likegocriticorrevive) might analyze how that variable is used. If the content ofx.txtchanges the length or structure of that string, it could trigger "magic number" or "complexity" warnings elsewhere in your code. - Nope, I was wrong. See experiment below.
If you have some custom linters checking other things around these embedded values, then maybe there are other issues slipping through.
I ran a quick experiment to check this
//go:embed regex.txt
var pattern string
var re = regexp.MustCompile(pattern)
func main() {
fmt.Println(re.MatchString("hello"))
}- Changing to an invalid file
//go:embed not-real.txtand runninggolangci-lintthrew a typecheck linting error. So linting would catch it, but so doesbuild,run, andtest. - Changing the contents of
regex.txttoinvalid).golangci-lintandbuilddid not catch this, buttestandrundid.
So, if you renamed an embedded file x.txt -> y.txt and failed to update it in the Go code, this lint step would not be able to catch it due to file filtering. But if you're regularly running test on the same changes, you're not missing anything. This seems like an excessively minor issue, but if you're worried, I only see a few options:
- Forget the filter and lint everything every time (I'm guessing that's too expensive for this repo).
- If you have a directory or file pattern we can add to the list (e.g.,
assets/or*.txt), then that helps things a bit. - @erikburt's fix to run lints on cron jobs. It will let the issues through PRs, but they'll eventually get caught, and you can better pinpoint where.
- Or you could do effectively the same thing as the cron job, only on pushes to the
mainbranch.
If 3 seems reasonable to you, this should be good to go.
There was a problem hiding this comment.
I updated my comment above after running some experiments. @jmank88 hopefully this answers your question and we can merge.
Changes
changed-modules-goto determine which modules have changed based on the triggering eventTesting
This PR - change no modules - https://github.com/smartcontractkit/chainlink-common/actions/runs/22467329645/job/65076281025?pr=1858
DX-2353