mirror of
https://github.com/dorny/paths-filter.git
synced 2025-06-08 00:59:04 +00:00
Adds global filter option
This commit is contained in:
parent
9a3e560c61
commit
14827485d3
7 changed files with 83 additions and 20 deletions
2
.github/filterignore
vendored
Normal file
2
.github/filterignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
**/*.ts
|
||||
**/*.nothing
|
36
.github/workflows/pull-request-verification.yml
vendored
36
.github/workflows/pull-request-verification.yml
vendored
|
@ -247,3 +247,39 @@ jobs:
|
|||
if: steps.filter.outputs.anyignoreall_count != 2
|
||||
run: |
|
||||
exit 1
|
||||
|
||||
test-global-ignore:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
echo "NEW FILE" > local.ts
|
||||
echo "IGNORE FILE" > local.md
|
||||
- run: git add local.ts local.md
|
||||
- uses: ./
|
||||
id: filter
|
||||
with:
|
||||
base: HEAD
|
||||
filters: |
|
||||
error:
|
||||
- not_existing_path/**/*
|
||||
any:
|
||||
- "**/*"
|
||||
anyignore:
|
||||
-
|
||||
paths: "**/*"
|
||||
paths_ignore:
|
||||
- "**local.md"
|
||||
global-ignore: .github/filterignore
|
||||
- name: print context
|
||||
run: |
|
||||
echo "${{ tojson(steps.filter) }}"
|
||||
- name: filter-test
|
||||
if: steps.filter.outputs.any_count != 1
|
||||
run: exit 1
|
||||
- name: ignore-test
|
||||
if: steps.filter.outputs.anyignore == true
|
||||
run: exit 1
|
||||
- name: ignore_testnull
|
||||
if: steps.filter.outputs.error == true
|
||||
run: exit 1
|
|
@ -192,6 +192,26 @@ describe('matching specific change status', () => {
|
|||
const match = filter.match(files)
|
||||
expect(match.ignore).toEqual(modified(['config/settings.yml']))
|
||||
})
|
||||
test('matches path based on rules including using global ignore', () => {
|
||||
const yaml = `
|
||||
ignore:
|
||||
-
|
||||
paths: ["**/*"]
|
||||
paths_ignore:
|
||||
- "**.md"
|
||||
ignoreall:
|
||||
-
|
||||
paths: ["**/*"]
|
||||
paths_ignore:
|
||||
- "**.md"
|
||||
- "**.yml"
|
||||
`
|
||||
const filter = new Filter(yaml, ['**.this'])
|
||||
const files = modified(['config/settings.yml', 'config/settings.md', 'nothing/todo/with.this'])
|
||||
const match = filter.match(files)
|
||||
expect(match.ignore).toEqual(modified(['config/settings.yml']))
|
||||
expect(match.ignoreall).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
function modified(paths: string[]): File[] {
|
||||
|
|
|
@ -50,6 +50,11 @@ inputs:
|
|||
This option takes effect only when changes are detected using git against different base branch.
|
||||
required: false
|
||||
default: '100'
|
||||
global-ignore:
|
||||
description: |
|
||||
Globally set ignore patterns on all filters via a file. Accepts a file path to a file with new line separate list.
|
||||
Like a .gitignore but for your filtering.
|
||||
required: false
|
||||
outputs:
|
||||
changes:
|
||||
description: JSON array with names of all filters matching any of changed files
|
||||
|
|
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
|
@ -12,16 +12,12 @@ type includesFilter =
|
|||
| string[] // Array of filename patterns e.g. ["path/to/thing/**", "path/to/another/**"]
|
||||
| {[changeTypes: string]: string | string[]} // Change status and filename, e.g. added|modified: "path/to/*.js"
|
||||
|
||||
type excludesFilter = string[] // Filename pattern, e.g. "path/to/*.js"
|
||||
export type excludesFilter = string[] // Filename pattern, e.g. "path/to/*.js"
|
||||
|
||||
// Minimatch options used in all matchers
|
||||
type matchoptions = {
|
||||
dot: boolean
|
||||
ignore: string[]
|
||||
}
|
||||
const defaultMatchOptions: matchoptions = {
|
||||
dot: true,
|
||||
ignore: []
|
||||
ignore: excludesFilter
|
||||
}
|
||||
|
||||
// Internal representation of one item in named filter rule
|
||||
|
@ -37,16 +33,15 @@ export interface FilterResults {
|
|||
|
||||
export class Filter {
|
||||
rules: {[key: string]: FilterRuleItem[]} = {}
|
||||
|
||||
// Creates instance of Filter and load rules from YAML if it's provided
|
||||
constructor(yaml?: string) {
|
||||
constructor(yaml?: string, globalIgnoreArray: excludesFilter = []) {
|
||||
if (yaml) {
|
||||
this.load(yaml)
|
||||
this.load(yaml, globalIgnoreArray)
|
||||
}
|
||||
}
|
||||
|
||||
// Load rules from YAML string
|
||||
load(yaml: string): void {
|
||||
load(yaml: string, globalIgnoreArray: excludesFilter): void {
|
||||
const doc = jsyaml.load(yaml) as FilterYaml
|
||||
if (typeof doc !== 'object') {
|
||||
this.throwInvalidFormatError('Root element is not an object')
|
||||
|
@ -62,7 +57,7 @@ export class Filter {
|
|||
)} type: ${typeof item} isarray?: ${Array.isArray(item)}`
|
||||
)
|
||||
}
|
||||
this.rules[key] = this.parseFilterItemYaml(item)
|
||||
this.rules[key] = this.parseFilterItemYaml(item, [], globalIgnoreArray)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,19 +75,23 @@ export class Filter {
|
|||
)
|
||||
}
|
||||
|
||||
private parseFilterItemYaml(item: FilterItemYaml, excludes: excludesFilter = []): FilterRuleItem[] {
|
||||
var MatchOptions: matchoptions = Object.assign(defaultMatchOptions)
|
||||
MatchOptions.ignore = excludes
|
||||
private parseFilterItemYaml(
|
||||
item: FilterItemYaml,
|
||||
excludes: excludesFilter = [],
|
||||
globalIgnoreArray: excludesFilter
|
||||
): FilterRuleItem[] {
|
||||
let MatchOptions: matchoptions = {dot: true, ignore: []}
|
||||
MatchOptions.ignore.push(...excludes, ...globalIgnoreArray)
|
||||
if (typeof item === 'string' || this.isStringsArray(item as string[])) {
|
||||
return [{status: undefined, isMatch: picomatch(item as string | string[], MatchOptions)}]
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
return flat(item.map(i => this.parseFilterItemYaml(i, excludes)))
|
||||
return flat(item.map(i => this.parseFilterItemYaml(i, excludes, globalIgnoreArray)))
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
var len = Object.keys(item).length
|
||||
if (len == 2 && item.paths_ignore && item.paths) {
|
||||
return this.parseFilterItemYaml(item.paths, item.paths_ignore as excludesFilter)
|
||||
return this.parseFilterItemYaml(item.paths, item.paths_ignore as excludesFilter, globalIgnoreArray)
|
||||
} else if (len == 1) {
|
||||
return Object.entries(item).map(([key, pattern]) => {
|
||||
if (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as fs from 'fs'
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {Filter, FilterResults} from './filter'
|
||||
import {excludesFilter, Filter, FilterResults} from './filter'
|
||||
import {File, ChangeStatus} from './file'
|
||||
import * as git from './git'
|
||||
import {backslashEscape, shellEscape} from './list-format/shell-escape'
|
||||
|
@ -13,7 +13,8 @@ async function run(): Promise<void> {
|
|||
if (workingDirectory) {
|
||||
process.chdir(workingDirectory)
|
||||
}
|
||||
|
||||
const globalIgnore = core.getInput('global-ignore', {required: false})
|
||||
const globalIgnoreArray: excludesFilter = globalIgnore ? getConfigFileContent(globalIgnore).split(/\r?\n/) : []
|
||||
const customfiles = core.getInput('files', {required: false})
|
||||
const token = core.getInput('token', {required: false})
|
||||
const ref = core.getInput('ref', {required: false})
|
||||
|
@ -32,7 +33,7 @@ async function run(): Promise<void> {
|
|||
return
|
||||
}
|
||||
|
||||
const filter = new Filter(filtersYaml)
|
||||
const filter = new Filter(filtersYaml, globalIgnoreArray)
|
||||
core.info(`Detected ${files.length} changed files`)
|
||||
const results = filter.match(files)
|
||||
exportResults(results, listFiles)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue