Skip to content

Commit

Permalink
Collect and report number of changes
Browse files Browse the repository at this point in the history
  • Loading branch information
lykahb authored and 9999years committed Mar 28, 2024
1 parent de90cc6 commit 7e44107
Show file tree
Hide file tree
Showing 11 changed files with 376 additions and 169 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

# v3.0.3
- Added stat feature which computes diffs in subtrees

## v3.0.2
- [Add config parameter for predicate quantifier](https://github.com/dorny/paths-filter/pull/224)

Expand Down
49 changes: 40 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Paths Changes Filter
# Paths Changes Filter And Diff Stat

[GitHub Action](https://github.com/features/actions) that enables conditional execution of workflow steps and jobs, based on the files modified by pull request, on a feature
branch, or by the recently pushed commits.
Expand All @@ -7,6 +7,8 @@ Run slow tasks like integration tests or deployments only for changed components
GitHub workflows built-in [path filters](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpaths)
don't allow this because they don't work on a level of individual jobs or steps.

This is a fork of [dorny/paths-filter](https://github.com/dorny/paths-filter) that adds the feature of diff stat output. The reason behind forking is that original project is dormant.

**Real world usage examples:**

- [sentry.io](https://sentry.io/) - [backend.yml](https://github.com/getsentry/sentry/blob/2ebe01feab863d89aa7564e6d243b6d80c230ddc/.github/workflows/backend.yml#L36)
Expand Down Expand Up @@ -73,13 +75,14 @@ For more scenarios see [examples](#examples) section.
## What's New

- New major release `v3` after update to Node 20 [Breaking change]
- Add `stat` parameter that enables output of the file changes statistics per filter.
- Add `ref` input parameter
- Add `list-files: csv` format
- Configure matrix job to run for each folder with changes using `changes` output
- Improved listing of matching files with `list-files: shell` and `list-files: escape` options
- Paths expressions are now evaluated using [picomatch](https://github.com/micromatch/picomatch) library

For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
For more information, see [CHANGELOG](https://github.com/lykahb/paths-filter/blob/master/CHANGELOG.md)

## Usage

Expand Down Expand Up @@ -154,14 +157,14 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob
# Default: ${{ github.token }}
token: ''
# Optional parameter to override the default behavior of file matching algorithm.
# Optional parameter to override the default behavior of file matching algorithm.
# By default files that match at least one pattern defined by the filters will be included.
# This parameter allows to override the "at least one pattern" behavior to make it so that
# all of the patterns have to match or otherwise the file is excluded.
# An example scenario where this is useful if you would like to match all
# .ts files in a sub-directory but not .md files.
# The filters below will match markdown files despite the exclusion syntax UNLESS
# you specify 'every' as the predicate-quantifier parameter. When you do that,
# all of the patterns have to match or otherwise the file is excluded.
# An example scenario where this is useful if you would like to match all
# .ts files in a sub-directory but not .md files.
# The filters below will match markdown files despite the exclusion syntax UNLESS
# you specify 'every' as the predicate-quantifier parameter. When you do that,
# it will only match the .ts files in the subdirectory as expected.
#
# backend:
Expand All @@ -179,6 +182,7 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob
- For each filter, it sets an output variable with the name `${FILTER_NAME}_count` to the count of matching files.
- If enabled, for each filter it sets an output variable with the name `${FILTER_NAME}_files`. It will contain a list of all files matching the filter.
- `changes` - JSON array with names of all filters matching any of the changed files.
- If `stat` input is set to an output format, the output variable `stat` contains JSON or CSV value with the change statistics for each filter.

## Examples

Expand Down Expand Up @@ -558,10 +562,37 @@ jobs:
</details>
<details>
<summary>Passing number of added lines from a filter to another action</summary>
```yaml
- uses: dorny/paths-filter@v2
id: filter
with:
# Enable listing of diff stat matching each filter.
# Paths to files will be available in `stat` output variable.
# Stat will be formatted as JSON object
stat: json

# In this example all changed files are passed to the following action to do
# some custom processing.
filters: |
changed:
- '**'
- name: Lint Markdown
uses: johndoe/some-action@v1
# Run action only if the change is large enough.
if: ${{fromJson(steps.filter.outputs.stat).changed.additionCount > 1000}}
with:
files: ${{ steps.filter.outputs.changed_files }}
```
</details>
## See also
- [test-reporter](https://github.com/dorny/test-reporter) - Displays test results from popular testing frameworks directly in GitHub
## License
The scripts and documentation in this project are released under the [MIT License](https://github.com/dorny/paths-filter/blob/master/LICENSE)
The scripts and documentation in this project are released under the [MIT License](https://github.com/lykahb/paths-filter/blob/master/LICENSE)
12 changes: 3 additions & 9 deletions __tests__/filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ describe('matching specific change status', () => {
- added: "**/*"
`
let filter = new Filter(yaml)
const files = [{status: ChangeStatus.Added, filename: 'file.js'}]
const files = [{status: ChangeStatus.Added, filename: 'file.js', additions: 1, deletions: 0}]
const match = filter.match(files)
expect(match.add).toEqual(files)
})
Expand All @@ -192,7 +192,7 @@ describe('matching specific change status', () => {
- added|modified: "**/*"
`
let filter = new Filter(yaml)
const files = [{status: ChangeStatus.Modified, filename: 'file.js'}]
const files = [{status: ChangeStatus.Modified, filename: 'file.js', additions: 1, deletions: 1}]
const match = filter.match(files)
expect(match.addOrModify).toEqual(files)
})
Expand All @@ -214,12 +214,6 @@ describe('matching specific change status', () => {

function modified(paths: string[]): File[] {
return paths.map(filename => {
return {filename, status: ChangeStatus.Modified}
})
}

function renamed(paths: string[]): File[] {
return paths.map(filename => {
return {filename, status: ChangeStatus.Renamed}
return {filename, status: ChangeStatus.Modified, additions: 1, deletions: 1}
})
}
15 changes: 13 additions & 2 deletions __tests__/git.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as git from '../src/git'
import {ChangeStatus} from '../src/file'

describe('parsing output of the git diff command', () => {
test('parseGitDiffOutput returns files with correct change status', async () => {
const files = git.parseGitDiffOutput(
test('parseGitDiffNameStatusOutput returns files with correct change status', async () => {
const files = git.parseGitDiffNameStatusOutput(
'A\u0000LICENSE\u0000' + 'M\u0000src/index.ts\u0000' + 'D\u0000src/main.ts\u0000'
)
expect(files.length).toBe(3)
Expand All @@ -14,6 +14,17 @@ describe('parsing output of the git diff command', () => {
expect(files[2].filename).toBe('src/main.ts')
expect(files[2].status).toBe(ChangeStatus.Deleted)
})

test('parseGitDiffNumstatOutput returns files with correct change status', async () => {
const files = git.parseGitDiffNumstatOutput('4\t2\tLICENSE\u0000' + '5\t0\tsrc/index.ts\u0000')
expect(files.length).toBe(2)
expect(files[0].filename).toBe('LICENSE')
expect(files[0].additions).toBe(4)
expect(files[0].deletions).toBe(2)
expect(files[1].filename).toBe('src/index.ts')
expect(files[1].additions).toBe(5)
expect(files[1].deletions).toBe(0)
})
})

describe('git utility function tests (those not invoking git)', () => {
Expand Down
14 changes: 12 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: 'Paths Changes Filter'
name: 'Paths Changes Filter And Diff Stat'
description: 'Execute your workflow steps only if relevant files are modified.'
author: 'Michal Dorner <[email protected]>'
author: 'Michal Dorner <[email protected]>, Boris Lykah<[email protected]>'
inputs:
token:
description: 'GitHub Access Token'
Expand Down Expand Up @@ -36,6 +36,16 @@ inputs:
Backslash escapes every potentially unsafe character.
required: false
default: none
stat:
description: |
Enables listing of that enables output of the file change statistics per filter, similar to `git diff --shortstat`.
If some changes do not match any filter, the output includes an additional entry with the filter name 'other'.
'none' - Disables listing of stats (default).
'csv' - Coma separated list that has name of filter, count of additions, count of deletions, count of changed files.
If needed it uses double quotes to wrap name of filter with unsafe characters. For example, `"some filter",12,7,2`.
'json' - Serialized as JSON object where the filter names are keys. For example, `{"some filter": {"additionCount": 12, "deletionCount": 7, "fileCount": 2}}`
required: false
default: none
initial-fetch-depth:
description: |
How many commits are initially fetched from base branch.
Expand Down
Loading

0 comments on commit 7e44107

Please sign in to comment.