Navigate back to the homepage

GitHub Actions - Detect silently added permissions part-2

Dion Segijn
April 29th, 2020 · 2 min read

In the previous blog post I showed you how to run two jobs in parallel. Now I’m going to show you how the third job is only started when the first two succeeded and also how we only post a comment on the pull request when new permissions are detected.

PR comment with permissions detected

The end result will be a message on your pull request letting you know new permission are added as in the image above.

Detect changes in permissions

Workflow diff permissions

Let’s look at the third job:

1diff-permissions:
2 needs: [build-develop, build-branch]
3 runs-on: ubuntu-latest
4 steps:
5 - name: Download permissions
6 uses: actions/download-artifact@v1
7 with:
8 name: permissions
9
10 - name: Execute diff
11 run: diff --changed-group-format='%<%>' --unchanged-group-format='' $GITHUB_WORKSPACE/permissions/permissions-develop.txt $GITHUB_WORKSPACE/permissions/permissions-branch.txt > permissions-diff.txt && echo ::set-env name=NEW_PERMISSIONS::'false' || echo ::set-env name=NEW_PERMISSIONS::'true'
12
13 - run: printf "⚠ New permission(s) found\n\n\`\`\`\n" > pr-comment.txt && cat permissions-diff.txt >> pr-comment.txt
14
15 - name: comment PR
16 if: env.NEW_PERMISSIONS == 'true'
17 uses: machine-learning-apps/pr-comment@master
18 env:
19 GITHUB_TOKEN: ${{ secrets.personaltoken }}
20 with:
21 path: pr-comment.txt

This diff-permissions job depends on both the build-develop and build-branch job. We do this by defining the needs property containing the job names you want to depend on.

1needs: [build-develop, build-branch]

This job will only run when both jobs succeed, otherwise it will be ignored.

Let’s look at the steps:

  • First we download the artifacts that were uploaded at the end of previous jobs
  • Then we diff both files and see if there are any changes
  • If any changes are detected a comment will be posted

Downloading the files from the artifacts is done with this Github action. The files are downloaded as a .zip archive named permissions and automatically extracted into a folder with the same name.

Find changes in permissions with diff

More interestingly is the command to find changes between both files with diff, save the output and set an environment variable. That’s quite some things happening in one command.

1diff --changed-group-format='%<%>' --unchanged-group-format='' $GITHUB_WORKSPACE/permissions/permissions-develop.txt $GITHUB_WORKSPACE/permissions/permissions-branch.txt > permissions-diff.txt && echo ::set-env name=NEW_PERMISSIONS::'false' || echo ::set-env name=NEW_PERMISSIONS::'true'
Workflow diff permissions

We’re going to use diff on the two files downloaded from the artifacts:

  • $GITHUB_WORKSPACE/permissions/permissions-develop.txt
  • $GITHUB_WORKSPACE/permissions/permissions-branch.txt

Using diff in combination with --changed-group-format='%<%>' --unchanged-group-format='' will only output the changed lines between both files. Adding the formatting (green in the image above) to the diff command makes sure it doesn’t output extra information like what row and columns are changed.

This output is written to a file named permissions-diff.txt. Diff throws an exit code if changes are found so we need to catch this by piping the command. We use this in our advantage to set the environment variable NEW_PERMISSIONS::'true' when changes are found. We execute NEW_PERMISSIONS::'false' to false if no changes are found.

An example would be if we have two files with the following permissions:

1permissions-develop.txt permissions-branch.txt
2
3name='android.permission.INTERNET' name='android.permission.INTERNET'
4name='android.permission.ACCESS_NETWORK_STATE' name='android.permission.ACCESS_NETWORK_STATE'
5name='android.permission.ACCESS_WIFI_STATE' name='android.permission.ACCESS_WIFI_STATE'
6 name='android.permission.CAMERA'

Executing above command will generate a new file with the following contents:

1permissions-diff.txt
2
3name='android.permission.CAMERA'

It will also execute echo ::set-env name=NEW_PERMISSIONS::'true' which will tell the next step in the job to execute.

Posting information to the Pull Request

In order to post information to the pull request we need to prepare two things:

  • Your workflow must start with on: pull_request. If not the pull request number will not be available during the workflow.
  • Set a GitHub authorisation token in your secrets in order to post comments as a user.

Preparing the comment

Before posting the output of the diff as a comment on the pull request we first want to prepare a nicer message. This is done with the following command:

1- run: printf "⚠ New permission(s) found\n\n\`\`\`\n" > pr-comment.txt && cat permissions-diff.txt >> pr-comment.txt

We write a header message into a new text file named pr-comment.txt and then append the output of the diff to that same file. In the next step you’ll see the end result.

Let’s look at posting the information:

1- name: comment PR
2 if: env.NEW_PERMISSIONS == 'true'
3 uses: machine-learning-apps/pr-comment@master
4 env:
5 GITHUB_TOKEN: ${{ secrets.personaltoken }}
6 with:
7 path: pr-comment.txt

In this step we use if to only run if the environment variable NEW_PERMISSIONS is set to true. As explained earlier, this is only done when the diff command found any changes.

if: env.NEW_PERMISSIONS == 'true'

All we have to do now is tell the Github Action pr-comment to upload the contents of the file pr-comment.txt to the pull request.

Now that every step is complete, the following comment will be posted on the pull request with the newly detected permissions:

PR comment with permissions detected

And that’s about it!

You can find the full source of the workflow here and find me on twitter @Dionsegijn if you have any questions

More articles from Dion Segijn

Konfetti migration guide v2.x.x

Migration guide to update Konfetti from v1.x.x to v2.x.x

December 29th, 2021 · 2 min read

Konfetti - Simple 3D animation on a 2D Android canvas

Implementing a 3D rotation effect on a 2D canvas on Android might be easier than you think. This article demonstrates the three things you need in order to achieve that.

October 22nd, 2020 · 2 min read
© 2020–2021 Dion Segijn
Link to $https://twitter.com/DionSegijnLink to $https://github.com/DanielMartinusLink to $https://www.linkedin.com/in/dionsegijn/Link to $https://www.instagram.com/dionsegijn/