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

Add reporter for outputing Reviewdog JSONL format #377

Closed
wants to merge 2 commits into from

Conversation

ewencluley
Copy link

@ewencluley ewencluley commented Mar 28, 2021

This reporter will convert linter output to a standardised format that can
easily be read by reviewdog.

I have decided to use the JSONL format over the JSON format as it will be
simpler to join together mutltiple files before feeding into review dog.

Very much a WIP and would like feedback on whether this approach is sensible or not.

Currently I've done a converter for Flake8 and Black but would obviously need to do many more, though as I work on this some commonalities will emerge e.g. those linters that output unified diffs can likely share a converter.

TODO:

  • RDJSON output format for eslint + any other typescript/javascript linters
  • Documentation

@nvuillam
Copy link
Member

Great, i'll have a look :)

@nvuillam
Copy link
Member

Seems promising !
Do you think that we could make generic stdout/err post-processing methods for all linters, and we could define in descriptor YML files the method to call for reviewdog post-processing ?

I'd like to avoid as much as possible to have direct references to linters in core Mega-Linter architecture, and it would be easier to maintain than having a method for each linter ^^

@ewencluley
Copy link
Author

Seems promising !
Do you think that we could make generic stdout/err post-processing methods for all linters, and we could define in descriptor YML files the method to call for reviewdog post-processing ?

I'd like to avoid as much as possible to have direct references to linters in core Mega-Linter architecture, and it would be easier to maintain than having a method for each linter ^^

That sounds sensible- I can look into doing that, yeah. I think the 2 convertors I have made so far will be pretty re-usable as one is for unified diff and the other is a pretty simple pattern matching sort of thing.

@ewencluley
Copy link
Author

To clarify, before I go down some 🐰 🕳️, do you mean adding a post_process method to the Linter base class that would be called from the ReviewdogJsonlReporter and would use the linter description to determine which specific processor/convertor to call (e.g. UnifiedDiffRdjsonlConvertor)?

@nvuillam
Copy link
Member

nvuillam commented Mar 31, 2021

Sorry for the delay... lot of work on the job that pays my rent ^^
Do you think we can call reviewdog after each linter, or in "bulk" mode at the end ?

We can have linter reporters and mega-linter reporter, so for example we could collect/transform all data after each linter, then send the whole package at the end

And for me reviewdog reporter could itself receive "reviewdog_processor" from .yml descriptors (it can become a standard yml attribute, reviewdog looks so great that it deserves it ^^ )

@ewencluley
Copy link
Author

Sorry for the delay... lot of work on the job that pays my rent ^^

Same for me. Don't worry about slow replies, great to have this level of engagement from a project maintainer 😄

I have been primarily focused on looking at reviewdog from a github perspective (will have to investigate bitbucket and gitlab at some point).

I think there are pros and cons to each approach.

If we call it once for the overal result of all linters (this was what I was thinking would be the best approach) we will get a single review on the PR (using the github-pr-review reporter in reviewdog) for all linters together. RD automatically limits the number of line comments it posts with the review to 30 to avoid hitting githubs rate limit(see here ). It will add any over the limit to the summary comment for the review so no output is lost.

If it is called once for each linter output that would generate a seperate "review" for each linter with the 30 comment limit per linter output, however the rate limit could still kick in if we are calling RD multiple times in quick sucession. This way we would have less control over whether it hit the rate limit or not.

I think calling RD once for all the linters togehter is the best approach and this can easily be achieved by joinign together the RDJSONL output as the input to RD. I also think this will allow us to just let RD do it's thing with any of its reporters.

@ewencluley ewencluley force-pushed the reviewdog-reporter branch 2 times, most recently from b86e034 to 4b963cc Compare April 2, 2021 16:30
@ewencluley
Copy link
Author

Have updated this to allow the reviewdog processor to be defined in the descriptor file for each linter. I'm not quite sure ive got the json schema stuff right but it seems to ./build.sh ok. If not defined, the reporter will currently just skip writing output files (temporary behaviour). Let me know if this is along the lines of what you were thinking @nvuillam.

@nvuillam
Copy link
Member

nvuillam commented Apr 2, 2021

That is exactly what i was thinking :)

@ewencluley ewencluley force-pushed the reviewdog-reporter branch 4 times, most recently from 6d46fde to 936140e Compare April 4, 2021 11:25
@ewencluley
Copy link
Author

ewencluley commented Apr 4, 2021

@nvuillam 2 questions:

  1. The reviewdog_processor property I have added to the descriptor is not getting picked up when the linter runs on this PR. Do you know why that would be happening? Is it expected? When i run locally it is working fine and picking up the property. (running locally using docker build -f flavors/python/Dockerfile . -t mega-linter && docker run -it -e ENABLE=PYTHON -e ADDITIONAL_EXCLUDED_DIRECTORIES=venv -e REVIEWDOG_REPORTER=true -v "/Users/ewen/example-project:/tmp/lint" mega-linter)

  2. How am I best to add the install command for reviewdog to the docker file? I can see the build.sh that uses the linter descriptors to determin what needs installed but is there a place to define installation commands for all dockerfile flavours? I dont think I can just add it to the Dockerfile as it will be overwriten?

@nvuillam
Copy link
Member

nvuillam commented Apr 4, 2021

  1. MegaLinter job on a PR uses the previous version of MegaLinter, so it's ok that this job fails on case of a major evolution impacting new YML properties
    While the big PR job pass, it's ok :) ( it contains a step linting own repo with just built MegaLinter image
    If you set Quick build in the commit message, it can reuse previously built image so the PR job is way faster. But to have access to QuickBuild function you need to be an internal contributor of the main repo, I give you access :)

  2. you can put it here :)
    image

@ewencluley ewencluley force-pushed the reviewdog-reporter branch 2 times, most recently from 1d9e6fc to 0846dd0 Compare April 4, 2021 19:26
@ewencluley
Copy link
Author

Awesome, thanks. I have added 2 more commits, one to install reviewdog and one to post to the PR. The later I ahve not been able to test completely as locally I am not working on a PR and in thsi PR (as identified above) it doesnt run with the latest changes in this PR so the descriptors dont have the config to make the the review dog per linter reporter run.

@codecov-io
Copy link

codecov-io commented Apr 5, 2021

Codecov Report

Merging #377 (0c80cae) into master (24f2c9c) will increase coverage by 0.85%.
The diff coverage is 85.71%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #377      +/-   ##
==========================================
+ Coverage   86.68%   87.54%   +0.85%     
==========================================
  Files         123      125       +2     
  Lines        2915     3082     +167     
==========================================
+ Hits         2527     2698     +171     
+ Misses        388      384       -4     
Impacted Files Coverage Δ
megalinter/setup.py 0.00% <ø> (ø)
megalinter/reporters/ReviewdogReporter.py 58.69% <58.69%> (ø)
megalinter/reporters/ReviewdogLinterReporter.py 95.86% <95.86%> (ø)
megalinter/Reporter.py 90.47% <100.00%> (ø)
megalinter/MegaLinter.py 90.62% <0.00%> (+2.08%) ⬆️
...alinter/tests/test_megalinter/helpers/utilstest.py 99.12% <0.00%> (+9.64%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 24f2c9c...0c80cae. Read the comment docs.

@nvuillam
Copy link
Member

nvuillam commented Apr 5, 2021

Can you add a test case using reviewdog ? This way you'll be able to see if it works from ci :)

@ewencluley ewencluley force-pushed the reviewdog-reporter branch 5 times, most recently from 5a74495 to 8fedc6e Compare April 8, 2021 20:52
@ewencluley
Copy link
Author

I think that once eslint is managed, we may consider publishing a first version ?
Python Java & JS/TS being the most used, I think it would be enough for a start ^^

Great. That sounds like a good plan. I will work on that and some docs.

I also think it would be sensible to have the reporter disabled by default (currently I have it enabled by default) so users have to explicitly enable it. Happy to defer to your opinion on that though.

@nvuillam
Copy link
Member

nvuillam commented May 17, 2021

Just a suggestion (I don't know the topic so it may be dumb), but couldn't it possible to use https://github.com/reviewdog/errorformat ?

Do you mean instead of the RDJSON format? In theory it could be, the one issue there is that errorformat AFAICT does not support suggestions, where as RDJSON does. I wouldn't normally care too much but on some of the linters that output a unified diff there is very little detail of the actual error and the diff provides a suggestion.

For example, Black outputs a generic message for all files regardless of the rule violation with the diff, as follows:

❌ [ERROR] radiopi.py
    would reformat radiopi.py
    Oh no! 💥 💔 💥
    1 file would be reformatted.
    --- radiopi.py      2021-04-30 09:49:25.071383 +0000
    +++ radiopi.py      2021-05-17 08:06:48.931037 +0000
   
                alarm = Clock.get_alarm()
    -        alarm_str = f'{str(alarm.hour).zfill(2)}:{str(alarm.minute).zfill(2)} [{Clock.get_days_str(alarm.day_of_week)}]'
    +        alarm_str = f"{str(alarm.hour).zfill(2)}:{str(alarm.minute).zfill(2)} [{Clock.get_days_str(alarm.day_of_week)}]"
     
             display.draw_text((20, 0), time_str, font=display.big_font)

From this we cannot infer the actual issue Black has found, only what it suggests the code is changed too, hence the reliance on suggestions.

It is a real shame there is no industry standard output for linters as that would make this whole thing so much easier.

I don't know the details, I just read in reviewdog that it uses that internally, so maybe it would prevent you from describing the format, as it may already be done by an existing tool ^^
But if it does not fit the requirement, I trust your judgement :)

I think that once eslint is managed, we may consider publishing a first version ?
Python Java & JS/TS being the most used, I think it would be enough for a start ^^

Great. That sounds like a good plan. I will work on that and some docs.

I also think it would be sensible to have the reporter disabled by default (currently I have it enabled by default) so users have to explicitly enable it. Happy to defer to your opinion on that though.

Agreed, Mega-Linter claims that there is no calls to external apps by default, let's respect that :)
But why not a suggestion message in the logs to propose to activate reviewdog ? ( message that could be disabled with another variable, like with FLAVORS_SUGGESTION )

@nvuillam
Copy link
Member

Note: as you are declared as collaborator on the repo, you can create an branch named alpha in the main repo, that would generate automatically an alpha version of Mega-Linter, that could be tested on other repos to be sure it works as expected in a real context :)

@nvuillam
Copy link
Member

@ewencluley you should install https://www.npmjs.com/package/markdown-table-formatter :) (it is used in build.sh)
npm i markdown-table-formatter -g

@nvuillam
Copy link
Member

you can also write quick-build in the commit message when u have just updated python code :) ( faster build , does not performs all the installations of Dockerfile )

@ewencluley
Copy link
Author

ewencluley commented May 25, 2021

Thanks for the pointers. I was trying to test out the alpha branch I created on this PR , but am unsure why it seems to be not getting the alpha version and instead getting v4

https://github.com/ewencluley/radiopi/pull/4/checks?check_run_id=2667467176

@nvuillam
Copy link
Member

My bad sorry ^^
Set alpha instead of v4 in action.yml and it will be ok :)Screenshot_20210525-235953.png

@ewencluley
Copy link
Author

Ah, perfect. Next question- i need to add unidiff as a dependency. I've added it to .automation/setup.py and requirements.dev.txt but is there anywhere else I need to add it. I can see an error in one of the CI logs that is

--Error detail:
************* Module megalinter.reporters.ReviewdogLinterReporter
megalinter/reporters/ReviewdogLinterReporter.py:139:12: E0401: Unable to import 'unidiff' (import-error)

https://github.com/nvuillam/mega-linter/runs/2688240026?check_suite_focus=true

@ewencluley
Copy link
Author

ewencluley commented May 27, 2021

Sorry, not .automation/setup.py, my mistake, I have it already in:
megalinter/setup.py and requirements.dev.txt

see https://github.com/nvuillam/mega-linter/blob/10821dcac67367d53af15837986de1e18481238d/megalinter/setup.py

@ewencluley
Copy link
Author

@nvuillam I have just pushed to a new branch (alpha-reviewdog-reporter) and getting the same error

--Error detail:
************* Module megalinter.reporters.ReviewdogLinterReporter
megalinter/reporters/ReviewdogLinterReporter.py:139:12: E0401: Unable to import 'unidiff' (import-error)

https://github.com/nvuillam/mega-linter/runs/2912917400?check_suite_focus=true

I have unidiff in megalinter/setup.py and when i build the docker image locally and run all works fine. Any ideas appreciated. Thanks

P.S. Apologies for the delays in getting this moving again, been on vacation for 3 weeks and just back.

@nvuillam
Copy link
Member

@ewencluley i'll try to checkout your branch :)

Copy link
Member

@nvuillam nvuillam left a comment

Choose a reason for hiding this comment

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

Plz check comments :)

repository_owner, repository = config.get("GITHUB_REPOSITORY").split("/")

process = subprocess.Popen(
"reviewdog -f=rdjsonl -reporter=github-pr-review -filter-mode=nofilter",
Copy link
Member

Choose a reason for hiding this comment

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

Could the reporter have a default value that would be calculated according to ENV variables ? ( github, gitlab, azure ... )

Copy link
Member

Choose a reason for hiding this comment

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

Gitlab: GITLAB_CI
Github action: GITHUB_ACTION
Azure: SYSTEM_TEAMFOUNDATIONCOLLECTIONURI
Travis CI: TRAVIS
Circle CI: CIRCLECI
(cf https://github.com/npm/ci-detect/blob/master/index.js )

Copy link
Member

Choose a reason for hiding this comment

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

I think it would also be nice to be able to add more parameter to reviewdog, like we do for linters, using some var REVIEWDOG_EXTRA_ARGS

@nvuillam
Copy link
Member

nvuillam commented Jun 26, 2021

About https://github.com/nvuillam/mega-linter/runs/2912917400?check_suite_focus=true, Mega-Linter's own Mega-Linting during PR uses a merge between latest docker image and updated local code.
So latest image does not contain unidiff, and local code does ,that's what explains the crash

So basically....

  • focus on Build & Deploy - DEV / Tests + Deploy Docker Image - DEV job, it contains an own MegaLinter linting with just created docker image, so if this one passes, I'll be able to ignore MegaLinter failed job :)

@nvuillam
Copy link
Member

You also need to fix real MegaLinter errors

Copy-Paste:

Clone found (python):
 - megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py [52:76 - 65:6] (13 lines, 89 tokens)
   megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py [28:55 - 41:7]

CSpell:
Copy .cspell.json in your local branch and check the git diff to see if there are real typos or not (https://github.com/nvuillam/mega-linter/suites/2817971503/artifacts/62734442)

Python:

/tmp/lint/megalinter/reporters/ReviewdogLinterReporter.py:67:121: E501 line too long (126 > 120 characters)
/tmp/lint/megalinter/reporters/ReviewdogLinterReporter.py:75:17: F841 local variable 'file_nm' is assigned to but never used
/tmp/lint/megalinter/reporters/ReviewdogLinterReporter.py:161:27: E741 ambiguous variable name 'l'
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:44:121: E501 line too long (211 > 120 characters)
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:45:121: E501 line too long (211 > 120 characters)
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:79:121: E501 line too long (211 > 120 characters)
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:80:121: E501 line too long (211 > 120 characters)
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:109:1: W293 blank line contains whitespace
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:116:1: W293 blank line contains whitespace
/tmp/lint/megalinter/tests/test_megalinter/reporters/ReviewDogLinterReporterTest.py:130:121: E501 line too long (754 > 120 characters)

@ewencluley
Copy link
Author

@nvuillam - I've fixed the linting errors but the build on the alpha-reviewdog-reporter branch seems to timeout now after 1 hour. I have no idea what is causing it to do so and no idea why it is taking this length of time.
https://github.com/nvuillam/mega-linter/runs/3031852908?check_suite_focus=true

@nvuillam
Copy link
Member

@nvuillam - I've fixed the linting errors but the build on the alpha-reviewdog-reporter branch seems to timeout now after 1 hour. I have no idea what is causing it to do so and no idea why it is taking this length of time.
https://github.com/nvuillam/mega-linter/runs/3031852908?check_suite_focus=true

Please can you try to increase timeout properties in CI job config ?
https://github.com/nvuillam/mega-linter/blob/master/.github/workflows/deploy-DEV.yml

@ewencluley
Copy link
Author

Please can you try to increase timeout properties in CI job config ?
https://github.com/nvuillam/mega-linter/blob/master/.github/workflows/deploy-DEV.yml

Awesome, that seems to have worked. I am trying to test it out on this PR https://github.com/ewencluley/radiopi/actions/runs/1017820202

Having some trouble working out what the uses should be in the workflow yaml.
https://github.com/ewencluley/radiopi/pull/4/files#diff-206ce5348d308a71dab8cdc132d6dc2babebc80b94a707a45a744909ed9367d4R44

Have tried:
uses: nvuillam/mega-linter@test-ewencluley-alpha-reviewdog-reporter - the tag of the docker image on docker hub
This gives me

Unable to resolve action nvuillam/mega-linter@test-ewencluley-alpha-reviewdog-reporter

and
uses: nvuillam/mega-linter@alpha-reviewdog-reporter - the branch name
That gives me

Pull down action image 'nvuillam/mega-linter:alpha-reviewdog-reporter'
  /usr/bin/docker pull nvuillam/mega-linter:alpha-reviewdog-reporter
  Error response from daemon: manifest for nvuillam/mega-linter:alpha-reviewdog-reporter not found: manifest unknown: manifest unknown

Can you advise @nvuillam?

@nvuillam
Copy link
Member

You need to be in alpha branch and use the alpha version built by deploy docker image - alpha job

alpha must be the exact name ^^

@ewencluley
Copy link
Author

You need to be in alpha branch and use the alpha version built by deploy docker image - alpha job

alpha must be the exact name ^^

Oh! Makes sense. Ok for me to push it to the alpha branch?

@nvuillam
Copy link
Member

alpha branch is yours :)

@ewencluley
Copy link
Author

Victory!!!! I have finally got it to post comments on a PR!!

ewencluley/radiopi#4

ewencluley and others added 2 commits July 12, 2021 08:05
This reporter will convert linter output to a standardised format that can
easily be read by reviewdog.

I have decided to use the JSONL format over the JSON format as it will be
simpler to join together mutltiple files before feeding into review dog.

Install reviewdog
To use with the reviewdog reporter we install reviewdog in the
docker image. This intentionally pinned to a specific version
to avoid issues if breaking changes occur in Reviewdog.

Add overall reviewdog reporter
This gathers results generated by the Reviewdog Linter Reporters
and feeds those results into reviewdog. This will make reviewdog
post comments to github as a PR review.

Configure pylint for reviewdog reporter

add unit tests for reviewdog reporter

Reviewdog: Checkstyle config

Dont run reviewdog reporter by default
@codecov-commenter
Copy link

Codecov Report

Merging #377 (80decf8) into master (5cab12d) will decrease coverage by 1.74%.
The diff coverage is 36.84%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #377      +/-   ##
==========================================
- Coverage   86.67%   84.92%   -1.75%     
==========================================
  Files         130      132       +2     
  Lines        2986     3157     +171     
==========================================
+ Hits         2588     2681      +93     
- Misses        398      476      +78     
Impacted Files Coverage Δ
megalinter/setup.py 0.00% <ø> (ø)
megalinter/reporters/ReviewdogLinterReporter.py 32.78% <32.78%> (ø)
megalinter/reporters/ReviewdogReporter.py 46.93% <46.93%> (ø)
megalinter/MegaLinter.py 90.68% <0.00%> (+2.41%) ⬆️
megalinter/reporters/UpdatedSourcesReporter.py 89.18% <0.00%> (+2.70%) ⬆️
...alinter/tests/test_megalinter/helpers/utilstest.py 97.05% <0.00%> (+9.24%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5cab12d...80decf8. Read the comment docs.

@github-actions
Copy link
Contributor

This pull request has been automatically marked as stale because it has not had recent activity.
It will be closed in 14 days if no further activity occurs.
Thank you for your contributions.

If you think this pull request should stay open, please remove the O: stale 🤖 label or comment on the pull request.

@github-actions github-actions bot added the O: stale 🤖 This issue or pull request is stale, it will be closed if there is no activity label Aug 12, 2021
@github-actions github-actions bot closed this Aug 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O: stale 🤖 This issue or pull request is stale, it will be closed if there is no activity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants