Change detection via git + rename `githubToken` to `token` (#9)
This commit is contained in:
parent
a2e5f9f7bb
commit
1cbb925a17
|
@ -1,2 +1,4 @@
|
|||
error:
|
||||
- not_existing_path/**/*
|
||||
any:
|
||||
- "**/*"
|
|
@ -16,7 +16,23 @@ jobs:
|
|||
npm install
|
||||
npm run all
|
||||
|
||||
test:
|
||||
test-inline:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
error:
|
||||
- not_existing_path/**/*
|
||||
any:
|
||||
- "**/*"
|
||||
- name: filter-test
|
||||
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
|
||||
run: exit 1
|
||||
|
||||
test-external:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -24,16 +40,19 @@ jobs:
|
|||
id: filter
|
||||
with:
|
||||
filters: '.github/filters.yml'
|
||||
- uses: ./
|
||||
id: inlineFilter
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- src/**/*
|
||||
tests:
|
||||
- __tests__/**/*
|
||||
any:
|
||||
- "**/*"
|
||||
- name: filter-test
|
||||
if: steps.filter.outputs.any != 'true' || steps.inlineFilter.outputs.any != 'true'
|
||||
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
|
||||
run: exit 1
|
||||
|
||||
test-without-token:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./
|
||||
id: filter
|
||||
with:
|
||||
token: ''
|
||||
filters: '.github/filters.yml'
|
||||
- name: filter-test
|
||||
if: steps.filter.outputs.any != 'true' || steps.filter.outputs.error == 'true'
|
||||
run: exit 1
|
||||
|
|
11
README.md
11
README.md
|
@ -21,7 +21,7 @@ Corresponding output variable will be created to indicate if there's a changed f
|
|||
Output variables can be later used in the `if` clause to conditionally run specific steps.
|
||||
|
||||
### Inputs
|
||||
- **`githubToken`**: GitHub Access Token - defaults to `${{ github.token }}`
|
||||
- **`token`**: GitHub Access Token - defaults to `${{ github.token }}`
|
||||
- **`filters`**: Path to the configuration file or directly embedded string in YAML format. Filter configuration is a dictionary, where keys specifies rule names and values are lists of file path patterns.
|
||||
|
||||
### Outputs
|
||||
|
@ -78,10 +78,11 @@ jobs:
|
|||
|
||||
## How it works
|
||||
|
||||
1. Required inputs are checked (`githubToken` & `filters`)
|
||||
2. Provided access token is used to fetch list of changed files.
|
||||
3. For each filter rule it checks if there is any matching file
|
||||
4. Output variables are set
|
||||
1. Required inputs are checked (`filters`)
|
||||
2. If token was provided, it's used to fetch list of changed files from Github API.
|
||||
3. If token was not provided, base branch is fetched and changed files are detected using `git diff-index` command.
|
||||
4. For each filter rule it checks if there is any matching file
|
||||
5. Output variables are set
|
||||
|
||||
## Difference from related projects:
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ name: 'Pull request changed files filter'
|
|||
description: 'Enables conditional execution of workflow job steps considering which files are modified by a pull request.'
|
||||
author: 'Michal Dorner <dorner.michal@gmail.com>'
|
||||
inputs:
|
||||
githubToken:
|
||||
token:
|
||||
description: 'GitHub Access Token'
|
||||
required: true
|
||||
required: false
|
||||
default: ${{ github.token }}
|
||||
filters:
|
||||
description: 'Path to the configuration file or YAML string with filters definition'
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,6 +9,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.4.tgz",
|
||||
"integrity": "sha512-YJCEq8BE3CdN8+7HPZ/4DxJjk/OkZV2FFIf+DlZTC/4iBlzYCD5yjRR6eiOS5llO11zbRltIRuKAjMKaWTE6cg=="
|
||||
},
|
||||
"@actions/exec": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.4.tgz",
|
||||
"integrity": "sha512-4DPChWow9yc9W3WqEbUj8Nr86xkpyE29ZzWjXucHItclLbEW6jr80Zx4nqv18QL6KK65+cifiQZXvnqgTV6oHw==",
|
||||
"requires": {
|
||||
"@actions/io": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@actions/github": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-2.2.0.tgz",
|
||||
|
@ -27,6 +35,11 @@
|
|||
"tunnel": "0.0.6"
|
||||
}
|
||||
},
|
||||
"@actions/io": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz",
|
||||
"integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg=="
|
||||
},
|
||||
"@babel/code-frame": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/github": "^2.2.0",
|
||||
"@octokit/webhooks": "^7.6.2",
|
||||
"minimatch": "^3.0.4"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import {exec} from '@actions/exec'
|
||||
|
||||
export async function fetchBranch(base: string): Promise<void> {
|
||||
const exitCode = await exec('git', ['fetch', '--depth=1', 'origin', base])
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(`Fetching branch ${base} failed, exiting`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getChangedFiles(base: string): Promise<string[]> {
|
||||
let output = ''
|
||||
const exitCode = await exec('git', ['diff-index', '--name-only', base], {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => (output += data.toString())
|
||||
}
|
||||
})
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(`Couldn't determine changed files, exiting`)
|
||||
}
|
||||
|
||||
return output
|
||||
.split('\n')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0)
|
||||
}
|
23
src/main.ts
23
src/main.ts
|
@ -4,16 +4,14 @@ import * as github from '@actions/github'
|
|||
import {Webhooks} from '@octokit/webhooks'
|
||||
|
||||
import Filter from './filter'
|
||||
import * as git from './git'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
const token = core.getInput('githubToken', {required: true})
|
||||
const token = core.getInput('token', {required: false})
|
||||
const filtersInput = core.getInput('filters', {required: true})
|
||||
|
||||
const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput
|
||||
|
||||
const client = new github.GitHub(token)
|
||||
|
||||
if (github.context.eventName !== 'pull_request') {
|
||||
core.setFailed('This action can be triggered only by pull_request event')
|
||||
return
|
||||
|
@ -21,7 +19,8 @@ async function run(): Promise<void> {
|
|||
|
||||
const pr = github.context.payload.pull_request as Webhooks.WebhookPayloadPullRequestPullRequest
|
||||
const filter = new Filter(filtersYaml)
|
||||
const files = await getChangedFiles(client, pr)
|
||||
const files = token ? await getChangedFilesFromApi(token, pr) : await getChangedFilesFromGit(pr)
|
||||
|
||||
const result = filter.match(files)
|
||||
for (const key in result) {
|
||||
core.setOutput(key, String(result[key]))
|
||||
|
@ -47,11 +46,21 @@ function getConfigFileContent(configPath: string): string {
|
|||
return fs.readFileSync(configPath, {encoding: 'utf8'})
|
||||
}
|
||||
|
||||
// Fetch base branch and use `git diff` to determine changed files
|
||||
async function getChangedFilesFromGit(pullRequest: Webhooks.WebhookPayloadPullRequestPullRequest): Promise<string[]> {
|
||||
core.debug('Fetching base branch and using `git diff-index` to determine changed files')
|
||||
const baseRef = pullRequest.base.ref
|
||||
await git.fetchBranch(baseRef)
|
||||
return await git.getChangedFiles(pullRequest.base.sha)
|
||||
}
|
||||
|
||||
// Uses github REST api to get list of files changed in PR
|
||||
async function getChangedFiles(
|
||||
client: github.GitHub,
|
||||
async function getChangedFilesFromApi(
|
||||
token: string,
|
||||
pullRequest: Webhooks.WebhookPayloadPullRequestPullRequest
|
||||
): Promise<string[]> {
|
||||
core.debug('Fetching list of modified files from Github API')
|
||||
const client = new github.GitHub(token)
|
||||
const pageSize = 100
|
||||
const files: string[] = []
|
||||
for (let page = 0; page * pageSize < pullRequest.changed_files; page++) {
|
||||
|
|
Loading…
Reference in New Issue