Adds global filter option

This commit is contained in:
Henry Painter 2022-08-14 18:14:01 +01:00
parent 9a3e560c61
commit 14827485d3
7 changed files with 83 additions and 20 deletions

2
.github/filterignore vendored Normal file
View file

@ -0,0 +1,2 @@
**/*.ts
**/*.nothing

View file

@ -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

View file

@ -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[] {

View 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

File diff suppressed because one or more lines are too long

View file

@ -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 (

View file

@ -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)