4 Commits

Author SHA1 Message Date
Michal Dorner
189a1963db update CHANGELOG.md 2020-10-16 12:27:18 +02:00
Michal Dorner
77a8129fcb improve logging 2020-10-16 12:24:39 +02:00
Michal Dorner
9379d51f46 mention commit SHA in docs for base parameter 2020-10-16 11:49:15 +02:00
Michal Dorner
beaf26afca Allow change detection on all event types 2020-10-16 11:44:38 +02:00
10 changed files with 1375 additions and 2544 deletions

View File

@@ -71,23 +71,6 @@ jobs:
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
run: exit 1
test-local-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: echo "NEW FILE" > local
- run: git add local
- uses: ./
id: filter
with:
base: HEAD
filters: |
local:
- local
- name: filter-test
if: steps.filter.outputs.local != 'true'
run: exit 1
test-change-type:
runs-on: ubuntu-latest
steps:

View File

@@ -1,19 +1,5 @@
# Changelog
## v2.6.0
- [Support local changes](https://github.com/dorny/paths-filter/pull/53)
## v2.5.3
- [Fixed mapping of removed/deleted change status from github API](https://github.com/dorny/paths-filter/pull/51)
- [Fixed retrieval of all changes via Github API when there are 100+ changes](https://github.com/dorny/paths-filter/pull/50)
## v2.5.2
- [Add support for multiple patterns when using file status](https://github.com/dorny/paths-filter/pull/48)
- [Use picomatch directly instead of micromatch wrapper](https://github.com/dorny/paths-filter/pull/49)
## v2.5.1
- [Improved path matching with micromatch](https://github.com/dorny/paths-filter/pull/46)
## v2.5.0
- [Support workflows triggered by any event](https://github.com/dorny/paths-filter/pull/44)

View File

@@ -7,10 +7,6 @@ It saves time and resources especially in monorepo setups, where you can run slo
Github workflows built-in [path filters](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpaths)
doesn't allow this because they doesn't work on a level of individual jobs or steps.
**Real world usage examples:**
- [sentry.io](https://sentry.io/) - [backend-test-py3.6.yml](https://github.com/getsentry/sentry/blob/ca0e43dc5602a9ab2e06d3f6397cc48fb5a78541/.github/workflows/backend-test-py3.6.yml#L32)
- [GoogleChrome/web.dev](https://web.dev/) - [lint-and-test-workflow.yml](https://github.com/GoogleChrome/web.dev/blob/e1f0c28964e99ce6a996c1e3fd3ee1985a7a04f6/.github/workflows/lint-and-test-workflow.yml#L33)
## Supported workflows:
- **Pull requests:**
@@ -35,10 +31,6 @@ doesn't allow this because they doesn't work on a level of individual jobs or st
when `base` input parameter is same as the branch that triggered the workflow:
- Changes are detected from last commit
- Uses git commands to detect changes - repository must be already [checked out](https://github.com/actions/checkout)
- **Local changes**
- Workflow triggered by any event when `base` input parameter is set to `HEAD`
- Changes are detected against current HEAD
- Untracked files are ignored
## Example
```yaml
@@ -56,9 +48,9 @@ doesn't allow this because they doesn't work on a level of individual jobs or st
For more scenarios see [examples](#examples) section.
## Notes:
- Paths expressions are evaluated using [picomatch](https://github.com/micromatch/picomatch) library.
- Paths expressions are evaluated using [minimatch](https://github.com/isaacs/minimatch) library.
Documentation for path expression format can be found on project github page.
- Micromatch [dot](https://github.com/micromatch/picomatch#options) option is set to true.
- Minimatch [dot](https://www.npmjs.com/package/minimatch#dot) option is set to true.
Globbing will match also paths where file or folder name starts with a dot.
- It's recommended to quote your path expressions with `'` or `"`. Otherwise you will get an error if it starts with `*`.
- Local execution with [act](https://github.com/nektos/act) works only with alternative runner image. Default runner doesn't have `git` binary.
@@ -66,16 +58,13 @@ For more scenarios see [examples](#examples) section.
# What's New
- Support local changes
- Fixed retrieval of all changes via Github API when there are 100+ changes
- Paths expressions are now evaluated using [picomatch](https://github.com/micromatch/picomatch) library
- Support workflows triggered by any event
- Fixed compatibility with older (<2.23) versions of git
- Support for tag pushes and tags as a base reference
- Fixes for various edge cases when event payload is incomplete
- Supports local execution with [act](https://github.com/nektos/act)
- Fixed behavior of feature branch workflow:
- Detects only changes introduced by feature branch. Later modifications on base branch are ignored
- Detects only changes introduced by feature branch. Later modifications on base branch are ignored.
- Filter by type of file change:
- Optionally consider if file was added, modified or deleted
@@ -309,35 +298,6 @@ jobs:
```
</details>
<details>
<summary><b>Local changes:</b> Detect staged and unstaged local changes</summary>
```yaml
on:
push:
branches: # Push to following branches will trigger the workflow
- master
- develop
- release/**
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Some action which modifies files tracked by git (e.g. code linter)
- uses: johndoe/some-action@v1
# Filter to detect which files were modified
# Changes could be for example automatically committed
- uses: dorny/paths-filter@v2
id: filter
with:
base: HEAD
filters: ... # Configure your filters
```
</details>
## Advanced options
<details>
@@ -385,15 +345,10 @@ jobs:
# dictionary, where type(s) of change composes the key.
# Multiple change types can be specified using `|` as delimiter.
filters: |
shared: &shared
- common/**
- config/**
addedOrModified:
- added|modified: '**'
allChanges:
- added|deleted|modified: '**'
addedOrModifiedAnchors:
- added|modified: *shared
```
</details>
@@ -445,7 +400,7 @@ jobs:
- name: Lint Markdown
uses: johndoe/some-action@v1
with:
files: ${{ steps.filter.outputs.changed_files }}
files: ${{ steps.filter.changed_files }}
```
</details>

View File

@@ -98,25 +98,6 @@ describe('matching tests', () => {
expect(match.dot).toEqual(files)
})
test('matches all except tsx and less files (negate a group with or-ed parts)', () => {
const yaml = `
backend:
- '!(**/*.tsx|**/*.less)'
`
const filter = new Filter(yaml)
const tsxFiles = modified(['src/ui.tsx'])
const lessFiles = modified(['src/ui.less'])
const pyFiles = modified(['src/server.py'])
const tsxMatch = filter.match(tsxFiles)
const lessMatch = filter.match(lessFiles)
const pyMatch = filter.match(pyFiles)
expect(tsxMatch.backend).toEqual([])
expect(lessMatch.backend).toEqual([])
expect(pyMatch.backend).toEqual(pyFiles)
})
test('matches path based on rules included using YAML anchor', () => {
const yaml = `
shared: &shared
@@ -165,20 +146,6 @@ describe('matching specific change status', () => {
const match = filter.match(files)
expect(match.addOrModify).toEqual(files)
})
test('matches when using an anchor', () => {
const yaml = `
shared: &shared
- common/**/*
- config/**/*
src:
- modified: *shared
`
let filter = new Filter(yaml)
const files = modified(['config/file.js', 'common/anotherFile.js'])
const match = filter.match(files)
expect(match.src).toEqual(files)
})
})
function modified(paths: string[]): File[] {

3378
dist/index.js vendored

File diff suppressed because it is too large Load Diff

362
package-lock.json generated
View File

@@ -3808,12 +3808,6 @@
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
"dev": true
},
"@types/picomatch": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.2.1.tgz",
"integrity": "sha512-26/tQcDmJXYHiaWAAIjnTVL5nwrT+IVaqFZIbBImAuKk/r/j1r/1hmZ7uaOzG6IknqP3QHcNNQ6QO8Vp28lUoA==",
"dev": true
},
"@types/prettier": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.1.tgz",
@@ -4044,111 +4038,6 @@
"requires": {
"micromatch": "^3.1.4",
"normalize-path": "^2.1.1"
},
"dependencies": {
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
"extend-shallow": "^2.0.1",
"fill-range": "^4.0.0",
"isobject": "^3.0.1",
"repeat-element": "^1.1.2",
"snapdragon": "^0.8.1",
"snapdragon-node": "^2.0.1",
"split-string": "^3.0.2",
"to-regex": "^3.0.1"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
"repeat-string": "^1.6.1",
"to-regex-range": "^2.1.0"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"requires": {
"kind-of": "^3.0.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
"braces": "^2.3.1",
"define-property": "^2.0.2",
"extend-shallow": "^3.0.2",
"extglob": "^2.0.4",
"fragment-cache": "^0.2.1",
"kind-of": "^6.0.2",
"nanomatch": "^1.2.9",
"object.pick": "^1.3.0",
"regex-not": "^1.0.0",
"snapdragon": "^0.8.1",
"to-regex": "^3.0.2"
}
},
"to-regex-range": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"dev": true,
"requires": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"
}
}
}
},
"argparse": {
@@ -4889,8 +4778,7 @@
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"base": {
"version": "0.11.2",
@@ -4965,12 +4853,40 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
"extend-shallow": "^2.0.1",
"fill-range": "^4.0.0",
"isobject": "^3.0.1",
"repeat-element": "^1.1.2",
"snapdragon": "^0.8.1",
"snapdragon-node": "^2.0.1",
"split-string": "^3.0.2",
"to-regex": "^3.0.1"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"browser-process-hrtime": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -5229,8 +5145,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"contains-path": {
"version": "0.1.0",
@@ -6569,6 +6484,29 @@
"flat-cache": "^2.0.1"
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
"repeat-string": "^1.6.1",
"to-regex-range": "^2.1.0"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
@@ -6830,26 +6768,6 @@
"kind-of": "^4.0.0"
},
"dependencies": {
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"requires": {
"kind-of": "^3.0.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"kind-of": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
@@ -7203,6 +7121,26 @@
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"requires": {
"kind-of": "^3.0.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -12387,9 +12325,9 @@
}
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
"dev": true
},
"kleur": {
@@ -12540,6 +12478,27 @@
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
"braces": "^2.3.1",
"define-property": "^2.0.2",
"extend-shallow": "^3.0.2",
"extglob": "^2.0.4",
"fragment-cache": "^0.2.1",
"kind-of": "^6.0.2",
"nanomatch": "^1.2.9",
"object.pick": "^1.3.0",
"regex-not": "^1.0.0",
"snapdragon": "^0.8.1",
"to-regex": "^3.0.2"
}
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
@@ -12565,7 +12524,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -13019,7 +12977,8 @@
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"pify": {
"version": "2.3.0",
@@ -13547,114 +13506,11 @@
"walker": "~1.0.5"
},
"dependencies": {
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
"extend-shallow": "^2.0.1",
"fill-range": "^4.0.0",
"isobject": "^3.0.1",
"repeat-element": "^1.1.2",
"snapdragon": "^0.8.1",
"snapdragon-node": "^2.0.1",
"split-string": "^3.0.2",
"to-regex": "^3.0.1"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
"repeat-string": "^1.6.1",
"to-regex-range": "^2.1.0"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
}
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"requires": {
"kind-of": "^3.0.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
"braces": "^2.3.1",
"define-property": "^2.0.2",
"extend-shallow": "^3.0.2",
"extglob": "^2.0.4",
"fragment-cache": "^0.2.1",
"kind-of": "^6.0.2",
"nanomatch": "^1.2.9",
"object.pick": "^1.3.0",
"regex-not": "^1.0.0",
"snapdragon": "^0.8.1",
"to-regex": "^3.0.2"
}
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"to-regex-range": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"dev": true,
"requires": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"
}
}
}
},
@@ -13889,12 +13745,12 @@
"dev": true
},
"source-map-resolve": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
"integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
"integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
"dev": true,
"requires": {
"atob": "^2.1.2",
"atob": "^2.1.1",
"decode-uri-component": "^0.2.0",
"resolve-url": "^0.2.1",
"source-map-url": "^0.4.0",
@@ -14358,6 +14214,16 @@
"safe-regex": "^1.1.0"
}
},
"to-regex-range": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"dev": true,
"requires": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"
}
},
"tough-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",

View File

@@ -29,14 +29,13 @@
"@actions/exec": "^1.0.4",
"@actions/github": "^2.2.0",
"@octokit/webhooks": "^7.6.2",
"picomatch": "^2.2.2"
"minimatch": "^3.0.4"
},
"devDependencies": {
"@types/jest": "^25.2.3",
"@types/js-yaml": "^3.12.4",
"@types/minimatch": "^3.0.3",
"@types/node": "^14.0.5",
"@types/picomatch": "^2.2.1",
"@typescript-eslint/parser": "^3.3.0",
"@zeit/ncc": "^0.22.3",
"eslint": "^7.3.0",

View File

@@ -1,5 +1,5 @@
import * as jsyaml from 'js-yaml'
import picomatch from 'picomatch'
import * as minimatch from 'minimatch'
import {File, ChangeStatus} from './file'
// Type definition of object we expect to load from YAML
@@ -8,11 +8,11 @@ interface FilterYaml {
}
type FilterItemYaml =
| string // Filename pattern, e.g. "path/to/*.js"
| {[changeTypes: string]: string | string[]} // Change status and filename, e.g. added|modified: "path/to/*.js"
| {[changeTypes: string]: string} // Change status and filename, e.g. added|modified: "path/to/*.js"
| FilterItemYaml[] // Supports referencing another rule via YAML anchor
// Minimatch options used in all matchers
const MatchOptions = {
const MinimatchOptions: minimatch.IOptions = {
dot: true
}
@@ -20,7 +20,7 @@ const MatchOptions = {
// Created as simplified form of data in FilterItemYaml
interface FilterRuleItem {
status?: ChangeStatus[] // Required change status of the matched files
isMatch: (str: string) => boolean // Matches the filename
matcher: minimatch.IMinimatch // Matches the filename
}
export interface FilterResults {
@@ -63,7 +63,7 @@ export class Filter {
private isMatch(file: File, patterns: FilterRuleItem[]): boolean {
return patterns.some(
rule => (rule.status === undefined || rule.status.includes(file.status)) && rule.isMatch(file.filename)
rule => (rule.status === undefined || rule.status.includes(file.status)) && rule.matcher.match(file.filename)
)
}
@@ -73,14 +73,14 @@ export class Filter {
}
if (typeof item === 'string') {
return [{status: undefined, isMatch: picomatch(item, MatchOptions)}]
return [{status: undefined, matcher: new minimatch.Minimatch(item, MinimatchOptions)}]
}
if (typeof item === 'object') {
return Object.entries(item).map(([key, pattern]) => {
if (typeof key !== 'string' || (typeof pattern !== 'string' && !Array.isArray(pattern))) {
if (typeof key !== 'string' || typeof pattern !== 'string') {
this.throwInvalidFormatError(
`Expected [key:string]= pattern:string | string[], but [${key}:${typeof key}]= ${pattern}:${typeof pattern} found`
`Expected [key:string]= pattern:string, but [${key}:${typeof key}]= ${pattern}:${typeof pattern} found`
)
}
return {
@@ -89,7 +89,7 @@ export class Filter {
.map(x => x.trim())
.filter(x => x.length > 0)
.map(x => x.toLowerCase()) as ChangeStatus[],
isMatch: picomatch(pattern, MatchOptions)
matcher: new minimatch.Minimatch(pattern, MinimatchOptions)
}
})
}

View File

@@ -3,7 +3,6 @@ import * as core from '@actions/core'
import {File, ChangeStatus} from './file'
export const NULL_SHA = '0000000000000000000000000000000000000000'
export const HEAD = 'HEAD'
export async function getChangesInLastCommit(): Promise<File[]> {
core.startGroup(`Change detection in last commit`)
@@ -40,20 +39,6 @@ export async function getChanges(ref: string): Promise<File[]> {
return parseGitDiffOutput(output)
}
export async function getChangesOnHead(): Promise<File[]> {
// Get current changes - both staged and unstaged
core.startGroup(`Change detection on HEAD`)
let output = ''
try {
output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', 'HEAD'])).stdout
} finally {
fixStdOutNullTermination()
core.endGroup()
}
return parseGitDiffOutput(output)
}
export async function getChangesSinceMergeBase(ref: string, initialFetchDepth: number): Promise<File[]> {
if (!(await hasCommit(ref))) {
// Fetch and add base branch

View File

@@ -55,12 +55,6 @@ function getConfigFileContent(configPath: string): string {
}
async function getChangedFiles(token: string, base: string, initialFetchDepth: number): Promise<File[]> {
// if base is 'HEAD' only local uncommitted changes will be detected
// This is the simplest case as we don't need to fetch more commits or evaluate current/before refs
if (base === git.HEAD) {
return await git.getChangesOnHead()
}
if (github.context.eventName === 'pull_request' || github.context.eventName === 'pull_request_target') {
const pr = github.context.payload.pull_request as Webhooks.WebhookPayloadPullRequestPullRequest
if (token) {
@@ -81,7 +75,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number):
const pushRef =
git.getShortName(github.context.ref) ||
(core.warning(`'ref' field is missing in event payload - using current branch, tag or commit SHA`),
(core.warning(`'ref' field is missing in PUSH event payload - using current branch, tag or commit SHA`),
await git.getCurrentRef())
const baseRef = git.getShortName(base) || defaultRef
@@ -94,11 +88,11 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number):
const isBaseRefSha = git.isGitSha(baseRef)
const isBaseSameAsPush = baseRef === pushRef
// If base is commit SHA we will do comparison against the referenced commit
// Or if base references same branch it was pushed to, we will do comparison against the previously pushed commit
// If base is commit SHA will do comparison against the referenced commit
// Or If base references same branch it was pushed to, we will do comparison against the previously pushed commit
if (isBaseRefSha || isBaseSameAsPush) {
if (!isBaseRefSha && !beforeSha) {
core.warning(`'before' field is missing in event payload - changes will be detected from last commit`)
core.warning(`'before' field is missing in PUSH event payload - changes will be detected from last commit`)
return await git.getChangesInLastCommit()
}
@@ -129,13 +123,11 @@ async function getChangedFilesFromApi(
token: string,
pullRequest: Webhooks.WebhookPayloadPullRequestPullRequest
): Promise<File[]> {
core.startGroup(`Fetching list of changed files for PR#${pullRequest.number} from Github API`)
core.info(`Number of changed_files is ${pullRequest.changed_files}`)
core.info(`Fetching list of changed files for PR#${pullRequest.number} from Github API`)
const client = new github.GitHub(token)
const pageSize = 100
const files: File[] = []
for (let page = 1; (page - 1) * pageSize < pullRequest.changed_files; page++) {
core.info(`Invoking listFiles(pull_number: ${pullRequest.number}, page: ${page}, per_page: ${pageSize})`)
for (let page = 0; page * pageSize < pullRequest.changed_files; page++) {
const response = await client.pulls.listFiles({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
@@ -144,7 +136,6 @@ async function getChangedFilesFromApi(
per_page: pageSize
})
for (const row of response.data) {
core.info(`[${row.status}] ${row.filename}`)
// There's no obvious use-case for detection of renames
// Therefore we treat it as if rename detection in git diff was turned off.
// Rename is replaced by delete of original filename and add of new filename
@@ -159,17 +150,14 @@ async function getChangedFilesFromApi(
status: ChangeStatus.Deleted
})
} else {
// Github status and git status variants are same except for deleted files
const status = row.status === 'removed' ? ChangeStatus.Deleted : (row.status as ChangeStatus)
files.push({
filename: row.filename,
status
status: row.status as ChangeStatus
})
}
}
}
core.endGroup()
return files
}