dorny / paths-filter

Conditionally run actions based on files modified by PR, feature branch or pushed commits
MIT License
2.14k stars 239 forks source link

Excluding file via negation is not working as expected #135

Open Superskyyy opened 2 years ago

Superskyyy commented 2 years ago

For example below, I added a rootFiles and expect it to match nothing, however, it actually matches the root.tsx.

  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 rootFiles = modified(['root.tsx'])

    const tsxMatch = filter.match(tsxFiles)
    const lessMatch = filter.match(lessFiles)
    const pyMatch = filter.match(pyFiles)
    const rootMatch = filter.match(rootFiles)

    expect(tsxMatch.backend).toEqual([])
    expect(lessMatch.backend).toEqual([])
    expect(pyMatch.backend).toEqual(pyFiles)
    expect(rootMatch.backend).toEqual([])
> 120 |     expect(rootMatch.backend).toEqual([])
      |                               ^
  121 | 
  122 |   })
  123 | 

  at Object.<anonymous> (__tests__/filter.test.ts:120:31)
  at processTicksAndRejections (node:internal/process/task_queues:96:5)
jbarmash commented 1 year ago

We've used this, and it worked great for us, although it's become out of date recently due to no node 12 support on GHA.

https://github.com/AurorNZ/paths-filter

AndreyNautilus commented 11 months ago

@Superskyyy I think that your expectation expect(rootMatch.backend).toEqual([]) is incorrect.

According to picomatch documentation - the underlying matching library - a pattern like **/*.tsx requires at least 1 path separator, so in your example root.tsx doesn't match that part of the pattern and after negation actually matches the pattern.

If we try picomatch directly:

const picomatch = require('picomatch');
const pattern = '!(**/*.tsx|**/*.less)';
console.log(picomatch.isMatch('root.tsx', pattern));

returns true. If you want to ignore all *.tsx files regardless of their location, you should replace **/* with just ** in the pattern, see:

const picomatch = require('picomatch');
const pattern = '!(**.tsx|**/*.less)';  // new pattern
console.log(picomatch.isMatch('root.tsx', pattern));

returns false.