I am trying to write a job that would lint only the changed files, on a push or pull request.
I succeeded in writing a job that retrieves the changed files but when I am passing the list of files to the lint step, it is being skipped.
I on purpose changing a bunch of files.
The code looks like this:
name: Lint Changed Files
on: [push, pull_request]
jobs:
changed_files:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Get list of added and modified files
id: changed-files
uses: tj-actions/changed-files@v39
- name: Echo changed files
run: |
echo "Changed Files: ${{ steps.changed-files.outputs.all_changed_files }}"
lint:
needs: [changed_files]
runs-on: ubuntu-latest
steps:
- name: Lint Python scripts
if: endsWith(needs.changed_files.outputs.all_changed_files, '.py')
run: |
pip install flake8
echo "${{ needs.changed_files.outputs.all_changed_files }}" | tr ' ' 'n' | grep \.py$ | xargs flake8
- name: Lint shell scripts
if: endsWith(needs.changed_files.outputs.all_changed_files, '.sh')
run: |
sudo apt-get install shellcheck
echo "${{ needs.changed_files.outputs.all_changed_files }}" | tr ' ' 'n' | grep \.sh$ | xargs shellcheck
- name: Lint YAML files
if: endsWith(needs.changed_files.outputs.all_changed_files, 'yaml')
run: |
pip install yamllint
echo "${{ needs.changed_files.outputs.all_changed_files }}" | tr ' ' 'n' | grep \.y[a]?ml$ | xargs yamllint
Can the ‘startsWith’ handle a list of strings (in this case, filenames)?
And if not, what is the best way of doing so?
Thank you!
2
Answers
The
startsWith
function in GitHub Actions does not handle a list of strings.It is designed to check if a single string starts with another specified string.
You are using the
endsWith
function, but it operates under a similar principle asstartsWith
, checking if a single string ends with a specified substring.The current approach of using
endsWith
to check if any of the changed files end with a specific extension (e.g.,.py
,.sh
,yaml
) will not work as intended sinceneeds.changed_files.outputs.all_changed_files
is a single string containing a space-separated list of all changed files, andendsWith
will only check the end of this entire string.A better approach would be to use a shell command to process the list of changed files and determine if any of the files have the desired extension:
You would now have separate steps added, to check for the presence of files with each of the desired extensions.
These steps use the
grep
command to search for the extensions in the list of changed files, and set an output variable totrue
if any files with the extension are found.The
if
conditions for the linting steps have been updated to check these output variables, so the linting steps will only run if there are files with the corresponding extensions among the changed files.tj-actions/changed-files already provides a
files
input parameter that you can use for this filtering.Example: