From 84c311ff395f16c9295f7c2be9d15bbe48f1a41e Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Wed, 29 Nov 2023 11:40:57 -0500 Subject: [PATCH 01/20] Modify set of possible inputs in action.yaml --- action.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/action.yaml b/action.yaml index 02c84c5..4bba380 100644 --- a/action.yaml +++ b/action.yaml @@ -3,7 +3,14 @@ description: Create "matrix" compliant file/folder lists using patterns inputs: patterns: description: The pattern(s) with which to match files/folders - required: true + root-patterns: + description: > + The pattern(s) to which all files/folders matched by `filter-patterns` + will be hoisted + filter-patterns: + description: > + The pattern(s) that will be used to filter (but not match) files/folders + default: '**' outputs: matches: description: The files/folders that matched the pattern From 5428d783dc4a704cef3543b3b3537ce28ffdb901 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 10:29:17 -0500 Subject: [PATCH 02/20] Change configuration for import/extensions rule --- .eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.js b/.eslintrc.js index 1a02db6..f555eac 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,5 +22,6 @@ module.exports = { sourceType: 'module', }, rules: { + 'import/extensions': ['error', 'ignorePackages'], }, }; From aa022fd1f76a2e828a1b7e8cbf4c718d2eaaecd5 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 10:35:38 -0500 Subject: [PATCH 03/20] Add support for new "hoisting" inputs --- dist/main.js | 23 ++++++++++++++++++++--- main.mjs | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/dist/main.js b/dist/main.js index 954fe58..4259cca 100755 --- a/dist/main.js +++ b/dist/main.js @@ -21873,10 +21873,10 @@ var require_string = __commonJS({ return typeof input === "string"; } exports.isString = isString; - function isEmpty(input) { + function isEmpty2(input) { return input === ""; } - exports.isEmpty = isEmpty; + exports.isEmpty = isEmpty2; } }); @@ -24688,8 +24688,25 @@ var generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync); var { convertPathToPattern } = import_fast_glob2.default; // main.mjs +function isEmpty(xs) { + return xs.length === 0; +} +function getInputs() { + const patterns = core.getMultilineInput("patterns"); + const rootPatterns = core.getMultilineInput("rootPatterns"); + if (isEmpty(patterns) && isEmpty(rootPatterns)) { + throw new Error('Either "patterns" or "root-patterns" must be provided'); + } + if (!isEmpty(patterns) && !isEmpty(rootPatterns)) { + throw new Error('Only one of "patterns" or "root-patterns" can be provided'); + } + const filterPatterns = core.getMultilineInput("filter-patterns", { + required: true + }); + return { patterns, rootPatterns, filterPatterns }; +} (async () => { - const patterns = core.getMultilineInput("patterns", { required: true }); + const { patterns } = getInputs(); const matches = await globby(patterns, { expandDirectories: false, gitignore: true, diff --git a/main.mjs b/main.mjs index 346eb29..fb97eaa 100755 --- a/main.mjs +++ b/main.mjs @@ -2,8 +2,27 @@ import * as core from '@actions/core'; import { globby } from 'globby'; +function isEmpty(xs) { + return xs.length === 0; +} + +function getInputs() { + const patterns = core.getMultilineInput('patterns'); + const rootPatterns = core.getMultilineInput('rootPatterns'); + if (isEmpty(patterns) && isEmpty(rootPatterns)) { + throw new Error('Either "patterns" or "root-patterns" must be provided'); + } + if (!isEmpty(patterns) && !isEmpty(rootPatterns)) { + throw new Error('Only one of "patterns" or "root-patterns" can be provided'); + } + const filterPatterns = core.getMultilineInput('filter-patterns', { + required: true, + }); + return { patterns, rootPatterns, filterPatterns }; +} + (async () => { - const patterns = core.getMultilineInput('patterns', { required: true }); + const { patterns } = getInputs(); const matches = await globby(patterns, { expandDirectories: false, gitignore: true, From 640a4d2bff5b3dd7e02ea9134e6e48ec446bba62 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 13:37:56 -0500 Subject: [PATCH 04/20] Isolate directMatch modality to separate function --- dist/main.js | 15 +++++++++++++-- main.mjs | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/dist/main.js b/dist/main.js index 4259cca..91208e4 100755 --- a/dist/main.js +++ b/dist/main.js @@ -24705,8 +24705,7 @@ function getInputs() { }); return { patterns, rootPatterns, filterPatterns }; } -(async () => { - const { patterns } = getInputs(); +async function directMatch(patterns) { const matches = await globby(patterns, { expandDirectories: false, gitignore: true, @@ -24715,6 +24714,18 @@ function getInputs() { }); core.debug(JSON.stringify({ patterns, matches }, null, 2)); core.setOutput("matches", matches); +} +(async () => { + const { patterns, rootPatterns } = getInputs(); + switch (true) { + case !isEmpty(patterns): + directMatch(patterns); + break; + case !isEmpty(rootPatterns): + throw new Error("Not implemented"); + default: + throw new Error("Unreachable"); + } })(); /*! Bundled license information: diff --git a/main.mjs b/main.mjs index fb97eaa..a11c387 100755 --- a/main.mjs +++ b/main.mjs @@ -21,8 +21,7 @@ function getInputs() { return { patterns, rootPatterns, filterPatterns }; } -(async () => { - const { patterns } = getInputs(); +async function directMatch(patterns) { const matches = await globby(patterns, { expandDirectories: false, gitignore: true, @@ -31,4 +30,17 @@ function getInputs() { }); core.debug(JSON.stringify({ patterns, matches }, null, 2)); core.setOutput('matches', matches); +} + +(async () => { + const { patterns, rootPatterns } = getInputs(); + switch (true) { + case !isEmpty(patterns): + directMatch(patterns); + break; + case !isEmpty(rootPatterns): + throw new Error('Not implemented'); + default: + throw new Error('Unreachable'); + } })(); From e620196cd9a69ceb4133b216e5781a88d7cfdb19 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 13:46:45 -0500 Subject: [PATCH 05/20] Isolate glob against filesystem to function --- dist/main.js | 7 +++++-- main.mjs | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dist/main.js b/dist/main.js index 91208e4..e2b44f9 100755 --- a/dist/main.js +++ b/dist/main.js @@ -24705,13 +24705,16 @@ function getInputs() { }); return { patterns, rootPatterns, filterPatterns }; } -async function directMatch(patterns) { - const matches = await globby(patterns, { +async function fsGlob(patterns) { + return globby(patterns, { expandDirectories: false, gitignore: true, markDirectories: true, onlyFiles: false }); +} +async function directMatch(patterns) { + const matches = await fsGlob(patterns); core.debug(JSON.stringify({ patterns, matches }, null, 2)); core.setOutput("matches", matches); } diff --git a/main.mjs b/main.mjs index a11c387..3948c26 100755 --- a/main.mjs +++ b/main.mjs @@ -21,13 +21,17 @@ function getInputs() { return { patterns, rootPatterns, filterPatterns }; } -async function directMatch(patterns) { - const matches = await globby(patterns, { +async function fsGlob(patterns) { + return globby(patterns, { expandDirectories: false, gitignore: true, markDirectories: true, onlyFiles: false, }); +} + +async function directMatch(patterns) { + const matches = await fsGlob(patterns); core.debug(JSON.stringify({ patterns, matches }, null, 2)); core.setOutput('matches', matches); } From 2d227a6474df2b663c7cb25383f15dd35425f84a Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 13:52:31 -0500 Subject: [PATCH 06/20] Fix root-patterns input format --- dist/main.js | 2 +- main.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/main.js b/dist/main.js index e2b44f9..bf2403b 100755 --- a/dist/main.js +++ b/dist/main.js @@ -24693,7 +24693,7 @@ function isEmpty(xs) { } function getInputs() { const patterns = core.getMultilineInput("patterns"); - const rootPatterns = core.getMultilineInput("rootPatterns"); + const rootPatterns = core.getMultilineInput("root-patterns"); if (isEmpty(patterns) && isEmpty(rootPatterns)) { throw new Error('Either "patterns" or "root-patterns" must be provided'); } diff --git a/main.mjs b/main.mjs index 3948c26..7a5fc8b 100755 --- a/main.mjs +++ b/main.mjs @@ -8,7 +8,7 @@ function isEmpty(xs) { function getInputs() { const patterns = core.getMultilineInput('patterns'); - const rootPatterns = core.getMultilineInput('rootPatterns'); + const rootPatterns = core.getMultilineInput('root-patterns'); if (isEmpty(patterns) && isEmpty(rootPatterns)) { throw new Error('Either "patterns" or "root-patterns" must be provided'); } From 1fd4b99673050c7c3f362747ec61a9f8f3b1ef07 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 14:00:44 -0500 Subject: [PATCH 07/20] Add micromatch as a dependency --- package-lock.json | 11 ++++++----- package.json | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d6e67a..b4d4176 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,22 @@ { "name": "actions-for-each", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { + "version": "0.1.0", "dependencies": { "@actions/core": "^1.10.1", - "globby": "^14.0.0" + "globby": "^14.0.0", + "micromatch": "^4.0.5" }, "devDependencies": { "esbuild": "^0.19.8", "eslint": "^8.54.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.29.0" - }, - "version": "0.1.0" + } }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", @@ -2937,6 +2939,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "version": "0.1.0" + } } diff --git a/package.json b/package.json index 81cd27f..b570bde 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ }, "dependencies": { "@actions/core": "^1.10.1", - "globby": "^14.0.0" + "globby": "^14.0.0", + "micromatch": "^4.0.5" }, "devDependencies": { "esbuild": "^0.19.8", From 4c22baf094853ffbebbd12caf1b1c2ec8edbf5cb Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:16:10 -0500 Subject: [PATCH 08/20] Define hoist function --- dist/main.js | 55 ++++++++++++++++++++++++++-------------------------- main.mjs | 15 ++++++++++++++ 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/dist/main.js b/dist/main.js index bf2403b..f6d0915 100755 --- a/dist/main.js +++ b/dist/main.js @@ -21420,7 +21420,7 @@ var require_micromatch = __commonJS({ var picomatch = require_picomatch2(); var utils = require_utils4(); var isEmptyString = (val) => val === "" || val === "./"; - var micromatch = (list, patterns, options) => { + var micromatch2 = (list, patterns, options) => { patterns = [].concat(patterns); list = [].concat(list); let omit = /* @__PURE__ */ new Set(); @@ -21463,11 +21463,11 @@ var require_micromatch = __commonJS({ } return matches; }; - micromatch.match = micromatch; - micromatch.matcher = (pattern, options) => picomatch(pattern, options); - micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); - micromatch.any = micromatch.isMatch; - micromatch.not = (list, patterns, options = {}) => { + micromatch2.match = micromatch2; + micromatch2.matcher = (pattern, options) => picomatch(pattern, options); + micromatch2.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + micromatch2.any = micromatch2.isMatch; + micromatch2.not = (list, patterns, options = {}) => { patterns = [].concat(patterns).map(String); let result = /* @__PURE__ */ new Set(); let items = []; @@ -21476,7 +21476,7 @@ var require_micromatch = __commonJS({ options.onResult(state); items.push(state.output); }; - let matches = new Set(micromatch(list, patterns, { ...options, onResult })); + let matches = new Set(micromatch2(list, patterns, { ...options, onResult })); for (let item of items) { if (!matches.has(item)) { result.add(item); @@ -21484,12 +21484,12 @@ var require_micromatch = __commonJS({ } return [...result]; }; - micromatch.contains = (str, pattern, options) => { + micromatch2.contains = (str, pattern, options) => { if (typeof str !== "string") { throw new TypeError(`Expected a string: "${util.inspect(str)}"`); } if (Array.isArray(pattern)) { - return pattern.some((p) => micromatch.contains(str, p, options)); + return pattern.some((p) => micromatch2.contains(str, p, options)); } if (typeof pattern === "string") { if (isEmptyString(str) || isEmptyString(pattern)) { @@ -21499,19 +21499,19 @@ var require_micromatch = __commonJS({ return true; } } - return micromatch.isMatch(str, pattern, { ...options, contains: true }); + return micromatch2.isMatch(str, pattern, { ...options, contains: true }); }; - micromatch.matchKeys = (obj, patterns, options) => { + micromatch2.matchKeys = (obj, patterns, options) => { if (!utils.isObject(obj)) { throw new TypeError("Expected the first argument to be an object"); } - let keys = micromatch(Object.keys(obj), patterns, options); + let keys = micromatch2(Object.keys(obj), patterns, options); let res = {}; for (let key of keys) res[key] = obj[key]; return res; }; - micromatch.some = (list, patterns, options) => { + micromatch2.some = (list, patterns, options) => { let items = [].concat(list); for (let pattern of [].concat(patterns)) { let isMatch = picomatch(String(pattern), options); @@ -21521,7 +21521,7 @@ var require_micromatch = __commonJS({ } return false; }; - micromatch.every = (list, patterns, options) => { + micromatch2.every = (list, patterns, options) => { let items = [].concat(list); for (let pattern of [].concat(patterns)) { let isMatch = picomatch(String(pattern), options); @@ -21531,13 +21531,13 @@ var require_micromatch = __commonJS({ } return true; }; - micromatch.all = (str, patterns, options) => { + micromatch2.all = (str, patterns, options) => { if (typeof str !== "string") { throw new TypeError(`Expected a string: "${util.inspect(str)}"`); } return [].concat(patterns).every((p) => picomatch(p, options)(str)); }; - micromatch.capture = (glob, input, options) => { + micromatch2.capture = (glob, input, options) => { let posix = utils.isWindows(options); let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); @@ -21545,9 +21545,9 @@ var require_micromatch = __commonJS({ return match.slice(1).map((v) => v === void 0 ? "" : v); } }; - micromatch.makeRe = (...args) => picomatch.makeRe(...args); - micromatch.scan = (...args) => picomatch.scan(...args); - micromatch.parse = (patterns, options) => { + micromatch2.makeRe = (...args) => picomatch.makeRe(...args); + micromatch2.scan = (...args) => picomatch.scan(...args); + micromatch2.parse = (patterns, options) => { let res = []; for (let pattern of [].concat(patterns || [])) { for (let str of braces(String(pattern), options)) { @@ -21556,7 +21556,7 @@ var require_micromatch = __commonJS({ } return res; }; - micromatch.braces = (pattern, options) => { + micromatch2.braces = (pattern, options) => { if (typeof pattern !== "string") throw new TypeError("Expected a string"); if (options && options.nobrace === true || !/\{.*\}/.test(pattern)) { @@ -21564,12 +21564,12 @@ var require_micromatch = __commonJS({ } return braces(pattern, options); }; - micromatch.braceExpand = (pattern, options) => { + micromatch2.braceExpand = (pattern, options) => { if (typeof pattern !== "string") throw new TypeError("Expected a string"); - return micromatch.braces(pattern, { ...options, expand: true }); + return micromatch2.braces(pattern, { ...options, expand: true }); }; - module2.exports = micromatch; + module2.exports = micromatch2; } }); @@ -21581,7 +21581,7 @@ var require_pattern = __commonJS({ exports.removeDuplicateSlashes = exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.isPatternRelatedToParentDirectory = exports.getPatternsOutsideCurrentDirectory = exports.getPatternsInsideCurrentDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; var path2 = require("path"); var globParent = require_glob_parent(); - var micromatch = require_micromatch(); + var micromatch2 = require_micromatch(); var GLOBSTAR = "**"; var ESCAPE_SYMBOL = "\\"; var COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; @@ -21685,13 +21685,13 @@ var require_pattern = __commonJS({ } exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion; function expandBraceExpansion(pattern) { - const patterns = micromatch.braces(pattern, { expand: true, nodupes: true, keepEscaping: true }); + const patterns = micromatch2.braces(pattern, { expand: true, nodupes: true, keepEscaping: true }); patterns.sort((a, b) => a.length - b.length); return patterns.filter((pattern2) => pattern2 !== ""); } exports.expandBraceExpansion = expandBraceExpansion; function getPatternParts(pattern, options) { - let { parts } = micromatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); + let { parts } = micromatch2.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); if (parts.length === 0) { parts = [pattern]; } @@ -21703,7 +21703,7 @@ var require_pattern = __commonJS({ } exports.getPatternParts = getPatternParts; function makeRe(pattern, options) { - return micromatch.makeRe(pattern, options); + return micromatch2.makeRe(pattern, options); } exports.makeRe = makeRe; function convertPatternsToRe(patterns, options) { @@ -24688,6 +24688,7 @@ var generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync); var { convertPathToPattern } = import_fast_glob2.default; // main.mjs +var import_micromatch = __toESM(require_micromatch(), 1); function isEmpty(xs) { return xs.length === 0; } diff --git a/main.mjs b/main.mjs index 7a5fc8b..c1f7852 100755 --- a/main.mjs +++ b/main.mjs @@ -1,6 +1,8 @@ #!/usr/bin/env node +import { dirname } from 'path'; import * as core from '@actions/core'; import { globby } from 'globby'; +import micromatch from 'micromatch'; function isEmpty(xs) { return xs.length === 0; @@ -36,6 +38,19 @@ async function directMatch(patterns) { core.setOutput('matches', matches); } +function hoist(rootPatterns, paths) { + const roots = []; + let remaining = [...paths, './']; + do { + roots.push(...micromatch(remaining, rootPatterns)); + remaining = micromatch + .not(remaining, rootPatterns) + .map((x) => `${dirname(x)}/`) + .filter((x) => x !== './'); + } while (remaining.length > 0); + return Array.from(new Set(roots)); +} + (async () => { const { patterns, rootPatterns } = getInputs(); switch (true) { From 47273129a17f486ef0daffb915143f8040572b56 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:18:23 -0500 Subject: [PATCH 09/20] Define hoistMatch function --- main.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main.mjs b/main.mjs index c1f7852..446725d 100755 --- a/main.mjs +++ b/main.mjs @@ -51,6 +51,18 @@ function hoist(rootPatterns, paths) { return Array.from(new Set(roots)); } +async function hoistMatch(rootPatterns, filterPatterns) { + const fromFilters = await fsGlob(filterPatterns); + const matches = hoist(rootPatterns, fromFilters); + core.debug(JSON.stringify({ + rootPatterns, + filterPatterns, + fromFilters, + matches, + }, null, 2)); + core.setOutput('matches', matches); +} + (async () => { const { patterns, rootPatterns } = getInputs(); switch (true) { From 20331385acd3348dc89c648ce3bda5500494db60 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:19:28 -0500 Subject: [PATCH 10/20] Add support for (root-patterns/filter-patterns) mode --- dist/main.js | 26 ++++++++++++++++++++++++-- main.mjs | 5 +++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/dist/main.js b/dist/main.js index f6d0915..f52cad2 100755 --- a/dist/main.js +++ b/dist/main.js @@ -24332,6 +24332,7 @@ var require_ignore = __commonJS({ }); // main.mjs +var import_path = require("path"); var core = __toESM(require_core(), 1); // node_modules/globby/index.js @@ -24719,14 +24720,35 @@ async function directMatch(patterns) { core.debug(JSON.stringify({ patterns, matches }, null, 2)); core.setOutput("matches", matches); } +function hoist(rootPatterns, paths) { + const roots = []; + let remaining = [...paths, "./"]; + do { + roots.push(...(0, import_micromatch.default)(remaining, rootPatterns)); + remaining = import_micromatch.default.not(remaining, rootPatterns).map((x) => `${(0, import_path.dirname)(x)}/`).filter((x) => x !== "./"); + } while (remaining.length > 0); + return Array.from(new Set(roots)); +} +async function hoistMatch(rootPatterns, filterPatterns) { + const fromFilters = await fsGlob(filterPatterns); + const matches = hoist(rootPatterns, fromFilters); + core.debug(JSON.stringify({ + rootPatterns, + filterPatterns, + fromFilters, + matches + }, null, 2)); + core.setOutput("matches", matches); +} (async () => { - const { patterns, rootPatterns } = getInputs(); + const { filterPatterns, patterns, rootPatterns } = getInputs(); switch (true) { case !isEmpty(patterns): directMatch(patterns); break; case !isEmpty(rootPatterns): - throw new Error("Not implemented"); + hoistMatch(rootPatterns, filterPatterns); + break; default: throw new Error("Unreachable"); } diff --git a/main.mjs b/main.mjs index 446725d..d7bf9cc 100755 --- a/main.mjs +++ b/main.mjs @@ -64,13 +64,14 @@ async function hoistMatch(rootPatterns, filterPatterns) { } (async () => { - const { patterns, rootPatterns } = getInputs(); + const { filterPatterns, patterns, rootPatterns } = getInputs(); switch (true) { case !isEmpty(patterns): directMatch(patterns); break; case !isEmpty(rootPatterns): - throw new Error('Not implemented'); + hoistMatch(rootPatterns, filterPatterns); + break; default: throw new Error('Unreachable'); } From 5cf3dd39b15e9ee28e32dabab3268daf688c84cc Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:21:40 -0500 Subject: [PATCH 11/20] Change id of parallel instance of for-each to "for-each" --- .github/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2caa2de..16b7df7 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,7 +9,7 @@ jobs: main: runs-on: ubuntu-latest outputs: - matches: ${{ steps.for-each-4.outputs.matches }} + matches: ${{ steps.for-each.outputs.matches }} steps: - uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: run: exit 1 - name: Run colpal/actions-for-each - id: for-each-4 + id: for-each uses: ./ with: patterns: 'fixtures/run-*' From e9443cf9615d8f02a7e49fb732793e7c680a5965 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:25:43 -0500 Subject: [PATCH 12/20] Add workflow test with root/filter patterns --- .github/workflows/test.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 16b7df7..d3c12f3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -41,6 +41,15 @@ jobs: - if: steps.for-each-3.outputs.matches != '["fixtures/run-a/file.txt","fixtures/run-b/file.txt"]' run: exit 1 + - name: Run colpal/actions-for-each + id: for-each-4 + uses: ./ + with: + root-patterns: '*/' + filter-patterns: '**/main.*' + - if: steps.for-each-4.outputs.matches != '["dist/"]' + run: exit 1 + - name: Run colpal/actions-for-each id: for-each uses: ./ From f60397cda2555f408d7f019ea179d03a6f336fee Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:28:45 -0500 Subject: [PATCH 13/20] Add workflow test showcasing multiple root patterns --- .github/workflows/test.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d3c12f3..5da388b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -50,6 +50,17 @@ jobs: - if: steps.for-each-4.outputs.matches != '["dist/"]' run: exit 1 + - name: Run colpal/actions-for-each + id: for-each-5 + uses: ./ + with: + root-patterns: | + ./ + **/ + filter-patterns: '**/main.*' + - if: steps.for-each-5.outputs.matches != '[]' + run: exit 1 + - name: Run colpal/actions-for-each id: for-each uses: ./ From 1c16766632f37161f4b8daeca3b85aa3b3a68a61 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:29:45 -0500 Subject: [PATCH 14/20] Correct expected output for test 5 --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5da388b..3ac71de 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -58,7 +58,7 @@ jobs: ./ **/ filter-patterns: '**/main.*' - - if: steps.for-each-5.outputs.matches != '[]' + - if: steps.for-each-5.outputs.matches != '["./","dist/"]' run: exit 1 - name: Run colpal/actions-for-each From f2e3ce44ccbc747ffa73586415a57c3a6a4b0776 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:32:19 -0500 Subject: [PATCH 15/20] Add 6th for-each test to workflow --- .github/workflows/test.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3ac71de..7d83594 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -61,6 +61,16 @@ jobs: - if: steps.for-each-5.outputs.matches != '["./","dist/"]' run: exit 1 + - name: Run colpal/actions-for-each + id: for-each-6 + uses: ./ + with: + root-patterns: | + **/*-b/ + filter-patterns: '**/file.txt' + - if: steps.for-each-6.outputs.matches != '["fixtures/function-b/","fixtures/run-b/"]' + run: exit 1 + - name: Run colpal/actions-for-each id: for-each uses: ./ From 0b3b36087f3c728682a09f464bbe65964ab05fa2 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 15:42:48 -0500 Subject: [PATCH 16/20] Update parallel header in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c2f5df..8904fcf 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ steps: # ["function-a/file.txt","function-b/file.txt"] ``` -### Parallel +### Static Parallel ```yaml jobs: From 1e623d3b14ac03c0c46da0fc761550839e5597ff Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 16:20:48 -0500 Subject: [PATCH 17/20] Write reference on root/filter-patterns --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8904fcf..a8759e3 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,35 @@ steps: - id: for-each uses: colpal/actions-for-each@v0.1 with: - # REQUIRED + # REQUIRED (if `root-patterns` is not specified) # The pattern(s) to be used to find folders/files. More than one pattern # may be supplied by putting each on its own line. - patterns: string + patterns: single-line string | multi-line string + + # OPTIONAL (only valid if `root-patterns` is specified) + # DEFAULT = ** + # The pattern(s) to be used to find files/folders to provide to + # `root-patterns` (see the description of `root-patterns` for more + # details) + filter-patterns: single-line string | multi-line string + + # REQUIRED (if `patterns` is not specified) + # The pattern(s) to be used to "hoist" files/folders matched by + # `filter-patterns`. The process is as follows: + # 1. `filter-patterns` is applied to the filesystem to create a list + # of paths (similar to what `patterns` does when specified alone) + # 2. `root-patterns` is then applied to the paths from the previous + # step. Any paths that match will be added to the `matches` output. + # 3. `dirname` will be applied to all paths from step 2 that DID NOT + # match `root-patterns`, effectively removing the last segment of + # the path. For example: + # `folder-a/subfolder-a/file-a` becomes `folder-a/subfolder-a/` + # `folder-a/subfolder-a/` becomes `folder-a/` + # `folder-a/` becomes `./` + # `./` becomes `./` + # 4. Repeat steps 2 - 4 until the only unmatched paths are "./" + # 5. `matches` is set as an output of the action + root-patterns: single-line string | multi-line string outputs: # An JSON-formatted array of paths that matched the pattern(s) matches: ${{ steps.for-each.outputs.matches }} From c793e63f478b7b93f54840af5837acb224556f5c Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 16:32:50 -0500 Subject: [PATCH 18/20] Add recipe to find all folders that contain certain files --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index a8759e3..58f9525 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,18 @@ outputs: # An JSON-formatted array of paths that matched the pattern(s) matches: ${{ steps.for-each.outputs.matches }} ``` + +## Recipes + +### Find all folders that contain certain files + +```yaml +- uses: colpal/actions-for-each@v0.1 + with: + root-patterns: | + ./ + **/ + filter-patterns: | + **/main.sh + **/start.sh +``` From c33590c18611c1b3751d46c40b8fa35b66c286d9 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 16:54:10 -0500 Subject: [PATCH 19/20] Fix bug where ./ would always match root-patterns --- dist/main.js | 7 ++++--- main.mjs | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dist/main.js b/dist/main.js index f52cad2..7f52230 100755 --- a/dist/main.js +++ b/dist/main.js @@ -24722,11 +24722,12 @@ async function directMatch(patterns) { } function hoist(rootPatterns, paths) { const roots = []; - let remaining = [...paths, "./"]; + let remaining = [...paths]; do { roots.push(...(0, import_micromatch.default)(remaining, rootPatterns)); - remaining = import_micromatch.default.not(remaining, rootPatterns).map((x) => `${(0, import_path.dirname)(x)}/`).filter((x) => x !== "./"); - } while (remaining.length > 0); + remaining = import_micromatch.default.not(remaining, rootPatterns).map((x) => `${(0, import_path.dirname)(x)}/`); + } while (remaining.filter((x) => x !== "./").length > 0); + roots.push(...(0, import_micromatch.default)(remaining, rootPatterns)); return Array.from(new Set(roots)); } async function hoistMatch(rootPatterns, filterPatterns) { diff --git a/main.mjs b/main.mjs index d7bf9cc..231cd15 100755 --- a/main.mjs +++ b/main.mjs @@ -40,14 +40,14 @@ async function directMatch(patterns) { function hoist(rootPatterns, paths) { const roots = []; - let remaining = [...paths, './']; + let remaining = [...paths]; do { roots.push(...micromatch(remaining, rootPatterns)); remaining = micromatch .not(remaining, rootPatterns) - .map((x) => `${dirname(x)}/`) - .filter((x) => x !== './'); - } while (remaining.length > 0); + .map((x) => `${dirname(x)}/`); + } while (remaining.filter((x) => x !== './').length > 0); + roots.push(...micromatch(remaining, rootPatterns)); return Array.from(new Set(roots)); } From e2d40bcbd68ad0e29dce74151425a2b1b5dade84 Mon Sep 17 00:00:00 2001 From: Nicholas Farley Date: Thu, 30 Nov 2023 16:56:34 -0500 Subject: [PATCH 20/20] Add 7th workflow test --- .github/workflows/test.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7d83594..4cd8544 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -71,6 +71,17 @@ jobs: - if: steps.for-each-6.outputs.matches != '["fixtures/function-b/","fixtures/run-b/"]' run: exit 1 + - name: Run colpal/actions-for-each + id: for-each-7 + uses: ./ + with: + root-patterns: | + ./ + filter-patterns: | + **/flie.txt + - if: steps.for-each-7.outputs.matches != '[]' + run: exit 1 + - name: Run colpal/actions-for-each id: for-each uses: ./