This commit is contained in:
Corey Butler 2019-09-02 18:45:33 -05:00
parent 28be1e2325
commit 1c9d139f45
2 changed files with 210 additions and 8 deletions

View File

@ -1,3 +1,96 @@
# Autotag
...fill me in...
Outputs: tag - empty if no tag is created.
## Usage
The following is an example `.github/main.workflow` that will execute when a `push` to the `master` branch occurs.
```yaml
name: Node CI
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
```
To make this work, the workflow must have the checkout action _before_ the autotag action.
This **order** is important!
```yaml
- uses: actions/checkout@master
- uses: butlerlogic/action-autotag@1.0.0
```
> If the repository is not checked out first, the autotagger cannot find the package.json file.
## Configuration
The `GITHUB_TOKEN` must be passed in. Without this, it is not possible to create a new tag. Make sure the autotag action looks like the following example:
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
```
The action will automatically extract the token at runtime. **DO NOT MANUALLY ENTER YOUR TOKEN.** If you put the actual token in your workflow file, you're make it accessible in plaintext to anyone who ever views the repository (it wil be in your git history).
### Optional Configurations
There are several options to customize how the tag is created.
1. `tag_prefx`
By default, `package.json` uses [semantic versioning](https://semver.org/), such as `1.0.0`. A prefix can be used to add text before the tag name. For example, if `tag_prefx` is set to `v`, then the tag would be labeled as `v1.0.0`.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
tag_prefx: "v"
```
1. `tag_suffix`
Text can also be applied to the end of the tag by setting `tag_suffix`. For example, if `tag_suffix` is ` (beta)`, the tag would be `1.0.0 (beta)`. Please note this example violates semantic versioning and is merely here to illustrate how to add text to the end of a tag name if you _really_ want to.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
tag_suffix: " (beta)"
```
1. `tag_message`
This is the annotated commit message associated with the tag. By default, a
changelog will be generated from the commits between the latest tag and the new tag (HEAD). This will override that with a hard-coded message.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
tag_message: "Custom message goes here."
```
## Developer Notes
If you are building an action that runs after this one, be aware this action produces several [outputs](https://help.github.com/en/articles/metadata-syntax-for-github-actions#outputs):
1. `tagname` will be empty if no tag was created, or it will be the value of the new tag.
1. `tagsha`: The SHA of the new tag.
1. `taguri`: The URI/URL of the new tag reference.
1. `version` will be the version attribute found in the `package.json` file.

View File

@ -6,22 +6,131 @@ const path = require('path')
async function run() {
try {
const git = new github.GitHub(process.env.INPUT_GITHUB_TOKEN)
core.warning(` Available environment variables:\n -> ${Object.keys(process.env).map(i => i + ' :: ' + process.env[i]).join('\n -> ')}`)
core.debug(` Available environment variables:\n -> ${Object.keys(process.env).map(i => i + ' :: ' + process.env[i]).join('\n -> ')}`)
let dir = fs.readdirSync(path.resolve(process.env.GITHUB_WORKSPACE), { withFileTypes: true }).map(entry => {
return `${entry.isDirectory() ? '> ' : ' - '}${entry.name}`
}).join('\n')
core.warning(` Working Directory: ${process.env.GITHUB_WORKSPACE}:\n${dir}`)
core.debug(` Working Directory: ${process.env.GITHUB_WORKSPACE}:\n${dir}`)
let pkg = require(path.join(process.env.GITHUB_WORKSPACE, 'package.json'))
let pkgfile = path.join(process.env.GITHUB_WORKSPACE, 'package.json')
core.warning(` ${pkg.version}`)
if (!fs.existsSync(pkgfile)) {
core.setFailed('package.json does not exist.')
return
}
core.setOutput('tag', '')
let pkg = require(pkgfile)
core.setOutput('version', pkg.version)
core.debug(` Detected version ${pkg.version}`)
if (!process.env.hasOwnProperty('INPUT_GITHUB_TOKEN') || process.env.INPUT_GITHUB_TOKEN.trim().length === 0) {
core.setFailed('Invalid or missing GITHUB_TOKEN.')
return
}
// Check existing for existing tag
const git = new github.GitHub(process.env.INPUT_GITHUB_TOKEN)
const owner = process.env.GITHUB_ACTOR
const repo = process.env.GITHUB_REPOSITORY.split('/').pop()
let tags = await git.repos.listTags({
owner,
repo,
per_page: 100
})
// Check for existance of tag and abort (short circuit) if it already exists.
for (let tag of tags.data) {
if (tag.name.trim().toLowerCase() === pkg.version.trim().toLowerCase()) {
core.warning(`"${tag.name.trim()}" tag already exists.`)
core.setOutput('tagname', '')
return
}
}
// Create the new tag name
let tagName = pkg.version
const tagPrefix = core.getInput('tag_prefix', { required: false })
const tagSuffix = core.getInput('tag_suffix', { required: false })
const tagMsg = core.getInput('tag_message', { required: false }).trim()
tagName = `${tagPrefix}${tagName}${tagSuffix}`
if (tagMsg.length === 0 && tags.data.length > 0) {
try {
latestTag = tags.data.shift()
let changelog = await git.repos.compareCommits({
owner,
repo,
base: latestTag.name,
head: 'master'
})
tagMsg = changelog.data.commits.map(commit => `**1) ${commit.commit.message}** (${commit.author.login})\n(SHA: ${commit.sha})\n`).join('\n')
} catch (e) {
core.setFailed(e.message)
return
}
}
let newTag
try {
newTag = await git.git.createTag({
owner,
repo,
tag: tagName,
message: tagMsg.trim().length > 0
? tagMsg
: `Version ${pkg.version}`,
object: process.env.GITHUB_SHA,
type: 'commit'
})
core.warning(`Created new tag: ${newTag.data.tag}`)
} catch (e) {
core.setFailed(e.message)
return
}
let newReference
try {
newReference = await git.git.createRef({
owner,
repo,
ref: `refs/tags/${newTag.data.tag}`,
sha: newTag.data.sha
})
core.warning(`Reference ${newReference.data.ref} available at ${newReference.data.url}`)
} catch (e) {
core.warning({
owner,
repo,
ref: `refs/tags/${newTag.data.tag}`,
sha: newTag.data.sha
})
core.setFailed(e.message)
return
}
// Store values for other actions
if (typeof newTag === 'object' && typeof newReference === 'object') {
core.setOutput('tagname', tagName)
core.setOutput('tagsha', newTag.data.sha)
core.setOutput('taguri', newReference.data.url)
}
} catch (error) {
core.setFailed(error.message)
core.warning(error.message)
core.setOutput('tagname', '')
core.setOutput('tagsha', '')
core.setOutput('taguri', '')
}
}