Skip to content

Commit

Permalink
Merge pull request #2 from colpal/manual-source
Browse files Browse the repository at this point in the history
Allow providing an explicit "source" to glob against
  • Loading branch information
nafarlee authored Dec 7, 2023
2 parents ead6bc7 + cc2fb19 commit 85cf7e0
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 44 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,39 @@ jobs:
- if: steps.for-each-7.outputs.matches != '[]'
run: exit 1

- name: Run colpal/actions-for-each
id: for-each-8
uses: ./
with:
patterns: |
banana/*
source: '["banana/a.txt","banana/b.txt","apple/a.txt"]'
- if: steps.for-each-8.outputs.matches != '["banana/a.txt","banana/b.txt"]'
run: exit 1

- name: Run colpal/actions-for-each
id: for-each-9
uses: ./
with:
patterns: |
**/a.txt
source: '["banana/a.txt","banana/b.txt","apple/a.txt"]'
- if: steps.for-each-9.outputs.matches != '["banana/a.txt","apple/a.txt"]'
run: exit 1

- name: Run colpal/actions-for-each
id: for-each-10
uses: ./
with:
root-patterns: |
banana/
apple/
filter-patterns: |
**/b.txt
source: '["banana/a.txt","banana/b.txt","apple/a.txt"]'
- if: steps.for-each-10.outputs.matches != '["banana/"]'
run: exit 1

- name: Run colpal/actions-for-each
id: for-each
uses: ./
Expand Down
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ steps:
# may be supplied by putting each on its own line.
patterns: single-line string | multi-line string

# OPTIONAL
# DEFAULT = The filesystem
# The source that will be globbed/searched by patterns/filter-patterns.
# If not supplied, the filesystem will be globbed/searched. If supplied,
# must be a list of filepaths
source: JSON-formatted array of strings

# OPTIONAL (only valid if `root-patterns` is specified)
# DEFAULT = **
# The pattern(s) to be used to find files/folders to provide to
Expand Down Expand Up @@ -123,3 +130,94 @@ outputs:
**/main.sh
**/start.sh
```
### Build Docker contexts
```
.
└── containers
├── container-a
│   ├── Dockerfile
│   ├── main.py
│   └── requirements.txt
└── container-b
├── Dockerfile
├── main.js
└── package.json
```

```yaml
jobs:
divide:
steps:
- uses: actions/checkout@v4
- id: for-each
uses: colpal/actions-for-each@v0.1
with:
root-patterns: |
containers/*/
filter-patterns: |
containers/*/**
outputs:
matches: ${{ steps.for-each.outputs.matches }}

conquer:
needs: divide
strategy:
matrix:
path: ${{ fromJSON(needs.divide.outputs.matches) }}
defaults:
run:
working-directory: ./${{ matrix.path }}
steps:
- uses: actions/checkout@v4
- run: docker build
```
### Build Docker contexts if they have changed
```
.
└── containers
├── container-a
│   ├── Dockerfile
│   ├── main.py
│   └── requirements.txt
└── container-b
├── Dockerfile
├── main.js
└── package.json
```

```yaml
jobs:
divide:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: changed
uses: colpal/actions-changed-files@v3
- id: for-each
uses: colpal/actions-for-each@v0.1
with:
root-patterns: |
containers/*/
filter-patterns: |
containers/*/**
source: ${{ toJSON(fromJSON(steps.changed.outputs.json).all) }}
outputs:
matches: ${{ steps.for-each.outputs.matches }}

conquer:
needs: divide
strategy:
matrix:
path: ${{ fromJSON(needs.divide.outputs.matches) }}
defaults:
run:
working-directory: ./${{ matrix.path }}
steps:
- uses: actions/checkout@v4
- run: docker build
```
5 changes: 5 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ inputs:
description: >
The pattern(s) that will be used to filter (but not match) files/folders
default: '**'
source:
description: >
The source to which `patterns` or `filter-patterns` will be applied. If
not provided, the filesystem will be used. If provided, it must be a
JSON-formatted array of file/folder paths
outputs:
matches:
description: The files/folders that matched the pattern
Expand Down
96 changes: 61 additions & 35 deletions dist/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -18351,7 +18351,7 @@ var require_core = __commonJS({
process.env["PATH"] = `${inputPath}${path2.delimiter}${process.env["PATH"]}`;
}
exports.addPath = addPath;
function getInput(name, options) {
function getInput2(name, options) {
const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || "";
if (options && options.required && !val) {
throw new Error(`Input required and not supplied: ${name}`);
Expand All @@ -18361,9 +18361,9 @@ var require_core = __commonJS({
}
return val.trim();
}
exports.getInput = getInput;
exports.getInput = getInput2;
function getMultilineInput2(name, options) {
const inputs = getInput(name, options).split("\n").filter((x) => x !== "");
const inputs = getInput2(name, options).split("\n").filter((x) => x !== "");
if (options && options.trimWhitespace === false) {
return inputs;
}
Expand All @@ -18373,7 +18373,7 @@ var require_core = __commonJS({
function getBooleanInput(name, options) {
const trueValue = ["true", "True", "TRUE"];
const falseValue = ["false", "False", "FALSE"];
const val = getInput(name, options);
const val = getInput2(name, options);
if (trueValue.includes(val))
return true;
if (falseValue.includes(val))
Expand Down Expand Up @@ -20391,18 +20391,18 @@ var require_scan = __commonJS({
}
let base = str;
let prefix = "";
let glob = "";
let glob2 = "";
if (start > 0) {
prefix = str.slice(0, start);
str = str.slice(start);
lastIndex -= start;
}
if (base && isGlob === true && lastIndex > 0) {
base = str.slice(0, lastIndex);
glob = str.slice(lastIndex);
glob2 = str.slice(lastIndex);
} else if (isGlob === true) {
base = "";
glob = str;
glob2 = str;
} else {
base = str;
}
Expand All @@ -20412,8 +20412,8 @@ var require_scan = __commonJS({
}
}
if (opts.unescape === true) {
if (glob)
glob = utils.removeBackslashes(glob);
if (glob2)
glob2 = utils.removeBackslashes(glob2);
if (base && backslashes === true) {
base = utils.removeBackslashes(base);
}
Expand All @@ -20423,7 +20423,7 @@ var require_scan = __commonJS({
input,
start,
base,
glob,
glob: glob2,
isBrace,
isBracket,
isGlob,
Expand Down Expand Up @@ -21269,9 +21269,9 @@ var require_picomatch = __commonJS({
var utils = require_utils4();
var constants = require_constants6();
var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
var picomatch = (glob, options, returnState = false) => {
if (Array.isArray(glob)) {
const fns = glob.map((input) => picomatch(input, options, returnState));
var picomatch = (glob2, options, returnState = false) => {
if (Array.isArray(glob2)) {
const fns = glob2.map((input) => picomatch(input, options, returnState));
const arrayMatcher = (str) => {
for (const isMatch of fns) {
const state2 = isMatch(str);
Expand All @@ -21282,13 +21282,13 @@ var require_picomatch = __commonJS({
};
return arrayMatcher;
}
const isState = isObject(glob) && glob.tokens && glob.input;
if (glob === "" || typeof glob !== "string" && !isState) {
const isState = isObject(glob2) && glob2.tokens && glob2.input;
if (glob2 === "" || typeof glob2 !== "string" && !isState) {
throw new TypeError("Expected pattern to be a non-empty string");
}
const opts = options || {};
const posix = utils.isWindows(options);
const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true);
const regex = isState ? picomatch.compileRe(glob2, options) : picomatch.makeRe(glob2, options, false, true);
const state = regex.state;
delete regex.state;
let isIgnored = () => false;
Expand All @@ -21297,8 +21297,8 @@ var require_picomatch = __commonJS({
isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
}
const matcher = (input, returnObject = false) => {
const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix });
const result = { glob, state, regex, posix, input, output, match, isMatch };
const { isMatch, match, output } = picomatch.test(input, regex, options, { glob: glob2, posix });
const result = { glob: glob2, state, regex, posix, input, output, match, isMatch };
if (typeof opts.onResult === "function") {
opts.onResult(result);
}
Expand All @@ -21323,7 +21323,7 @@ var require_picomatch = __commonJS({
}
return matcher;
};
picomatch.test = (input, regex, options, { glob, posix } = {}) => {
picomatch.test = (input, regex, options, { glob: glob2, posix } = {}) => {
if (typeof input !== "string") {
throw new TypeError("Expected input to be a string");
}
Expand All @@ -21332,11 +21332,11 @@ var require_picomatch = __commonJS({
}
const opts = options || {};
const format = opts.format || (posix ? utils.toPosixSlashes : null);
let match = input === glob;
let match = input === glob2;
let output = match && format ? format(input) : input;
if (match === false) {
output = format ? format(input) : input;
match = output === glob;
match = output === glob2;
}
if (match === false || opts.capture === true) {
if (opts.matchBase === true || opts.basename === true) {
Expand All @@ -21347,8 +21347,8 @@ var require_picomatch = __commonJS({
}
return { isMatch: Boolean(match), match, output };
};
picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
picomatch.matchBase = (input, glob2, options, posix = utils.isWindows(options)) => {
const regex = glob2 instanceof RegExp ? glob2 : picomatch.makeRe(glob2, options);
return regex.test(path2.basename(input));
};
picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
Expand Down Expand Up @@ -21537,9 +21537,9 @@ var require_micromatch = __commonJS({
}
return [].concat(patterns).every((p) => picomatch(p, options)(str));
};
micromatch2.capture = (glob, input, options) => {
micromatch2.capture = (glob2, input, options) => {
let posix = utils.isWindows(options);
let regex = picomatch.makeRe(String(glob), { ...options, capture: true });
let regex = picomatch.makeRe(String(glob2), { ...options, capture: true });
let match = regex.exec(posix ? utils.toPosixSlashes(input) : input);
if (match) {
return match.slice(1).map((v) => v === void 0 ? "" : v);
Expand Down Expand Up @@ -24705,7 +24705,21 @@ function getInputs() {
const filterPatterns = core.getMultilineInput("filter-patterns", {
required: true
});
return { patterns, rootPatterns, filterPatterns };
let source = core.getInput("source") || null;
try {
source = JSON.parse(source);
} catch (err) {
throw new Error(
'If provided, "source" must be a JSON-formatted array of filepaths',
{ cause: err }
);
}
return {
patterns,
rootPatterns,
filterPatterns,
source
};
}
async function fsGlob(patterns) {
return globby(patterns, {
Expand All @@ -24715,9 +24729,15 @@ async function fsGlob(patterns) {
onlyFiles: false
});
}
async function directMatch(patterns) {
const matches = await fsGlob(patterns);
core.debug(JSON.stringify({ patterns, matches }, null, 2));
function memGlob(patterns, source) {
return (0, import_micromatch.default)(source, patterns);
}
function glob(patterns, source = null) {
return source ? memGlob(patterns, source) : fsGlob(patterns);
}
async function directMatch(patterns, source) {
const matches = await glob(patterns, source);
core.debug(JSON.stringify({ patterns, matches, source }, null, 2));
core.setOutput("matches", matches);
}
function hoist(rootPatterns, paths) {
Expand All @@ -24730,25 +24750,31 @@ function hoist(rootPatterns, paths) {
roots.push(...(0, import_micromatch.default)(remaining, rootPatterns));
return Array.from(new Set(roots));
}
async function hoistMatch(rootPatterns, filterPatterns) {
const fromFilters = await fsGlob(filterPatterns);
async function hoistMatch(rootPatterns, filterPatterns, source) {
const fromFilters = await glob(filterPatterns, source);
const matches = hoist(rootPatterns, fromFilters);
core.debug(JSON.stringify({
rootPatterns,
filterPatterns,
fromFilters,
matches
matches,
source
}, null, 2));
core.setOutput("matches", matches);
}
(async () => {
const { filterPatterns, patterns, rootPatterns } = getInputs();
const {
filterPatterns,
patterns,
rootPatterns,
source
} = getInputs();
switch (true) {
case !isEmpty(patterns):
directMatch(patterns);
directMatch(patterns, source);
break;
case !isEmpty(rootPatterns):
hoistMatch(rootPatterns, filterPatterns);
hoistMatch(rootPatterns, filterPatterns, source);
break;
default:
throw new Error("Unreachable");
Expand Down
Loading

0 comments on commit 85cf7e0

Please sign in to comment.