mirror of
https://gitea.com/actions/dorny-paths-filter.git
synced 2026-08-21 16:13:13 +01:00
Compare commits
4 Commits
retry-tran
...
v4.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceb8a2b8f2 | ||
|
|
ef09b88f3e | ||
|
|
44adc5b06d | ||
|
|
93c889f9e5 |
16
.github/workflows/pull-request-verification.yml
vendored
16
.github/workflows/pull-request-verification.yml
vendored
@@ -193,7 +193,9 @@ jobs:
|
||||
excludesOnly:
|
||||
- '!**/*.md'
|
||||
- name: Print 'mobile_files'
|
||||
run: echo ${{steps.filter.outputs.mobile_files}}
|
||||
env:
|
||||
MOBILE_FILES: ${{ steps.filter.outputs.mobile_files }}
|
||||
run: echo "$MOBILE_FILES"
|
||||
- name: filter-test
|
||||
if: |
|
||||
steps.filter.outputs.mobile != 'true'
|
||||
@@ -227,11 +229,17 @@ jobs:
|
||||
any:
|
||||
- added|deleted|modified: "*"
|
||||
- name: Print 'added_files'
|
||||
run: echo ${{steps.filter.outputs.added_files}}
|
||||
env:
|
||||
ADDED_FILES: ${{ steps.filter.outputs.added_files }}
|
||||
run: echo "$ADDED_FILES"
|
||||
- name: Print 'modified_files'
|
||||
run: echo ${{steps.filter.outputs.modified_files}}
|
||||
env:
|
||||
MODIFIED_FILES: ${{ steps.filter.outputs.modified_files }}
|
||||
run: echo "$MODIFIED_FILES"
|
||||
- name: Print 'deleted_files'
|
||||
run: echo ${{steps.filter.outputs.deleted_files}}
|
||||
env:
|
||||
DELETED_FILES: ${{ steps.filter.outputs.deleted_files }}
|
||||
run: echo "$DELETED_FILES"
|
||||
- name: filter-test
|
||||
if: |
|
||||
steps.filter.outputs.added != 'true'
|
||||
|
||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## v4.0.3
|
||||
- [Document safe handling of file list outputs in workflows](https://github.com/dorny/paths-filter/pull/326)
|
||||
- [Escape multi-line filenames in list-files shell and csv output](https://github.com/advisories/GHSA-7hc6-8hq5-9q2m)
|
||||
- [Add 'some-with-excludes' predicate quantifier](https://github.com/dorny/paths-filter/pull/322)
|
||||
- [Add contents permission to PR example](https://github.com/dorny/paths-filter/pull/248)
|
||||
- [Scope base-ignored warning to API path](https://github.com/dorny/paths-filter/pull/319)
|
||||
- [Update outputs in readme to account for the 'every' predicate-quantifier](https://github.com/dorny/paths-filter/pull/247)
|
||||
|
||||
## v4.0.2
|
||||
- [Work around git dubious ownership errors in container jobs](https://github.com/dorny/paths-filter/pull/317)
|
||||
- [Use rev-parse instead of branch --show-current for older git compat](https://github.com/dorny/paths-filter/pull/303)
|
||||
@@ -11,6 +19,9 @@
|
||||
## v4.0.0
|
||||
- [Update action runtime to node24](https://github.com/dorny/paths-filter/pull/294)
|
||||
|
||||
## v3.0.4
|
||||
- [Escape multi-line filenames in list-files shell and csv output](https://github.com/advisories/GHSA-7hc6-8hq5-9q2m)
|
||||
|
||||
## v3.0.3
|
||||
- [Add missing predicate-quantifier](https://github.com/dorny/paths-filter/pull/279)
|
||||
|
||||
|
||||
14
README.md
14
README.md
@@ -67,6 +67,10 @@ For more scenarios see [examples](#examples) section.
|
||||
|
||||
## Notes
|
||||
|
||||
- **Security:** `${FILTER_NAME}_files` outputs contain filenames that may be attacker-influenced on pull requests.
|
||||
Do not interpolate them directly into a `run:` script with `${{ ... }}`.
|
||||
Pass the value through `env:` and reference the variable from the shell instead.
|
||||
See [Custom processing of changed files](#custom-processing-of-changed-files).
|
||||
- Paths expressions are evaluated using [picomatch](https://github.com/micromatch/picomatch) library.
|
||||
Documentation for path expression format can be found on the project GitHub page.
|
||||
- Picomatch [dot](https://github.com/micromatch/picomatch#options) option is set to true.
|
||||
@@ -205,7 +209,7 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob
|
||||
- `'true'` - if **any** changed file matches **at least one** of the filter's rules and **none** of its negated rules
|
||||
- `'false'` - if **no** changed file matches **at least one** of the filter's rules and **none** of its negated rules
|
||||
- Each filter 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.
|
||||
- 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. Treat these values as untrusted when filenames can come from pull requests.
|
||||
- `changes` - JSON array with names of all filters matching any of the changed files.
|
||||
|
||||
## Examples
|
||||
@@ -589,9 +593,13 @@ jobs:
|
||||
- added|modified: '*.md'
|
||||
- name: Lint Markdown
|
||||
if: ${{ steps.filter.outputs.markdown == 'true' }}
|
||||
run: npx textlint ${{ steps.filter.outputs.markdown_files }}
|
||||
env:
|
||||
MARKDOWN_FILES: ${{ steps.filter.outputs.markdown_files }}
|
||||
run: npx textlint $MARKDOWN_FILES
|
||||
```
|
||||
|
||||
When passing file lists to shell commands, use `env:` as shown above. Do not write `${{ steps.filter.outputs.markdown_files }}` directly inside the `run:` script.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -617,6 +625,8 @@ jobs:
|
||||
files: ${{ steps.filter.outputs.changed_files }}
|
||||
```
|
||||
|
||||
The `json` and `csv` formats are intended as structured data for scripts, programs, or other actions. Passing them to an action input as above is fine. Do not interpolate `json` or `csv` outputs directly into a `run:` script.
|
||||
|
||||
</details>
|
||||
|
||||
## See also
|
||||
|
||||
@@ -20,4 +20,12 @@ describe('csvEscape() backslash escapes every character except subset of definit
|
||||
test('Double quote should be escaped by another double quote', () => {
|
||||
expect(csvEscape('file " with double quote')).toBe('"file "" with double quote"')
|
||||
})
|
||||
|
||||
test('filename with LF should be quoted per RFC 4180', () => {
|
||||
expect(csvEscape('a\nb')).toBe('"a\nb"')
|
||||
})
|
||||
|
||||
test('filename with CRLF should be quoted per RFC 4180', () => {
|
||||
expect(csvEscape('a\r\nb')).toBe('"a\r\nb"')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -54,4 +54,16 @@ describe('shellEscape() returns human readable filenames with as few escaping ap
|
||||
test('filename with single quote and special characters is split and quoted/escaped as needed', () => {
|
||||
expect(shellEscape("file'with $quote")).toBe("file\\''with $quote'")
|
||||
})
|
||||
|
||||
test('filename with LF should be single-quoted', () => {
|
||||
expect(shellEscape('x\ntouch pwned.md')).toBe("'x\ntouch pwned.md'")
|
||||
})
|
||||
|
||||
test('filename with CRLF should be single-quoted', () => {
|
||||
expect(shellEscape('x\r\ntouch pwned.md')).toBe("'x\r\ntouch pwned.md'")
|
||||
})
|
||||
|
||||
test('filename with CR should be single-quoted', () => {
|
||||
expect(shellEscape('a\rb')).toBe("'a\rb'")
|
||||
})
|
||||
})
|
||||
|
||||
1661
dist/index.js
vendored
1661
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
48
package-lock.json
generated
48
package-lock.json
generated
@@ -12,7 +12,6 @@
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "6.0.0",
|
||||
"@octokit/plugin-retry": "^6.1.0",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -200,6 +199,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
|
||||
"integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
@@ -1391,6 +1391,7 @@
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz",
|
||||
"integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.0.0",
|
||||
@@ -1462,38 +1463,6 @@
|
||||
"@octokit/core": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz",
|
||||
"integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "8.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
|
||||
@@ -1926,6 +1895,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2326,12 +2296,6 @@
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||
},
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
@@ -2372,6 +2336,7 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001565",
|
||||
"electron-to-chromium": "^1.4.601",
|
||||
@@ -2918,6 +2883,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
|
||||
"integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
@@ -2973,6 +2939,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
|
||||
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
},
|
||||
@@ -3147,6 +3114,7 @@
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz",
|
||||
"integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -4654,6 +4622,7 @@
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
|
||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^29.7.0",
|
||||
"@jest/types": "^29.6.3",
|
||||
@@ -6829,6 +6798,7 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
|
||||
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "6.0.0",
|
||||
"@octokit/plugin-retry": "^6.1.0",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,7 +4,7 @@ export function csvEscape(value: string): string {
|
||||
if (value === '') return value
|
||||
|
||||
// Only safe characters
|
||||
if (/^[a-zA-Z0-9._+:@%/-]+$/m.test(value)) {
|
||||
if (/^[a-zA-Z0-9._+:@%/-]+$/.test(value)) {
|
||||
return value
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ export function shellEscape(value: string): string {
|
||||
if (value === '') return value
|
||||
|
||||
// Only safe characters
|
||||
if (/^[a-zA-Z0-9,._+:@%/-]+$/m.test(value)) {
|
||||
if (/^[a-zA-Z0-9,._+:@%/-]+$/.test(value)) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (value.includes("'")) {
|
||||
// Only safe characters, single quotes and white-spaces
|
||||
if (/^[a-zA-Z0-9,._+:@%/'\s-]+$/m.test(value)) {
|
||||
if (/^[a-zA-Z0-9,._+:@%/'\s-]+$/.test(value)) {
|
||||
return `"${value}"`
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as fs from 'fs'
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {retry} from '@octokit/plugin-retry'
|
||||
import {GetResponseDataTypeFromEndpointMethod} from '@octokit/types'
|
||||
import {MergeGroupEvent, PullRequest, PushEvent} from '@octokit/webhooks-types'
|
||||
|
||||
@@ -205,7 +204,7 @@ async function getChangedFilesFromGit(base: string, head: string, initialFetchDe
|
||||
async function getChangedFilesFromApi(token: string, pullRequest: PullRequest): Promise<File[]> {
|
||||
core.startGroup(`Fetching list of changed files for PR#${pullRequest.number} from GitHub API`)
|
||||
try {
|
||||
const client = github.getOctokit(token, undefined, retry)
|
||||
const client = github.getOctokit(token)
|
||||
const per_page = 100
|
||||
const files: File[] = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user