DEV Community

Cover image for Get changed files in github actions

Get changed files in github actions

kbarendrecht profile image Kars Barendrecht Updated on ・2 min read

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.

    runs-on: ubuntu-latest
    # Map a step output to a job output
      all: ${{ steps.changes.outputs.all}}
      ts: ${{ steps.changes.outputs.ts }}
        # 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)"
    runs-on: ubuntu-latest
    # require the first job to have ran
    needs: changedfiles
    # only run there are changed files
    if: ${{needs.changedfiles.outputs.ts}}
      - name: echo changed files
        run: echo ${{needs.changedfiles.outputs.ts}}

Enter fullscreen mode Exit fullscreen mode

Discussion (0)

Editor guide