Closed pajlada closed 2 years ago
Hi @pajlada, getting clang-tidy-review working nicely with forks would be really great!
Is perhaps a third way to use annotations instead of comments? It looks like that would be limited to only 10 annotations, which is perhaps a bit small. I'm also not sure if they handle suggestions, which is one of the really nice things about using comments. I'm actually not even sure if they do work from forks.
Would your suggestion mean people would need to start using two separate actions (and we would need two repos) in order to use clang-tidy-review
? I'm not opposed to that, but I worry it would make it a little bit harder to use (and also to develop and test!). Do you know if it would be possible to define both actions in the same repo? That would be a little bit nicer at least. I guess submodules might always work.
I wonder if there would be a way to make it work so that if run from a fork, and the user was not using the split action, then it would post a failure as an annotation with instructions on how to use the split action?
Annotations definitely looks like a suitable alternative, however I believe the 10 annotation limit is correct, and losing the Suggestions part is unfortunate.
For 2), I would also prefer using a single repo & action since there would need to be some code shared (e.g. posting the actual suggestions). I think this can done by having two inputs the user can set. One that tell the action to save the suggestions as an output or artifact instead of actually posting them, and one that fetches that output or artifact and then applies the suggestions.
# Action 1
Name: Review
...
- uses: ZedThree/clang-tidy-review@v0.8.4
id: review
with:
output_suggestions: true
...
# Action 2
Name: Post suggestions
on:
workflow_run:
workflows: ["Receive PR"]
types:
- completed
...
- uses: ZedThree/clang-tidy-review@v0.8.4
id: review
with:
post_suggestions: true
...
The default behaviour of the action would stay the same, but the output_suggestions
and post_suggestions
can be used together to split the workload up (naming would need more thought of course).
In practice it might need to be slightly more complicated (might need to output the information as an artifact rather than using ::set-output
), but it should stay fairly simple
I wonder if there would be a way to make it work so that if run from a fork, and the user was not using the split action, then it would post a failure as an annotation with instructions on how to use the split action?
Handling the error gracefully with instructions sounds like a great approach
While that sort of split using switches to control output vs posting would work, my main worry is the time and resource use. This is a docker action, and it seems Github does no caching of the images so it rebuilds it from scratch each time which takes a couple of minutes. The post action looks like it should be pretty cheap to run as it can be done in javascript (or using the actions/github-script action).
It actually does look like it's possible to have multiple actions in the same repo: https://github.com/github/codeql-action
So we'd have something like:
clang-tidy-review
├── review
│ └── action.yml
└── post_comments
└── action.yml
And users would have:
# Action 1
Name: clang-tidy-review
...
- uses: ZedThree/clang-tidy-review/review@v0.8.4
id: review
with:
post_comments: false
...
# Action 2
Name: Post suggestions
on:
workflow_run:
workflows: ["clang-tidy-review"]
types:
- completed
...
- uses: ZedThree/clang-tidy-review/post_comments@v0.8.4
id: review
...
I have been experimenting with the GitHub action part of this, and it can be achieved as a single repo as you said.
# Action 1 standard operation
...
- uses: ZedThree/clang-tidy-review@v0.8.4
...
# Action 1 split operation
...
- uses: ZedThree/clang-tidy-review@v0.8.4
with:
post_comments: false
- uses: actions/upload-artifact@v3
with:
name: clang-tidy-review
path: clang_tidy_review.yaml
# Action 2 split operation
...
- name: 'Download artifact'
uses: actions/github-script@v6
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "clang-tidy-review"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('${{github.workspace}}/clang-tidy-review.zip', Buffer.from(download.data));
- name: 'Unzip artifact'
run: unzip clang-tidy-review.zip
- uses: ZedThree/clang-tidy-review/post_comments@v0.8.4
My main question for you @ZedThree before I start working on a PR is:
Do you want to keep the review action in the root of the repository, or do you want it moved to a review
subdirectory? I personally prefer the former to be as little of a burden as possible (users won't have to change their workflow at all when they update to the version that has this feature), and I haven't found any downsides to as the full repo is cloned regardless when the action is built.
And as an additional note on the size of the split operation; I've found that the PyGithub
library used is kind of out of date with the GitHub API and doesn't have bindings for any of the methods we'd want to access (Upload Artifact, List Workflow Artifacts, and Download Artifact), which means that the implementation will have to be a bit more ugly and involve some additional actions.
We have adopted clang-tidy-review in our eCAL Project a while back. Since we moved to Eclipse and now use it for Eclipse eCAL, we have adopted a fork-based workflow. And - as one can imagine - clang-tidy-review doesn't work great with that new workflow.
Therefore I would be happy about any workaround. For me, it would also be acceptable to have the clang-tidy-review-action only post a nicely formatted comment, without leaving an actual github review.
@pajlada : Thanks for experimenting and taking care of this. If you need any assistance, please let me know.
@FlorianReimold I've got it minimally working in a fork environment. Will make a PR this weekend for feedback to which I'll request you as a reviewer to ensure we've captured everyone's workflow needs!
When an outside contributor makes a PR, clang-tidy can review the code but it can't post comments due to a lack of permissions.
The way GitHub Actions is set up is that forks have very limited permissions, including the inability to access any repository or organization secrets you've set up with extra permissions.
I see two ways of solving this: 1) Making the action running this unsafe by using pull_request_target - this would mean that the person creating the fork & PR have access to your secrets with their modified code, which means they could easily abuse or leak the secrets so this is not viable for public repositories. 2) Splitting the action up into two parts. The unprivileged action that runs clang-tidy, parses errors/warnings etc and adds them to
::set-output
, and the privileged action that parses the output set from the first action and posts the actual PR comments. (Similar to the example posted here)I would be interested in implementing 2), but I'd like to hear your thoughts about before I do any development in case I've missed something obvious or if you feel some part of the solution wouldn't fit into this action.
Example logs from the error occurring: (click to expand)
``` 2022-07-31T20:20:45.0448070Z ##[group]Run ZedThree/clang-tidy-review@v0.8.4 2022-07-31T20:20:45.0448519Z with: 2022-07-31T20:20:45.0448686Z build_dir: build 2022-07-31T20:20:45.0448889Z config_file: .clang-tidy 2022-07-31T20:20:45.0449243Z token: *** 2022-07-31T20:20:45.0449496Z base_dir: /home/runner/work/chatterino2/chatterino2 2022-07-31T20:20:45.0449740Z clang_tidy_version: 12 2022-07-31T20:20:45.0450087Z clang_tidy_checks: -*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-* 2022-07-31T20:20:45.0450427Z include: *.[ch],*.[ch]xx,*.[ch]pp,*.[ch]++,*.cc,*.hh 2022-07-31T20:20:45.0450655Z max_comments: 25 2022-07-31T20:20:45.0450841Z pr: 3886 2022-07-31T20:20:45.0451037Z repo: Chatterino/chatterino2 2022-07-31T20:20:45.0451258Z env: 2022-07-31T20:20:45.0451490Z pythonLocation: /opt/hostedtoolcache/Python/3.10.5/x64 2022-07-31T20:20:45.0451906Z LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.10.5/x64/lib:/home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64/lib 2022-07-31T20:20:45.0452312Z PKG_CONFIG_PATH: /home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64/lib/pkgconfig 2022-07-31T20:20:45.0452977Z Qt5_Dir: /home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64 2022-07-31T20:20:45.0453429Z Qt5_DIR: /home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64 2022-07-31T20:20:45.0453736Z QT_PLUGIN_PATH: /home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64/plugins 2022-07-31T20:20:45.0454058Z QML2_IMPORT_PATH: /home/runner/work/chatterino2/chatterino2/qt/Qt/5.15.2/gcc_64/qml 2022-07-31T20:20:45.0454303Z ##[endgroup] 2022-07-31T20:20:45.0834749Z ##[command]/usr/bin/docker run --name cd98f5e81d1ff62384aabaebb014676eef0ab_833c71 --label 4cd98f --workdir /github/workspace --rm -e pythonLocation -e LD_LIBRARY_PATH -e PKG_CONFIG_PATH -e Qt5_Dir -e Qt5_DIR -e QT_PLUGIN_PATH -e QML2_IMPORT_PATH -e INPUT_BUILD_DIR -e INPUT_CONFIG_FILE -e INPUT_TOKEN -e INPUT_BASE_DIR -e INPUT_CLANG_TIDY_VERSION -e INPUT_CLANG_TIDY_CHECKS -e INPUT_INCLUDE -e INPUT_EXCLUDE -e INPUT_APT_PACKAGES -e INPUT_CMAKE_COMMAND -e INPUT_MAX_COMMENTS -e INPUT_PR -e INPUT_REPO -e HOME -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL -e GITHUB_REF_NAME -e GITHUB_REF_PROTECTED -e GITHUB_REF_TYPE -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e GITHUB_STEP_SUMMARY -e RUNNER_OS -e RUNNER_ARCH -e RUNNER_NAME -e RUNNER_TOOL_CACHE -e RUNNER_TEMP -e RUNNER_WORKSPACE -e ACTIONS_RUNTIME_URL -e ACTIONS_RUNTIME_TOKEN -e ACTIONS_CACHE_URL -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/chatterino2/chatterino2":"/github/workspace" 4cd98f:5e81d1ff62384aabaebb014676eef0ab "--clang_tidy_binary=clang-tidy-12" "--token=***" "--repo=Chatterino/chatterino2" "--pr=3886" "--build_dir=build" "--base_dir=/home/runner/work/chatterino2/chatterino2" "--clang_tidy_checks=-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*" "--config_file=.clang-tidy" "--include='*.[ch],*.[ch]xx,*.[ch]pp,*.[ch]++,*.cc,*.hh'" "--exclude=''" "--apt-packages=" "--cmake-command=''" 2022-07-31T20:20:45.8627385Z Found 'build/compile_commands.json', updating absolute paths 2022-07-31T20:20:45.8628286Z Replacing '/home/runner/work/chatterino2/chatterino2' with '/github/workspace' 2022-07-31T20:20:46.7076671Z 2022-07-31T20:20:46.7077060Z Diff from GitHub PR: 2022-07-31T20:20:46.7077901Z [