Enable custom ref and base on PRs

This commit is contained in:
Henry Painter 2022-08-11 23:10:18 +01:00
parent 8c7f485a57
commit b0bc141e31
6 changed files with 156 additions and 15 deletions

View file

@ -135,3 +135,82 @@ jobs:
|| steps.filter.outputs.modified_files != 'LICENSE'
|| steps.filter.outputs.deleted_files != 'README.md'
run: exit 1
test-baseref-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./
id: filter
with:
base: ${{ github.base_ref }}
ref: ${{ github.sha }}
filters: |
error:
- not_existing_path/**/*
any:
- "**/*"
- name: filter-test
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
run: exit 1
- name: changes-test
if: contains(fromJSON(steps.filter.outputs.changes), 'error') || !contains(fromJSON(steps.filter.outputs.changes), 'any')
run: exit 1
test-custom-nostatus:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: |
base=${{ github.base_ref }}
compare=${{ github.sha }}
git fetch origin $base:$base
echo 'customchanges<<EOF' >> $GITHUB_ENV
git diff --name-only $base..$compare >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
- uses: ./
id: filter
with:
files: ${{ env.customchanges }}
filters: |
error:
- not_existing_path/**/*
any:
- "**/*"
- name: filter-test
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
run: exit 1
- name: changes-test
if: contains(fromJSON(steps.filter.outputs.changes), 'error') || !contains(fromJSON(steps.filter.outputs.changes), 'any')
run: exit 1
test-custom-withstatus:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: |
base=${{ github.base_ref }}
compare=${{ github.sha }}
git fetch origin $base:$base
echo 'customchanges<<EOF' >> $GITHUB_ENV
git diff --name-status $base..$compare >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
- uses: ./
id: filter
with:
files: ${{ env.customchanges }}
filters: |
error:
- not_existing_path/**/*
any:
- "**/*"
- name: filter-test
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
run: exit 1
- name: changes-test
if: contains(fromJSON(steps.filter.outputs.changes), 'error') || !contains(fromJSON(steps.filter.outputs.changes), 'any')
run: exit 1

View file

@ -18,7 +18,7 @@ don't allow this because they don't work on a level of individual jobs or steps.
- Workflow triggered by **[pull_request](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request)**
or **[pull_request_target](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target)** event
- Changes are detected against the pull request base branch
- Uses GitHub REST API to fetch a list of modified files
- Uses GitHub REST API to fetch a list of modified files, if base or ref are not provided.
- **Feature branches:**
- Workflow triggered by **[push](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push)**
or any other **[event](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)**
@ -40,6 +40,8 @@ don't allow this because they don't work on a level of individual jobs or steps.
- Workflow triggered by any event when `base` input parameter is set to `HEAD`
- Changes are detected against the current HEAD
- Untracked files are ignored
- **Input Files**
- Input list of string to `customfiles` input parameter and get the filtered results. In case you want to generate list of files elsewhere.
## Example
@ -107,14 +109,12 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob
# introduced by the current branch are considered.
# All files are considered as added if there is no common ancestor with
# base branch or no previous commit.
# This option is ignored if action is triggered by pull_request event.
# Default: repository default branch (e.g. master)
base: ''
# Git reference (e.g. branch name) from which the changes will be detected.
# Useful when workflow can be triggered only on the default branch (e.g. repository_dispatch event)
# but you want to get changes on a different branch.
# This option is ignored if action is triggered by pull_request event.
# default: ${{ github.ref }}
ref:
@ -150,6 +150,11 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob
# changes using git commands.
# Default: ${{ github.token }}
token: ''
# Optionally provide a list of files you ahve generated elsewhere.
# Performs the glob matching against these files instead. Negates
# all other inputs less filters & list-files.
customfiles: ''
```
## Outputs

View file

@ -36,6 +36,12 @@ inputs:
Backslash escapes every potentially unsafe character.
required: true
default: none
files:
description: |
Custom input for files changed if you do your diff elsewhere.
Accepts a newline separated list of files, with optional leading status code, as per output of git diff --name-only or git diff --name-status
If no status supplied sets status to unmerged. Is set then only filers and list-files inputs are effective.
required: false
initial-fetch-depth:
description: |
How many commits are initially fetched from base branch.

39
dist/index.js vendored
View file

@ -178,7 +178,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isGitSha = exports.getShortName = exports.getCurrentRef = exports.listAllFilesAsAdded = exports.parseGitDiffOutput = exports.getChangesSinceMergeBase = exports.getChangesOnHead = exports.getChanges = exports.getChangesInLastCommit = exports.HEAD = exports.NULL_SHA = void 0;
exports.statusMap = exports.isGitSha = exports.getShortName = exports.getCurrentRef = exports.listAllFilesAsAdded = exports.parseGitDiffOutput = exports.getChangesSinceMergeBase = exports.getChangesOnHead = exports.getChanges = exports.getChangesInLastCommit = exports.HEAD = exports.NULL_SHA = void 0;
const exec_1 = __importDefault(__nccwpck_require__(7757));
const core = __importStar(__nccwpck_require__(2186));
const file_1 = __nccwpck_require__(4014);
@ -307,7 +307,7 @@ function parseGitDiffOutput(output) {
const files = [];
for (let i = 0; i + 1 < tokens.length; i += 2) {
files.push({
status: statusMap[tokens[i]],
status: exports.statusMap[tokens[i]],
filename: tokens[i + 1]
});
}
@ -421,7 +421,7 @@ function fixStdOutNullTermination() {
// Otherwise things like ::set-output wouldn't work.
core.info('');
}
const statusMap = {
exports.statusMap = {
A: file_1.ChangeStatus.Added,
C: file_1.ChangeStatus.Copied,
D: file_1.ChangeStatus.Deleted,
@ -536,6 +536,7 @@ async function run() {
if (workingDirectory) {
process.chdir(workingDirectory);
}
const customfiles = core.getInput('files', { required: false });
const token = core.getInput('token', { required: false });
const ref = core.getInput('ref', { required: false });
const base = core.getInput('base', { required: false });
@ -543,12 +544,14 @@ async function run() {
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 files = customfiles
? parseFilesInput(customfiles.split(/\r?\n/))
: await getChangedFiles(token, base, ref, initialFetchDepth);
if (!isExportFormat(listFiles)) {
core.setFailed(`Input parameter 'list-files' is set to invalid value '${listFiles}'`);
return;
}
const filter = new filter_1.Filter(filtersYaml);
const files = await getChangedFiles(token, base, ref, initialFetchDepth);
core.info(`Detected ${files.length} changed files`);
const results = filter.match(files);
exportResults(results, listFiles);
@ -557,6 +560,28 @@ async function run() {
core.setFailed(error.message);
}
}
function parseFilesInput(customfiles) {
const files = [];
for (let i = 0; i + 1 < customfiles.length; i += 1) {
var filearray = customfiles[i].split(/\s+/);
if (filearray.length == 1) {
var filestatus = 'U';
var filename = filearray[0];
}
else if (filearray.length == 2) {
var filestatus = filearray[0];
var filename = filearray[1];
}
else {
throw new Error(`Line '${i + 1}' in custom file: '${customfiles[i]}' is not parseable.`);
}
files.push({
status: git.statusMap[filestatus],
filename: filename
});
}
return files;
}
function isPathInput(text) {
return !(text.includes('\n') || text.includes(':'));
}
@ -579,12 +604,12 @@ async function getChangedFiles(token, base, ref, initialFetchDepth) {
return await git.getChangesOnHead();
}
const prEvents = ['pull_request', 'pull_request_review', 'pull_request_review_comment', 'pull_request_target'];
if (prEvents.includes(github.context.eventName)) {
if (prEvents.includes(github.context.eventName) && !ref && !base) {
if (ref) {
core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`);
core.warning(`'ref' input parameter is ignored when 'base' is not also set on PR events.`);
}
if (base) {
core.warning(`'base' input parameter is ignored when action is triggered by pull request event`);
core.warning(`'base' input parameter is ignored when 'ref' is not also set on PR events.`);
}
const pr = github.context.payload.pull_request;
if (token) {

View file

@ -260,7 +260,7 @@ function fixStdOutNullTermination(): void {
core.info('')
}
const statusMap: {[char: string]: ChangeStatus} = {
export const statusMap: {[char: string]: ChangeStatus} = {
A: ChangeStatus.Added,
C: ChangeStatus.Copied,
D: ChangeStatus.Deleted,

View file

@ -18,6 +18,7 @@ async function run(): Promise<void> {
process.chdir(workingDirectory)
}
const customfiles = core.getInput('files', {required: false})
const token = core.getInput('token', {required: false})
const ref = core.getInput('ref', {required: false})
const base = core.getInput('base', {required: false})
@ -26,13 +27,16 @@ async function run(): Promise<void> {
const listFiles = core.getInput('list-files', {required: false}).toLowerCase() || 'none'
const initialFetchDepth = parseInt(core.getInput('initial-fetch-depth', {required: false})) || 10
const files = customfiles
? parseFilesInput(customfiles.split(/\r?\n/))
: await getChangedFiles(token, base, ref, initialFetchDepth)
if (!isExportFormat(listFiles)) {
core.setFailed(`Input parameter 'list-files' is set to invalid value '${listFiles}'`)
return
}
const filter = new Filter(filtersYaml)
const files = await getChangedFiles(token, base, ref, initialFetchDepth)
core.info(`Detected ${files.length} changed files`)
const results = filter.match(files)
exportResults(results, listFiles)
@ -41,6 +45,28 @@ async function run(): Promise<void> {
}
}
function parseFilesInput(customfiles: string[]): File[] {
const files: File[] = []
for (let i = 0; i + 1 < customfiles.length; i += 1) {
var filearray = customfiles[i].split(/\s+/)
if (filearray.length == 1) {
var filestatus = 'U'
var filename = filearray[0]
} else if (filearray.length == 2) {
var filestatus = filearray[0]
var filename = filearray[1]
} else {
throw new Error(`Line '${i + 1}' in custom file: '${customfiles[i]}' is not parseable.`)
}
files.push({
status: git.statusMap[filestatus],
filename: filename
})
}
return files
}
function isPathInput(text: string): boolean {
return !(text.includes('\n') || text.includes(':'))
}
@ -68,12 +94,12 @@ async function getChangedFiles(token: string, base: string, ref: string, initial
}
const prEvents = ['pull_request', 'pull_request_review', 'pull_request_review_comment', 'pull_request_target']
if (prEvents.includes(github.context.eventName)) {
if (prEvents.includes(github.context.eventName) && !ref && !base) {
if (ref) {
core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`)
core.warning(`'ref' input parameter is ignored when 'base' is not also set on PR events.`)
}
if (base) {
core.warning(`'base' input parameter is ignored when action is triggered by pull request event`)
core.warning(`'base' input parameter is ignored when 'ref' is not also set on PR events.`)
}
const pr = github.context.payload.pull_request as Webhooks.WebhookPayloadPullRequestPullRequest
if (token) {