Merge pull request #53 from dorny/detect-local-changes

Support local changes
This commit is contained in:
Michal Dorner 2020-11-22 21:17:54 +01:00 committed by GitHub
commit eb75a1edc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 9 deletions

View File

@ -71,6 +71,23 @@ jobs:
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
run: exit 1
test-local-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: echo "NEW FILE" > local
- run: git add local
- uses: ./
id: filter
with:
base: HEAD
filters: |
local:
- local
- name: filter-test
if: steps.filter.outputs.local != 'true'
run: exit 1
test-change-type:
runs-on: ubuntu-latest
steps:

View File

@ -1,5 +1,8 @@
# Changelog
## v2.6.0
- [Support local changes](https://github.com/dorny/paths-filter/pull/53)
## v2.5.3
- [Fixed mapping of removed/deleted change status from github API](https://github.com/dorny/paths-filter/pull/51)
- [Fixed retrieval of all changes via Github API when there are 100+ changes](https://github.com/dorny/paths-filter/pull/50)

View File

@ -35,6 +35,10 @@ doesn't allow this because they doesn't work on a level of individual jobs or st
when `base` input parameter is same as the branch that triggered the workflow:
- Changes are detected from last commit
- Uses git commands to detect changes - repository must be already [checked out](https://github.com/actions/checkout)
- **Local changes**
- Workflow triggered by any event when `base` input parameter is set to `HEAD`
- Changes are detected against current HEAD
- Untracked files are ignored
## Example
```yaml
@ -62,6 +66,7 @@ For more scenarios see [examples](#examples) section.
# What's New
- Support local changes
- Fixed retrieval of all changes via Github API when there are 100+ changes
- Paths expressions are now evaluated using [picomatch](https://github.com/micromatch/picomatch) library
- Support workflows triggered by any event
@ -304,6 +309,35 @@ jobs:
```
</details>
<details>
<summary><b>Local changes:</b> Detect staged and unstaged local changes</summary>
```yaml
on:
push:
branches: # Push to following branches will trigger the workflow
- master
- develop
- release/**
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Some action which modifies files tracked by git (e.g. code linter)
- uses: johndoe/some-action@v1
# Filter to detect which files were modified
# Changes could be for example automatically committed
- uses: dorny/paths-filter@v2
id: filter
with:
base: HEAD
filters: ... # Configure your filters
```
</details>
## Advanced options
<details>

30
dist/index.js vendored
View File

@ -3811,11 +3811,12 @@ 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.getChanges = exports.getChangesInLastCommit = exports.NULL_SHA = void 0;
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(__webpack_require__(807));
const core = __importStar(__webpack_require__(470));
const file_1 = __webpack_require__(258);
exports.NULL_SHA = '0000000000000000000000000000000000000000';
exports.HEAD = 'HEAD';
async function getChangesInLastCommit() {
core.startGroup(`Change detection in last commit`);
let output = '';
@ -3850,6 +3851,20 @@ async function getChanges(ref) {
return parseGitDiffOutput(output);
}
exports.getChanges = getChanges;
async function getChangesOnHead() {
// Get current changes - both staged and unstaged
core.startGroup(`Change detection on HEAD`);
let output = '';
try {
output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', 'HEAD'])).stdout;
}
finally {
fixStdOutNullTermination();
core.endGroup();
}
return parseGitDiffOutput(output);
}
exports.getChangesOnHead = getChangesOnHead;
async function getChangesSinceMergeBase(ref, initialFetchDepth) {
if (!(await hasCommit(ref))) {
// Fetch and add base branch
@ -4675,6 +4690,11 @@ function getConfigFileContent(configPath) {
return fs.readFileSync(configPath, { encoding: 'utf8' });
}
async function getChangedFiles(token, base, initialFetchDepth) {
// 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) {
return await git.getChangesOnHead();
}
if (github.context.eventName === 'pull_request' || github.context.eventName === 'pull_request_target') {
const pr = github.context.payload.pull_request;
if (token) {
@ -4692,7 +4712,7 @@ async function getChangedFilesFromGit(base, initialFetchDepth) {
const defaultRef = (_a = github.context.payload.repository) === null || _a === void 0 ? void 0 : _a.default_branch;
const beforeSha = github.context.eventName === 'push' ? github.context.payload.before : null;
const pushRef = git.getShortName(github.context.ref) ||
(core.warning(`'ref' field is missing in PUSH event payload - using current branch, tag or commit SHA`),
(core.warning(`'ref' field is missing in event payload - using current branch, tag or commit SHA`),
await git.getCurrentRef());
const baseRef = git.getShortName(base) || defaultRef;
if (!baseRef) {
@ -4700,11 +4720,11 @@ async function getChangedFilesFromGit(base, initialFetchDepth) {
}
const isBaseRefSha = git.isGitSha(baseRef);
const isBaseSameAsPush = baseRef === pushRef;
// If base is commit SHA will do comparison against the referenced commit
// Or If base references same branch it was pushed to, we will do comparison against the previously pushed commit
// If base is commit SHA we will do comparison against the referenced commit
// Or if base references same branch it was pushed to, we will do comparison against the previously pushed commit
if (isBaseRefSha || isBaseSameAsPush) {
if (!isBaseRefSha && !beforeSha) {
core.warning(`'before' field is missing in PUSH event payload - changes will be detected from last commit`);
core.warning(`'before' field is missing in event payload - changes will be detected from last commit`);
return await git.getChangesInLastCommit();
}
const baseSha = isBaseRefSha ? baseRef : beforeSha;

View File

@ -3,6 +3,7 @@ import * as core from '@actions/core'
import {File, ChangeStatus} from './file'
export const NULL_SHA = '0000000000000000000000000000000000000000'
export const HEAD = 'HEAD'
export async function getChangesInLastCommit(): Promise<File[]> {
core.startGroup(`Change detection in last commit`)
@ -39,6 +40,20 @@ export async function getChanges(ref: string): Promise<File[]> {
return parseGitDiffOutput(output)
}
export async function getChangesOnHead(): Promise<File[]> {
// Get current changes - both staged and unstaged
core.startGroup(`Change detection on HEAD`)
let output = ''
try {
output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', 'HEAD'])).stdout
} finally {
fixStdOutNullTermination()
core.endGroup()
}
return parseGitDiffOutput(output)
}
export async function getChangesSinceMergeBase(ref: string, initialFetchDepth: number): Promise<File[]> {
if (!(await hasCommit(ref))) {
// Fetch and add base branch

View File

@ -55,6 +55,12 @@ function getConfigFileContent(configPath: string): string {
}
async function getChangedFiles(token: string, base: string, initialFetchDepth: number): Promise<File[]> {
// 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) {
return await git.getChangesOnHead()
}
if (github.context.eventName === 'pull_request' || github.context.eventName === 'pull_request_target') {
const pr = github.context.payload.pull_request as Webhooks.WebhookPayloadPullRequestPullRequest
if (token) {
@ -75,7 +81,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number):
const pushRef =
git.getShortName(github.context.ref) ||
(core.warning(`'ref' field is missing in PUSH event payload - using current branch, tag or commit SHA`),
(core.warning(`'ref' field is missing in event payload - using current branch, tag or commit SHA`),
await git.getCurrentRef())
const baseRef = git.getShortName(base) || defaultRef
@ -88,11 +94,11 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number):
const isBaseRefSha = git.isGitSha(baseRef)
const isBaseSameAsPush = baseRef === pushRef
// If base is commit SHA will do comparison against the referenced commit
// Or If base references same branch it was pushed to, we will do comparison against the previously pushed commit
// If base is commit SHA we will do comparison against the referenced commit
// Or if base references same branch it was pushed to, we will do comparison against the previously pushed commit
if (isBaseRefSha || isBaseSameAsPush) {
if (!isBaseRefSha && !beforeSha) {
core.warning(`'before' field is missing in PUSH event payload - changes will be detected from last commit`)
core.warning(`'before' field is missing in event payload - changes will be detected from last commit`)
return await git.getChangesInLastCommit()
}