In the search of a proper way to lint our pull request (changes only). I came across some Github Actions that all require you to share your Github token. With some knowledge of git I immediately thought, why not solve this with git diff
and some shell commands, thus without the use of a Github token. Git is present by default in the action containers anyway. Eventually I came up with the following solution. All this requires is a checkout of the codebase, with a step provided by github itself: actions/checkout@v2.
Get the commit-sha's to compare
In order to get the commit sha that the pull request was based off, we can use the Github's context, available in all actions. Here we have acces to github.event.pull_request.base.sha
and github.sha
.
Only include files that are still present
To only get the files that are changed and still present we can add the argument --diff-filter=ACMRT
. This will only return files that are added, copied, modified, renamed or changed. In order to get the filenames only we also add --name-only
.
Remove newlines
In order to get the output in a single line, without newlines, we can pipe the output to xargs: COMMAND | xargs
.
Filter by filetype (optional)
To get changed files grouped by filetype we can also pipe grep using a regex as such: COMMAND | grep .ts$
.
The finished command
Combining these arguments, we get something like this:
git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep .css$ | xargs
.
Using the changed files in an actions workflow
To be able to use the files in another job, we have to use outputs. Here is a full workflow example.
jobs:
changedfiles:
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
all: ${{ steps.changes.outputs.all}}
ts: ${{ steps.changes.outputs.ts }}
steps:
# Make sure we have some code to diff.
- name: Checkout repository
uses: actions/checkout@v2
- name: Get changed files
id: changes
# Set outputs using the command.
run: |
echo "::set-output name=all::$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)"
echo "::set-output name=ts::$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep .ts$ | xargs)"
lint:
runs-on: ubuntu-latest
# require the first job to have ran
needs: changedfiles
# only run there are changed files
if: ${{needs.changedfiles.outputs.ts}}
steps:
- name: echo changed files
run: echo ${{needs.changedfiles.outputs.ts}}