Skip to content

Commit

Permalink
feat(action): githubToken is optional (uses action token), added gith…
Browse files Browse the repository at this point in the history
…ubRepo, prNumber, and pushBefore & After
  • Loading branch information
trilom committed Mar 1, 2020
1 parent 6f64d05 commit b24e2c3
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 69 deletions.
149 changes: 101 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,101 @@ This action will take the information from the Push/Pull Request and output some

## Inputs

### githubRepo

_Optional_ - `string` - the github repository you want to compare changes from, defaults to the github.repository.

### githubToken

**Required** - string - your github token
_Optional_ - `string` - specific github token, github.token is used by default (Github Action Runner)

### output

_Optional_ - string - type of output for output variables, default is json. Use ',' for comma separated values, or ' ' for space delimited values. You can also create your own delimiter for example ' |FILE:' will output 'file1.yml |FILE:file2.yml |FILE:file3.yml'.
_Optional_ - `string` - type of output for output variables, default is json. Use ',' for comma separated values, or ' ' for space delimited values. You can also create your own delimiter for example ' |FILE:' will output 'file1.yml |FILE:file2.yml |FILE:file3.yml'.

### fileOutput

_Optional_ - string - type of output for file output, default is json. Use ',' for comma separated values, or ' ' for space delimited values. You can also create your own delimiter for example ' |FILE:' will output 'file1.yml |FILE:file2.yml |FILE:file3.yml'. If you select json then the file format will be .json, if you select ',' then the file format will be .csv, anything else will output the files as .txt
_Optional_ - `string` - type of output for file output, default is json. Use ',' for comma separated values, or ' ' for space delimited values. You can also create your own delimiter for example `\ |FILE:` will output:

> file1.yml |FILE:file2.yml |FILE:file3.yml
If you select json then the file format will be .json, if you select ',' then the file format will be .csv, anything else will output the files as .txt

### pushBefore

_Optional_ - `string` - pass in a specific sha to compare to as a before, required if using pushAfter. (push payload after github.payload.before)

### pushAfter

_Optional_ - `string` - pass in a specific sha to compare to as an after, required if using pushBefore. (push payload after github.payload.after)

### prNumber

_Optional_ - `string` - pass in a specific PR number to get file changes from.

## Outputs

### files

**Required** - string - The names all new, updated, and deleted files. The output is dependant on the output input, default is a json string.
steps.file_changes.outputs.files - `string` - The names all new, updated, and deleted files. The output is dependant on the output input, default is a json string.

### files_added

**Required** - string - The names of the newly created files. The output is dependant on the output input, default is a json string.
steps.file_changes.outputs.files_added - `string` - The names of the newly created files. The output is dependant on the output input, default is a json string.

### files_modified

**Required** - string - The names of the updated files. The output is dependant on the output input, default is a json string.
steps.file_changes.outputs.files_modified - `string` - The names of the updated files. The output is dependant on the output input, default is a json string.

### files_deleted

**Required** - string - The names of the deleted files. The output is dependant on the output input, default is a json string.
steps.file_changes.outputs.files_deleted - `string` - The names of the deleted files. The output is dependant on the output input, default is a json string.

## Example usage

```yaml
id: file_changes
uses: trilom/file-changes-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
# bare minimal
name: changes
on: push
jobs:
changes:
runs-on: ubuntu-latest
steps:
- id: file_changes
uses: trilom/file-changes-action@v1

### full
name: changes
on: [push, pull_request] # push or pull, or any event with custom pr number or before/after commit sha
jobs:
changes:
runs-on: ubuntu-latest
steps:
- id: file_changes
uses: trilom/file-changes-action@v1
with:
# optional target repo
githubRepo: trilom/file-changes-action
# optional token
githubToken: ${{ secrets.BOT_TOKEN }}
# optional output format
output: 'json'
# optional fileoutput format
fileOutput: 'csv'
# optional push before SHA (need both before and after)
pushBefore: 79eeec74aebc3deb0a2f6234c5ac13142e9224e5
# optional push after SHA (need both before and after)
pushAfter: 1c5a2bfde79e2c9cffb75b9a455391350fe69a40
# optional PR number to compare
prNumber: 36
```
## How to Use
In order to make those decisions we need to know what files have changed and that is where this action comes in. In the example below we are checking out our repository code, and then running the `trilom/file-changes-action@v1` action. The only thing you need to provide is a GITHUB_TOKEN so that Octokit can make it's API calls.

If a PR is made then it will look at all of the files included in the PR.
If a push is made then it will compare commits from the SHA `github.context.payload.before` to the SHA `github.context.payload.after` of the push.
If a push is made then it will compare commits from the SHA `github.payload.before` to the SHA `github.payload.after` of the push.

After gathering this information it will output the files in 2 ways.

Expand All @@ -72,24 +122,15 @@ Another case is if the **mappings/wordpress.mappings.yml** changes, we want to d

```yaml
name: push-develop
on:
push:
branches:
- develop
on: [push]
jobs:
build:
changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- id: file_changes
uses: trilom/file-changes-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
- name: test
run: |
ls $HOME
cat $HOME/files.json
cat $HOME/files_modified.json
cat $HOME/files_added.json
Expand All @@ -104,58 +145,70 @@ You can set the output and fileOutput to ',' for csv output.

```yaml
name: push-develop
on:
push:
branches:
- develop
paths:
- 'cloudformation/templates/*.yml'
- 'cloudformation/mappings/*.yml'
- 'functions/*'
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- id: file_changes
uses: trilom/file-changes-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
output: ','
fileOutput: ','
- name: test
run: |
cat $HOME/files.csv
```

You can set the output and fileOutput to ' ' for txt output.
You can set the output and fileOutput to ' ' for txt output. We also used a specific token, and got info for the PR that this push came from.

```yaml
name: push-develop
on:
push:
branches:
- develop
paths:
- 'cloudformation/templates/*.yml'
- 'cloudformation/mappings/*.yml'
- 'functions/*'
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/github-script@0.6.0
id: pr
with:
github-token: ${{env.BOT_USER_TOKEN}}
result-encoding: string
script: |
const result = await github.repos.listPullRequestsAssociatedWithCommit({
owner: context.payload.repository.owner.name,
repo: context.payload.repository.name,
commit_sha: context.payload.head_commit.id
})
return result.data[0].number;
- id: file_changes
uses: trilom/file-changes-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
githubToken: ${{ env.BOT_USER_TOKEN }}
prNumber: ${{ steps.pr.outputs.results }}
output: ' '
fileOutput: ' '
- name: test
run: |
cat $HOME/files.txt
```

```bash
# install project dependencies (including devDependencies)
yarn
# build the project (dist files)
yarn build
# build and lint
# run prettier (this will make your ugly code pretty)
yarn format
# dry-run prettier (this will tell you if your ugly code needs to be made pretty)
yarn format-check
# lint project
yarn lint
# test
yarn jest
# clean duh
yarn clean
```
19 changes: 18 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,25 @@ name: 'File Changes Action'
description: 'Creates outputs variables of files modified, added, or deleted by a PR or Push.'
author: 'Bryan Killian <me@trilom.org>'
inputs:
githubRepo:
description: 'The github repository you want to compare changes from, defaults to the github.repository.'
default: ${{ join('', github.repository) }}
required: true
githubToken:
description: 'The GITHUB_TOKEN secret if necessary'
description: 'The github action token will be used by default, if you want to use something different than you can pass it in here.'
default: ${{ github.token }}
required: true
pushBefore:
description: 'Pass in a specific sha to compare to as a before, required if using pushAfter. (push BASE payload after github.payload.before)'
default: ${{ join('', github.payload.before) }}
required: false
pushAfter:
description: 'Pass in a specific sha to compare to as an after, required if using pushBefore. (push HEAD payload after github.payload.after)'
default: ${{ join('', github.payload.after) }}
required: false
prNumber:
description: 'Pass in a specific PR number to get file changes from.'
default: ${{ join('', github.event.pull_request.number) }}
required: false
output:
description: 'Choose between json (default), or custom delimiter by passing a string, for example '','' for csv variable output'
Expand Down
58 changes: 38 additions & 20 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
import * as core from '@actions/core'
import * as fs from 'fs'
import * as gh from '@actions/github'
import {ChangedFiles, sortChangedFiles} from './ChangedFiles'
import { ChangedFiles, sortChangedFiles } from './ChangedFiles'

async function getChangedPRFiles(
repo: string,
client: gh.GitHub,
prNumber: number
): Promise<ChangedFiles> {
const options = client.pulls.listFiles.endpoint.merge({
owner: gh.context.repo.owner,
repo: gh.context.repo.repo,
owner: repo.split('/')[0],
repo: repo.split('/')[1],
pull_number: prNumber
})
return sortChangedFiles(
Expand All @@ -21,24 +22,20 @@ async function getChangedPRFiles(
}

async function getChangedPushFiles(
repo: string,
client: gh.GitHub,
base: string,
head: string
): Promise<ChangedFiles> {
const response = await client.repos.compareCommits({
owner: gh.context.repo.owner,
repo: gh.context.repo.repo,
owner: repo.split('/')[0],
repo: repo.split('/')[1],
base,
head
})
return sortChangedFiles(response.data.files)
}

function getPrNumber(): number | null {
const pr = gh.context.payload.pull_request
return pr ? pr.number : null
}

function writeFiles(format: string, changedFiles: ChangedFiles): void {
switch (format.trim()) {
case 'json':
Expand Down Expand Up @@ -86,39 +83,60 @@ function writeOutput(format: string, changedFiles: ChangedFiles): void {
async function run(): Promise<void> {
try {
const github: any = gh.context
const repo: string = core.getInput('githubRepo')
const token: string = core.getInput('githubToken')
const output: string = core.getInput('output')
const fileOutput: string = core.getInput('fileOutput')
const pushBefore: string = core.getInput('pushBefore')
const pushAfter: string = core.getInput('pushAfter')
const prNumber: string = core.getInput('prNumber')
const isPush = pushBefore !== '' && pushAfter !== ''
const isPR = prNumber !== ''
const client = new gh.GitHub(token)
let changedFiles = new ChangedFiles()
if (github.eventName === 'push') {
// do push actions
changedFiles = await getChangedPushFiles(
client,
github.payload.before,
github.payload.after
if (isPush && isPR) {
core.setFailed(
`You can't pick PR and Push, I don't know which one to do.`
)
} else if (github.eventName === 'pull_request') {
} else if (isPR) {
// do PR actions
const prNumber = getPrNumber()
if (prNumber != null) {
changedFiles = await getChangedPRFiles(client, prNumber)
try {
changedFiles = await getChangedPRFiles(repo, client, parseInt(prNumber))
} catch (error) {
core.error(`There was an error getting Pull Request change files:${error}`)
throw error
}
} else {
core.setFailed(
'Could not get pull request number from context, exiting'
)
return
}
} else if (isPush) {
// do push actions
try {
changedFiles = await getChangedPushFiles(
repo,
client,
pushBefore,
pushAfter
)
} catch (error) {
core.error(`There was an error getting Push change files:${error}`)
throw error
}
} else {
core.setFailed(
`Change not initiated by a PR or Push, it was ${
github.eventName
github.eventName
} instead. Github:${JSON.stringify(github)}`
)
return
}
// write file output
writeFiles(fileOutput, changedFiles)

// write output vars
writeOutput(output, changedFiles)

Expand Down

0 comments on commit b24e2c3

Please sign in to comment.