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 split workflow, allowing the action to be used in PRs created from forks #50

Merged
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/venv
**/__pycache__
.git
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
__pycache__/
venv/

# Generated by review action
clang-tidy-review-output.json
clang-tidy-review-metadata.json

# Generated by clang-tidy
clang_tidy_review.yaml
13 changes: 10 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ RUN apt update && \
clang-tidy-12 \
python3 python3-pip && \
pip3 install --upgrade pip && \
pip3 install -r requirements.txt
pip3 install -r requirements.txt && \
rm -rf /var/lib/apt/lists/

COPY review.py /review.py
WORKDIR /action

ENTRYPOINT ["/review.py"]
COPY review.py /action/review.py

# Include the entirety of the post directory for simplicity's sake
# Technically we only need the clang_tidy_review directory but this keeps things consistent for running the command locally during development and in the docker image
COPY post /action/post

ENTRYPOINT ["/action/review.py"]
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ at once, so `clang-tidy-review` will only attempt to post the first
- default: '25'
- `lgtm_comment_body`: Message to post on PR if no issues are found. An empty string will post no LGTM comment.
- default: 'clang-tidy review says "All clean, LGTM! :+1:"'
- `split_workflow`: Only generate but don't post the review, leaving it for the second workflow. Relevant when receiving PRs from forks that don't have the required permissions to post reviews.
- default: false

## Outputs

Expand Down Expand Up @@ -188,6 +190,86 @@ jobs:
base_dir: ${{ env.base_dir }}
```

## Usage in fork environments (Split workflow)

Actions from forks are limited in their permissions for your security. To support this use case, you can use the split workflow described below.

Example lint workflow:

```yaml
name: clang-tidy-review

# You can be more specific, but it currently only works on pull requests
on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

# Optionally generate compile_commands.json

- uses: ZedThree/[email protected]
with:
split_workflow: true

- uses: actions/upload-artifact@v3
with:
name: clang-tidy-review
path: |
clang-tidy-review-output.json
clang-tidy-review-metadata.json
```

Example post comments workflow:

```yaml
name: Post clang-tidy review comments

on:
workflow_run:
# The name field of the lint action
workflows: ["clang-tidy-review"]
types:
- completed

jobs:
build:
runs-on: ubuntu-latest

steps:
# Downloads the artifact uploaded by the lint action
- 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/[email protected]
```

The lint workflow runs with limited permissions, while the post comments workflow has the required permissions because it's triggered by the `workflow_run` event.
Read more about workflow security limitations [here](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).

## Real world project samples
|Project|Workflow|
|----------|-------|
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ inputs:
description: 'Message to post on PR if no issues are found. An empty string will post no LGTM comment.'
required: false
default: 'clang-tidy review says "All clean, LGTM! :+1:"'
split_workflow:
description: "Only generate but don't post the review, leaving it for the second workflow. Relevant when receiving PRs from forks that don't have the required permissions to post reviews."
required: false
default: false
pr:
default: ${{ github.event.pull_request.number }}
repo:
Expand All @@ -77,3 +81,4 @@ runs:
- --apt-packages=${{ inputs.apt_packages }}
- --cmake-command='${{ inputs.cmake_command }}'
- --lgtm-comment-body='${{ inputs.lgtm_comment_body }}'
- --split_workflow=${{ inputs.split_workflow }}
13 changes: 13 additions & 0 deletions post/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3

COPY requirements.txt /requirements.txt

RUN pip3 install --upgrade pip && \
pip3 install -r requirements.txt

WORKDIR /action

COPY post.py /action/post.py
COPY clang_tidy_review /action/clang_tidy_review

ENTRYPOINT ["/action/post.py"]
3 changes: 3 additions & 0 deletions post/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Clang-Tidy Review - Post

This is a child-action that only posts the review from the [parent action](../README.md).
Empty file added post/__init__.py
Empty file.
32 changes: 32 additions & 0 deletions post/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: 'clang-tidy review - post comments'
author: 'Peter Hill'
description: 'Create a pull request review based on warnings produced by the parent action'
branding:
icon: 'book-open'
color: 'red'
inputs:
token:
description: 'Authentication token'
default: ${{ github.token }}
required: false
repo:
default: ${{ github.repository }}
max_comments:
description: 'Maximum number of comments to post at once'
required: false
default: '25'
lgtm_comment_body:
description: 'Message to post on PR if no issues are found. An empty string will post no LGTM comment.'
required: false
default: 'clang-tidy review says "All clean, LGTM! :+1:"'
outputs:
total_comments:
description: 'Total number of warnings from clang-tidy'
runs:
using: 'docker'
image: 'Dockerfile'
args:
- --token=${{ inputs.token }}
- --repo=${{ inputs.repo }}
- --max-comments=${{ inputs.max_comments }}
- --lgtm-comment-body='${{ inputs.lgtm_comment_body }}'
Loading