mirror of
https://github.com/dorny/paths-filter.git
synced 2024-12-20 00:49:04 +00:00
Fix globbing, update metadata, update ncc (#4)
* Enable minimatch dot option It's not a default globbing behavior, however for our use-case is much more convenient to match those files. * Update README and package.json
This commit is contained in:
parent
f9b6173f5e
commit
29d498d99d
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
@ -1,5 +1,5 @@
|
||||
name: "build-test"
|
||||
on: # rebuild any PRs and main branch changes
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
@ -8,14 +8,15 @@ on: # rebuild any PRs and main branch changes
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build: # make sure build/ci work properly
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
npm install
|
||||
npm run all
|
||||
test: # make sure the action works without building
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -30,6 +30,10 @@ Output variables can be later used in the `if` clause to conditionally run speci
|
||||
- `'false'` - if **none** of changed files matches any of rule patterns
|
||||
|
||||
|
||||
### Notes
|
||||
- minimatch [dot](https://www.npmjs.com/package/minimatch#dot) option is set to true - therefore
|
||||
globbing will match also paths where file or folder name starts with a dot.
|
||||
|
||||
### Sample workflow
|
||||
```yaml
|
||||
...
|
||||
@ -94,4 +98,4 @@ jobs:
|
||||
- [Changed File Filter](https://github.com/tony84727/changed-file-filter)
|
||||
- allows change detection between any refs or commits
|
||||
- fetches whole history of your git repository
|
||||
- might have negative performance impact on big repositories (github by default fetches only single commit)
|
||||
- might have negative performance impact on big repositories (github by default fetches only single commit)
|
@ -80,4 +80,14 @@ describe('matching tests', () => {
|
||||
const match = filter.match(['test/test.js'])
|
||||
expect(match.any).toBeTruthy()
|
||||
})
|
||||
|
||||
test('globbing matches path where file or folder name starts with dot', () => {
|
||||
const yaml = `
|
||||
dot:
|
||||
- "**/*.js"
|
||||
`
|
||||
const filter = new Filter(yaml)
|
||||
const match = filter.match(['.test/.test.js'])
|
||||
expect(match.dot).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
237
dist/index.js
vendored
237
dist/index.js
vendored
@ -19,7 +19,13 @@ module.exports =
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/ var threw = true;
|
||||
/******/ try {
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/ threw = false;
|
||||
/******/ } finally {
|
||||
/******/ if(threw) delete installedModules[moduleId];
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
@ -296,9 +302,9 @@ module.exports = require("tls");
|
||||
/***/ }),
|
||||
|
||||
/***/ 18:
|
||||
/***/ (function() {
|
||||
/***/ (function(module) {
|
||||
|
||||
eval("require")("encoding");
|
||||
module.exports = eval("require")("encoding");
|
||||
|
||||
|
||||
/***/ }),
|
||||
@ -4090,74 +4096,74 @@ function checkMode (stat, options) {
|
||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(__webpack_require__(470));
|
||||
const github = __importStar(__webpack_require__(469));
|
||||
const filter_1 = __importDefault(__webpack_require__(235));
|
||||
function run() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const token = core.getInput('githubToken', { required: true });
|
||||
const filterYaml = core.getInput('filters', { required: true });
|
||||
const client = new github.GitHub(token);
|
||||
if (github.context.eventName !== 'pull_request') {
|
||||
core.setFailed('This action can be triggered only by pull_request event');
|
||||
return;
|
||||
}
|
||||
const pr = github.context.payload.pull_request;
|
||||
const filter = new filter_1.default(filterYaml);
|
||||
const files = yield getChangedFiles(client, pr);
|
||||
const result = filter.match(files);
|
||||
for (const key in result) {
|
||||
core.setOutput(key, String(result[key]));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Uses github REST api to get list of files changed in PR
|
||||
function getChangedFiles(client, pullRequest) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const pageSize = 100;
|
||||
const files = [];
|
||||
for (let page = 0; page * pageSize < pullRequest.changed_files; page++) {
|
||||
const response = yield client.pulls.listFiles({
|
||||
owner: github.context.repo.owner,
|
||||
repo: github.context.repo.repo,
|
||||
pull_number: pullRequest.number,
|
||||
page,
|
||||
per_page: pageSize
|
||||
});
|
||||
for (const row of response.data) {
|
||||
files.push(row.filename);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
});
|
||||
}
|
||||
run();
|
||||
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(__webpack_require__(470));
|
||||
const github = __importStar(__webpack_require__(469));
|
||||
const filter_1 = __importDefault(__webpack_require__(235));
|
||||
function run() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const token = core.getInput('githubToken', { required: true });
|
||||
const filterYaml = core.getInput('filters', { required: true });
|
||||
const client = new github.GitHub(token);
|
||||
if (github.context.eventName !== 'pull_request') {
|
||||
core.setFailed('This action can be triggered only by pull_request event');
|
||||
return;
|
||||
}
|
||||
const pr = github.context.payload.pull_request;
|
||||
const filter = new filter_1.default(filterYaml);
|
||||
const files = yield getChangedFiles(client, pr);
|
||||
const result = filter.match(files);
|
||||
for (const key in result) {
|
||||
core.setOutput(key, String(result[key]));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Uses github REST api to get list of files changed in PR
|
||||
function getChangedFiles(client, pullRequest) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const pageSize = 100;
|
||||
const files = [];
|
||||
for (let page = 0; page * pageSize < pullRequest.changed_files; page++) {
|
||||
const response = yield client.pulls.listFiles({
|
||||
owner: github.context.repo.owner,
|
||||
repo: github.context.repo.repo,
|
||||
pull_number: pullRequest.number,
|
||||
page,
|
||||
per_page: pageSize
|
||||
});
|
||||
for (const row of response.data) {
|
||||
files.push(row.filename);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
});
|
||||
}
|
||||
run();
|
||||
|
||||
|
||||
/***/ }),
|
||||
@ -4223,49 +4229,52 @@ module.exports = new Type('tag:yaml.org,2002:bool', {
|
||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const jsyaml = __importStar(__webpack_require__(414));
|
||||
const minimatch = __importStar(__webpack_require__(595));
|
||||
class Filter {
|
||||
constructor(yaml) {
|
||||
this.rules = {};
|
||||
const doc = jsyaml.safeLoad(yaml);
|
||||
if (typeof doc !== 'object') {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
for (const name of Object.keys(doc)) {
|
||||
const patterns = doc[name];
|
||||
if (!Array.isArray(patterns)) {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
if (!patterns.every(x => typeof x === 'string')) {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
this.rules[name] = patterns.map(x => new minimatch.Minimatch(x));
|
||||
}
|
||||
}
|
||||
// Returns dictionary with match result per rules group
|
||||
match(paths) {
|
||||
const result = {};
|
||||
for (const [key, patterns] of Object.entries(this.rules)) {
|
||||
const match = paths.some(fileName => patterns.some(rule => rule.match(fileName)));
|
||||
result[key] = match;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throwInvalidFormatError() {
|
||||
throw new Error('Invalid filter YAML format: Expected dictionary of string arrays');
|
||||
}
|
||||
}
|
||||
exports.default = Filter;
|
||||
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const jsyaml = __importStar(__webpack_require__(414));
|
||||
const minimatch = __importStar(__webpack_require__(595));
|
||||
class Filter {
|
||||
constructor(yaml) {
|
||||
this.rules = {};
|
||||
const doc = jsyaml.safeLoad(yaml);
|
||||
if (typeof doc !== 'object') {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
const opts = {
|
||||
dot: true
|
||||
};
|
||||
for (const name of Object.keys(doc)) {
|
||||
const patterns = doc[name];
|
||||
if (!Array.isArray(patterns)) {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
if (!patterns.every(x => typeof x === 'string')) {
|
||||
this.throwInvalidFormatError();
|
||||
}
|
||||
this.rules[name] = patterns.map(x => new minimatch.Minimatch(x, opts));
|
||||
}
|
||||
}
|
||||
// Returns dictionary with match result per rules group
|
||||
match(paths) {
|
||||
const result = {};
|
||||
for (const [key, patterns] of Object.entries(this.rules)) {
|
||||
const match = paths.some(fileName => patterns.some(rule => rule.match(fileName)));
|
||||
result[key] = match;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throwInvalidFormatError() {
|
||||
throw new Error('Invalid filter YAML format: Expected dictionary of string arrays');
|
||||
}
|
||||
}
|
||||
exports.default = Filter;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
10
package-lock.json
generated
10
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "typescript-action",
|
||||
"version": "0.0.0",
|
||||
"name": "pr-changed-files-filter",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -878,9 +878,9 @@
|
||||
}
|
||||
},
|
||||
"@zeit/ncc": {
|
||||
"version": "0.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
|
||||
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
|
||||
"version": "0.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.22.2.tgz",
|
||||
"integrity": "sha512-LGW5RPIwulh+fyKiMTgbIEbdc/hdf/4+U5B1WbT/We0jweHoywDbk9hi+3hNjSzQNShGumP72zgc6PHEUG5syg==",
|
||||
"dev": true
|
||||
},
|
||||
"abab": {
|
||||
|
10
package.json
10
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "typescript-action",
|
||||
"version": "0.0.0",
|
||||
"name": "pr-changed-files-filter",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "TypeScript template action",
|
||||
"description": "Enables conditional execution of workflow job steps considering which files are modified by a pull request.",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
@ -36,7 +36,7 @@
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"@zeit/ncc": "^0.22.2",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"eslint-plugin-jest": "^22.21.0",
|
||||
@ -49,5 +49,5 @@
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,10 @@ export default class Filter {
|
||||
this.throwInvalidFormatError()
|
||||
}
|
||||
|
||||
const opts: minimatch.IOptions = {
|
||||
dot: true
|
||||
}
|
||||
|
||||
for (const name of Object.keys(doc)) {
|
||||
const patterns = doc[name] as string[]
|
||||
if (!Array.isArray(patterns)) {
|
||||
@ -18,7 +22,7 @@ export default class Filter {
|
||||
if (!patterns.every(x => typeof x === 'string')) {
|
||||
this.throwInvalidFormatError()
|
||||
}
|
||||
this.rules[name] = patterns.map(x => new minimatch.Minimatch(x))
|
||||
this.rules[name] = patterns.map(x => new minimatch.Minimatch(x, opts))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user