diff --git a/action.yml b/action.yml index e7d24f5..6b984fe 100644 --- a/action.yml +++ b/action.yml @@ -1,13 +1,13 @@ -name: 'Paths Changes Filter' -description: 'Execute your workflow steps only if relevant files are modified.' -author: 'Michal Dorner ' +name: "Paths Changes Filter" +description: "Execute your workflow steps only if relevant files are modified." +author: "Michal Dorner " inputs: token: - description: 'GitHub Access Token' + description: "GitHub Access Token" required: false default: ${{ github.token }} working-directory: - description: 'Relative path under $GITHUB_WORKSPACE where the repository was checked out.' + description: "Relative path under $GITHUB_WORKSPACE where the repository was checked out." required: false ref: description: | @@ -20,8 +20,11 @@ inputs: If it references same branch it was pushed to, changes are detected against the most recent commit before the push. This option is ignored if action is triggered by pull_request event. required: false + files: + description: "Manual list of files to filter" + required: false filters: - description: 'Path to the configuration file or YAML string with filters definition' + description: "Path to the configuration file or YAML string with filters definition" required: true list-files: description: | @@ -43,13 +46,13 @@ inputs: until the merge-base is found or there are no more commits in the history. This option takes effect only when changes are detected using git against different base branch. required: false - default: '100' + default: "100" outputs: changes: description: JSON array with names of all filters matching any of changed files runs: - using: 'node20' - main: 'dist/index.js' + using: "node20" + main: "dist/index.js" branding: color: blue icon: filter diff --git a/dist/index.js b/dist/index.js index cc7d7d4..f7ccea5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -553,9 +553,10 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const fs = __importStar(__nccwpck_require__(7147)); const core = __importStar(__nccwpck_require__(2186)); +const fs = __importStar(__nccwpck_require__(7147)); const github = __importStar(__nccwpck_require__(5438)); +const jsyaml = __importStar(__nccwpck_require__(1917)); const filter_1 = __nccwpck_require__(3707); const file_1 = __nccwpck_require__(4014); const git = __importStar(__nccwpck_require__(3374)); @@ -570,6 +571,7 @@ async function run() { const token = core.getInput('token', { required: false }); const ref = core.getInput('ref', { required: false }); const base = core.getInput('base', { required: false }); + const filesInput = core.getInput('files', { required: false }); const filtersInput = core.getInput('filters', { required: true }); const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput; const listFiles = core.getInput('list-files', { required: false }).toLowerCase() || 'none'; @@ -586,7 +588,8 @@ async function run() { } const filterConfig = { predicateQuantifier }; const filter = new filter_1.Filter(filtersYaml, filterConfig); - const files = await getChangedFiles(token, base, ref, initialFetchDepth); + core.info(`Detected ${filesInput} files`); + const files = await getChangedFiles(filesInput, token, base, ref, initialFetchDepth); core.info(`Detected ${files.length} changed files`); const results = filter.match(files); exportResults(results, listFiles); @@ -607,8 +610,13 @@ function getConfigFileContent(configPath) { } return fs.readFileSync(configPath, { encoding: 'utf8' }); } -async function getChangedFiles(token, base, ref, initialFetchDepth) { +async function getChangedFiles(files, token, base, ref, initialFetchDepth) { var _a, _b; + if (files) { + core.info('Using list of files provided as input'); + const doc = jsyaml.load(files); + return doc.map(filename => ({ filename, status: file_1.ChangeStatus.Modified })); + } // if base is 'HEAD' only local uncommitted changes will be detected // This is the simplest case as we don't need to fetch more commits or evaluate current/before refs if (base === git.HEAD) { diff --git a/src/main.ts b/src/main.ts index 8320287..e43301b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,9 @@ -import * as fs from 'fs' import * as core from '@actions/core' +import * as fs from 'fs' import * as github from '@actions/github' -import {GetResponseDataTypeFromEndpointMethod} from '@octokit/types' -import {PushEvent, PullRequestEvent} from '@octokit/webhooks-types' +import * as jsyaml from 'js-yaml' +import { GetResponseDataTypeFromEndpointMethod } from '@octokit/types' +import { PushEvent, PullRequestEvent } from '@octokit/webhooks-types' import { isPredicateQuantifier, @@ -12,28 +13,29 @@ import { PredicateQuantifier, SUPPORTED_PREDICATE_QUANTIFIERS } from './filter' -import {File, ChangeStatus} from './file' +import { File, ChangeStatus } from './file' import * as git from './git' -import {backslashEscape, shellEscape} from './list-format/shell-escape' -import {csvEscape} from './list-format/csv-escape' +import { backslashEscape, shellEscape } from './list-format/shell-escape' +import { csvEscape } from './list-format/csv-escape' type ExportFormat = 'none' | 'csv' | 'json' | 'shell' | 'escape' async function run(): Promise { try { - const workingDirectory = core.getInput('working-directory', {required: false}) + const workingDirectory = core.getInput('working-directory', { required: false }) if (workingDirectory) { process.chdir(workingDirectory) } - const token = core.getInput('token', {required: false}) - const ref = core.getInput('ref', {required: false}) - const base = core.getInput('base', {required: false}) - const filtersInput = core.getInput('filters', {required: true}) + const token = core.getInput('token', { required: false }) + const ref = core.getInput('ref', { required: false }) + const base = core.getInput('base', { required: false }) + const filesInput = core.getInput('files', { required: false }) + const filtersInput = core.getInput('filters', { required: true }) const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput - const listFiles = core.getInput('list-files', {required: false}).toLowerCase() || 'none' - const initialFetchDepth = parseInt(core.getInput('initial-fetch-depth', {required: false})) || 10 - const predicateQuantifier = core.getInput('predicate-quantifier', {required: false}) || PredicateQuantifier.SOME + const listFiles = core.getInput('list-files', { required: false }).toLowerCase() || 'none' + const initialFetchDepth = parseInt(core.getInput('initial-fetch-depth', { required: false })) || 10 + const predicateQuantifier = core.getInput('predicate-quantifier', { required: false }) || PredicateQuantifier.SOME if (!isExportFormat(listFiles)) { core.setFailed(`Input parameter 'list-files' is set to invalid value '${listFiles}'`) @@ -46,10 +48,10 @@ async function run(): Promise { `'${predicateQuantifier}'. Valid values: ${SUPPORTED_PREDICATE_QUANTIFIERS.join(', ')}` throw new Error(predicateQuantifierInvalidErrorMsg) } - const filterConfig: FilterConfig = {predicateQuantifier} + const filterConfig: FilterConfig = { predicateQuantifier } const filter = new Filter(filtersYaml, filterConfig) - const files = await getChangedFiles(token, base, ref, initialFetchDepth) + const files = await getChangedFiles(filesInput, token, base, ref, initialFetchDepth) core.info(`Detected ${files.length} changed files`) const results = filter.match(files) exportResults(results, listFiles) @@ -71,10 +73,22 @@ function getConfigFileContent(configPath: string): string { throw new Error(`'${configPath}' is not a file.`) } - return fs.readFileSync(configPath, {encoding: 'utf8'}) + return fs.readFileSync(configPath, { encoding: 'utf8' }) } -async function getChangedFiles(token: string, base: string, ref: string, initialFetchDepth: number): Promise { +async function getChangedFiles( + files: string, + token: string, + base: string, + ref: string, + initialFetchDepth: number +): Promise { + if (files) { + core.info('Using list of files provided as input') + const doc = jsyaml.load(files) as string[] + return doc.map(filename => ({ filename, status: ChangeStatus.Modified })) + } + // if base is 'HEAD' only local uncommitted changes will be detected // This is the simplest case as we don't need to fetch more commits or evaluate current/before refs if (base === git.HEAD) {