Merge pull request #15 from ButlerLogic/master

Updating stable version to 1.1.0
This commit is contained in:
Corey Butler 2020-04-03 00:34:47 -05:00 committed by GitHub
commit 88cc59cb86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 592 additions and 257 deletions

63
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,63 @@
name: Autotag Action Test
on:
push:
branches:
- master
jobs:
package:
name: Test Suite - Package Strategy
runs-on: ubuntu-latest
steps:
# Checkout updated source code
- uses: actions/checkout@v2
# If the version has changed, create a new git tag for it.
- name: Tag Package
id: package_autotagger
uses: butlerlogic/action-autotag@master
with:
tag_prefix: test_package_
commit_message_template: "{{number}}) {{message}} ({{author}})\n"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Rollback Package Test Release
id: package_rollback
if: success() && ${{ steps.package_autotagger.outputs.tagcreated }} = "yes"
uses: author/action-rollback@master
with:
tag: ${{ steps.package_autotagger.outputs.tagrequested }}
delete_orphan_tag: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
docker:
name: Test Suite - Docker Strategy
runs-on: ubuntu-latest
steps:
# Checkout updated source code
- uses: actions/checkout@v2
# If the version has changed, create a new git tag for it.
- name: Tag Dockerfile
id: docker_autotagger
uses: butlerlogic/action-autotag@master
with:
strategy: docker
tag_prefix: test_docker_
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Rollback Docker Test Release
id: docker_rolback
if: success() && ${{ steps.docker_autotagger.outputs.tagcreated }} = "yes"
uses: author/action-rollback@master
env:
TAG: ${{ steps.docker_autotagger.outputs.tagrequested }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ steps.docker_autotagger.outputs.tagrequested }}
delete_orphan_tag: true

13
.gitignore vendored
View File

@ -1,16 +1,9 @@
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
*.log*
.*
!.gitignore
!.github
!.dockerignore
_*
node_modules

6
Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM node:13-alpine
LABEL version=1.1.0
ADD ./app /app
WORKDIR /app
RUN cd /app && npm i
CMD ["node", "/app/main.js"]

View File

@ -1,7 +1,7 @@
The MIT License (MIT)
Copyright (c) 2019 Corey Butler and contributors
Copyright (c) 2020 Corey Butler and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

120
README.md
View File

@ -1,8 +1,14 @@
# Autotag
This action will read a `package.json` file and compare the `version` attribute to the project's known tags. If a corresponding tag does not exist, it will be created.
This action will auto-generate a Github tag whenever a new version is detected. The following "detection strategies" are available:
This tag works well in combination with:
1. **package**: Monitor a `package.json` for new versions.
1. **docker**: Monitor a `Dockerfile` for a `LABEL version=x.x.x` value.
1. **regex**: Use a JavaScript [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) with any file for your own custom extraction.
When a version is detected, it is compared to the current list of tags in the Github repository. If a tag does not exist, it will be created.
This action works well in combination with:
- [actions/create-release](https://github.com/actions/create-release) (Auto-release)
- [author/action-publish](https://github.com/author/action-publish) (Auto-publish JavaScript/Node modules)
@ -44,7 +50,7 @@ This **order** is important!
## 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:
The `GITHUB_TOKEN` **must** be provided. 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@stable
@ -58,62 +64,108 @@ The action will automatically extract the token at runtime. **DO NOT MANUALLY EN
There are several options to customize how the tag is created.
1. `package_root`
#### strategy
By default, autotag will look for the `package.json` file in the project root. If the file is located in a subdirectory, this option can be used to point to the correct file.
This is the strategy used to identify the version number/tag from within the code base.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
1. _package_: Monitor a `package.json` for new versions. Use this for JavaScript projects based on Node modules (npm, yarn, etc).
1. _docker_: Monitor a `Dockerfile` for a `LABEL version=x.x.x` value. USe this for container projects.
1. _regex*_: Use a JavaScript [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) with any file for your own custom extraction.
*An example "
#### root `(required)`
_Formerly `package_root`_
By default, autotag will look for the `package.json` file in the project root. If the file is located in a subdirectory, this option can be used to point to the correct file.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
package_root: "/path/to/subdirectory"
```
root: "/path/to/subdirectory"
```
1. `tag_prefix`
> **EXCEPTION**: This property is not required if the regex_pattern property is defined. In that case, this property is assumed to be "regex".
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_prefix` is set to `v`, then the tag would be labeled as `v1.0.0`.
#### tag_prefix
```yaml
- uses: butlerlogic/action-autotag@1.0.0
By default, [semantic versioning](https://semver.org/) is used, such as `1.0.0`. A prefix can be used to add text before the tag name. For example, if `tag_prefix` 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_prefix: "v"
```
```
1. `tag_suffix`
#### 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.
Text can 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
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
tag_suffix: " (beta)"
```
```
1. `tag_message`
#### 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). Setting this option will override it witha custom 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 current reference (HEAD). Setting this option will override the message.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
tag_message: "Custom message goes here."
```
```
1. `version`
#### commit_message_template
Explicitly set the version instead of automatically detecting from `package.json`.
Useful for non-JavaScript projects where version may be output by a previous action.
By default, a changelog is generated, containing the commit messages since the last release. The message is generated by applying a commit message template to each commit's data attributes.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
commit_message_template: "({{sha}} by {{author}}) {{message}}"
```
Optional data points:
1. `number` The commit number (relevant to the overall list)
1. `message` The commit message.
1. `author` The author of the commit.
1. `sha` The SHA value representing the commit.
The default is `{{number}}) {{message}} ({{author}})\nSHA: {{sha}}\n`.
#### version
Explicitly set the version instead of using automatic detection.
Useful for projects where the version number may be output by a previous action.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
version: "${{ steps.previous_step.outputs.version }}"
```
```
#### regex_pattern
An optional attribute containing the regular expression used to extract the version number.
```yaml
- uses: butlerlogic/action-autotag@1.0.0
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
regex_pattern: "version=([0-9\.]+)"
```
This attribute is used as the first argument of a [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp) object. The first "group" (i.e. what's in parenthesis) will be used as the version number. For an example, see this [working example](regexr.com/51i6n).
## Developer Notes
@ -123,6 +175,8 @@ If you are building an action that runs after this one, be aware this action pro
1. `tagsha`: The SHA of the new tag.
1. `taguri`: The URI/URL of the new tag reference.
1. `tagmessage`: The messge applied to the tag reference (this is what shows up on the tag screen on Github).
1. `tagcreated`: `yes` or `no`.
1. `tagrequested`: The name of the requested tag. This will be populated even if the tag is not created. This will usually be the same as `tagname` and/or `version` for successful executions.
1. `version` will be the version attribute found in the `package.json` file.
---
@ -135,10 +189,10 @@ This action was written and is primarily maintained by [Corey Butler](https://gi
If you use this or find value in it, please consider contributing in one or more of the following ways:
1. Click the "Sponsor" button at the top of the page.
1. Click the "Sponsor" button at the top of the page and make a contribution.
1. Star it!
1. [Tweet about it!](https://twitter.com/intent/tweet?hashtags=github,actions&original_referer=http%3A%2F%2F127.0.0.1%3A91%2F&text=I%20am%20automating%20my%20workflow%20with%20the%20Autotagger%20Github%20action!&tw_p=tweetbutton&url=https%3A%2F%2Fgithub.com%2Fmarketplace%2Factions%2Fautotagger&via=goldglovecb)
1. Fix an issue.
1. Add a feature (post a proposal in an issue first!).
Copyright © 2019 ButlerLogic, Corey Butler, and Contributors.
Copyright © 2020 Butler Logic, Corey Butler, and Contributors.

View File

@ -1,14 +1,21 @@
name: "Autotagger"
description: "Automatically generate new tags when the package.json version changes."
author: "ButlerLogic"
description: "Automatically generate new tags for new versions. Supports several tagging strategies."
author: "Butler Logic"
branding:
icon: "tag"
color: "black"
color: "blue"
inputs:
package_root:
description: Autotag will look for the package.json file in in this location.
root:
description: Autotag will look for the appropriate file in in this location (relative to project root).
required: false
default: './'
strategy:
description: Options include 'package' (for package.json), 'docker' (for Dockerfile), and 'regex' to extract from an arbitrary file. This does not need to be specified if the "regex_pattern" property is provided.
required: false
default: 'package'
package_root:
description: (DEPRECATED. Use 'root' instead.) Autotag will look for the package.json file in in this location.
required: false
tag_prefix:
description: By default, package.json uses semantic versioning, 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".
required: false
@ -18,9 +25,15 @@ inputs:
tag_message:
description: 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.
required: false
commit_message_template:
description: "The commit message template (per commit). Default is `{{number}}) {{message}} ({{author}})\nSHA: {{sha}}\n`"
required: false
version:
description: Explicitly set the version here instead of automatically detecting from `package.json`. Useful for non-JavaScript projects where version may be output by a previous action.
required: false
regex_pattern:
description: An optional attribute containing the regular expression used to extract the version number.
required: false
outputs:
tagname:
description: Returns the new tag value. Empty if a tag is not created.
@ -30,8 +43,12 @@ outputs:
description: The URI/URL of the new tag reference.
tagmessage:
description: The messge applied to the tag reference (this is what shows up on the tag screen on Github).
tagcreated:
description: A "yes" or "no", indicating a new tag was created.
tagrequested:
description: The name of the requested tag. This will be populated even if the tag is not created.
version:
description: The version, as defined in package.json or explicitly set in the input.
runs:
using: "node12"
main: "lib/main.js"
using: 'docker'
image: 'Dockerfile'

16
app/lib/docker.js Normal file
View File

@ -0,0 +1,16 @@
import Regex from './regex.js'
import path from 'path'
import fs from 'fs'
import core from '@actions/core'
export default class Dockerfile extends Regex {
constructor (root = null) {
root = path.join(process.env.GITHUB_WORKSPACE, root)
if (fs.statSync(root).isDirectory()) {
root = path.join(root, 'Dockerfile')
}
super(root, /LABEL[\s\t]+version=[\t\s+]?[\"\']?([0-9\.]+)[\"\']?/i)
}
}

23
app/lib/package.js Normal file
View File

@ -0,0 +1,23 @@
import fs from 'fs'
import path from 'path'
export default class Package {
constructor (root = './') {
root = path.join(process.env.GITHUB_WORKSPACE, root)
if (fs.statSync(root).isDirectory()) {
root = path.join(root, 'package.json')
}
if (!fs.existsSync(root)) {
throw new Error(`package.json does not exist at ${root}.`)
}
this.root = root
this.data = JSON.parse(fs.readFileSync(root))
}
get version () {
return this.data.version
}
}

34
app/lib/regex.js Normal file
View File

@ -0,0 +1,34 @@
import fs from 'fs'
import path from 'path'
export default class Regex {
constructor (root = './', pattern) {
root = path.resolve(root)
if (fs.statSync(root).isDirectory()) {
throw new Error(`${root} is a directory. The Regex tag identification strategy requires a file.`)
}
if (!fs.existsSync(root)) {
throw new Error(`"${root}" does not exist.`)
}
this.content = fs.readFileSync(root).toString()
let content = pattern.exec(this.content)
if (!content) {
this._version = null
// throw new Error(`Could not find pattern matching "${pattern.toString()}" in "${root}".`)
} else {
this._version = content[1]
}
}
get version () {
return this._version
}
get versionFound () {
return this._version !== null
}
}

33
app/lib/setup.js Normal file
View File

@ -0,0 +1,33 @@
import core from '@actions/core'
import fs from 'fs'
import path from 'path'
export default class Setup {
static debug () {
// Metadate for debugging
core.debug(
` Available environment variables:\n -> ${Object.keys(process.env)
.map(i => i + ' :: ' + process.env[i])
.join('\n -> ')}`
)
const dir = fs
.readdirSync(path.resolve(process.env.GITHUB_WORKSPACE), { withFileTypes: true })
.map(entry => {
return `${entry.isDirectory() ? '> ' : ' - '}${entry.name}`
})
.join('\n')
core.debug(` Working Directory: ${process.env.GITHUB_WORKSPACE}:\n${dir}`)
}
static requireAnyEnv () {
for (const arg of arguments) {
if (!process.env.hasOwnProperty(arg)) {
return
}
}
throw new Error('At least one of the following environment variables is required: ' + Array.slice(arguments).join(', '))
}
}

161
app/lib/tag.js Normal file
View File

@ -0,0 +1,161 @@
import core from '@actions/core'
import os from 'os'
import gh from '@actions/github'
// Get authenticated GitHub client (Ocktokit): https://github.com/actions/toolkit/tree/master/packages/github#usage
const github = new gh.GitHub(process.env.GITHUB_TOKEN || process.env.INPUT_GITHUB_TOKEN)
// Get owner and repo from context of payload that triggered the action
const { owner, repo } = gh.context.repo
export default class Tag {
constructor (prefix, version, postfix) {
this.prefix = prefix
this.version = version
this.postfix = postfix
this._tags = null
this._message = null
this._exists = null
this._sha = ''
this._uri = ''
this._ref = ''
}
get name () {
return `${this.prefix.trim()}${this.version.trim()}${this.postfix.trim()}`
}
set message (value) {
if (value && value.length > 0) {
this._message = value
}
}
get sha () {
return this._sha || ''
}
get uri () {
return this._uri || ''
}
get ref () {
return this._ref || ''
}
async getMessage () {
if (this._message !== null) {
return this._message
}
try {
let tags = await this.getTags()
if (tags.length === 0) {
return `Version ${this.version}`
}
const changelog = await github.repos.compareCommits({ owner, repo, base: tags.shift().name, head: 'master' })
const tpl = (core.getInput('commit_message_template', { required: false }) || '').trim()
return changelog.data.commits
.map(
(commit, i) => {
if (tpl.length > 0) {
return tpl
.replace(/\{\{\s?(number)\s?\}\}/gi, i + 1)
.replace(/\{\{\s?(message)\s?\}\}/gi, commit.commit.message)
.replace(/\{\{\s?(author)\s?\}\}/gi, commit.hasOwnProperty('author') ? (commit.author.hasOwnProperty('login') ? commit.author.login : '') : '')
.replace(/\{\{\s?(sha)\s?\}\}/gi, commit.sha)
.trim() + '\n'
} else {
return `${i === 0 ? '\n' : ''}${i + 1}) ${commit.commit.message}${
commit.hasOwnProperty('author')
? commit.author.hasOwnProperty('login')
? ' (' + commit.author.login + ')'
: ''
: ''
}\n(SHA: ${commit.sha})\n`
}
})
.join('\n')
} catch (e) {
core.warning('Failed to generate changelog from commits: ' + e.message + os.EOL)
return `Version ${this.version}`
}
}
async getTags () {
if (this._tags !== null) {
return this._tags.data
}
this._tags = await github.repos.listTags({ owner, repo, per_page: 100 })
return this._tags.data
}
async exists () {
if (this._exists !== null) {
return this._exists
}
const currentTag = this.name
const tags = await this.getTags()
for (const tag of tags) {
if (tag.name === currentTag) {
this._exists = true
return true
}
}
this._exists = false
return false
}
async push () {
let tagexists = await this.exists()
if (!tagexists) {
// Create tag
const newTag = await github.git.createTag({
owner,
repo,
tag: this.name,
message: await this.getMessage(),
object: process.env.GITHUB_SHA,
type: 'commit'
})
this._sha = newTag.data.sha
core.warning(`Created new tag: ${newTag.data.tag}`)
// Create reference
let newReference
try {
newReference = await github.git.createRef({
owner,
repo,
ref: `refs/tags/${newTag.data.tag}`,
sha: newTag.data.sha
})
} catch (e) {
core.warning({
owner,
repo,
ref: `refs/tags/${newTag.data.tag}`,
sha: newTag.data.sha
})
throw e
}
this._uri = newReference.data.url
this._ref = newReference.data.ref
core.warning(`Reference ${newReference.data.ref} available at ${newReference.data.url}` + os.EOL)
} else {
core.warning('Cannot push tag (it already exists).')
}
}
}

87
app/main.js Normal file
View File

@ -0,0 +1,87 @@
import core from '@actions/core'
import os from 'os'
import Setup from './lib/setup.js'
import Package from './lib/package.js'
import Tag from './lib/tag.js'
import Regex from './lib/regex.js'
import Dockerfile from './lib/docker.js'
async function run () {
try {
Setup.debug()
Setup.requireAnyEnv('GITHUB_TOKEN', 'INPUT_GITHUB_TOKEN')
// Configure the default output
core.setOutput('tagcreated', 'no')
// Identify the tag parsing strategy
const root = core.getInput('root', { required: false }) || core.getInput('package_root', { required: false }) || './'
const strategy = (core.getInput('regex_pattern', { required: false }) || '').trim().length > 0 ? 'regex' : ((core.getInput('strategy', { required: false }) || 'package').trim().toLowerCase())
core.warning(`Attempting to use ${strategy} version extraction strategy.`)
// Extract the version number using the supplied strategy
let version = core.getInput('root', { required: false })
version = version === null || version.trim().length === 0 ? null : version
switch (strategy) {
case 'docker':
version = (new Dockerfile(root)).version
break
case 'package':
// Extract using the package strategy (this is the default strategy)
version = (new Package(root)).version
break
case 'regex':
version = (new Regex(root, new RegExp(core.getInput('regex_pattern', { required: false }), 'i'))).version
break
default:
core.setFailed(`"${strategy}" is not a recognized tagging strategy. Choose from: 'package' (package.json), 'docker' (uses Dockerfile), or 'regex' (JS-based RegExp).`)
return
}
core.setOutput('version', version)
core.debug(` Detected version ${version}`)
// Configure a tag using the identified version
const tag = new Tag(
core.getInput('tag_prefix', { required: false }),
version,
core.getInput('tag_suffix', { required: false })
)
core.warning(`Attempting to create ${tag.name} tag.`)
core.setOutput('tagrequested', tag.name)
// Check for existance of tag and abort (short circuit) if it already exists.
if (await tag.exists()) {
core.warning(`"${tag.name}" tag already exists.` + os.EOL)
core.setOutput('tagname', '')
return
}
// The tag setter will autocorrect the message if necessary.
tag.message = core.getInput('tag_message', { required: false }).trim()
await tag.push()
core.setOutput('tagname', tag.name)
core.setOutput('tagsha', tag.sha)
core.setOutput('taguri', tag.uri)
core.setOutput('tagmessage', tag.message)
core.setOutput('tagref', tag.ref)
core.setOutput('tagcreated', 'yes')
} catch (error) {
core.warning(error.message)
core.warning(error.stack)
core.setOutput('tagname', '')
core.setOutput('tagsha', '')
core.setOutput('taguri', '')
core.setOutput('tagmessage', '')
core.setOutput('tagref', '')
core.setOutput('tagcreated', 'no')
}
}
run()

26
app/package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "autotag-action",
"version": "1.0.2",
"private": true,
"description": "Automatically create a tag whenever the version changes in package.json",
"main": "lib/main.js",
"scripts": {
"start": "node ./main.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/butlerlogic/action-autotag.git"
},
"keywords": [
"actions",
"node",
"setup"
],
"author": "ButlerLogic",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.2",
"@actions/github": "^2.1.0"
},
"type": "module"
}

View File

@ -1,174 +0,0 @@
const core = require('@actions/core')
const { GitHub, context } = require('@actions/github')
const fs = require('fs')
const path = require('path')
const os = require('os')
async function run() {
try {
core.debug(
` Available environment variables:\n -> ${Object.keys(process.env)
.map(i => i + ' :: ' + process.env[i])
.join('\n -> ')}`
)
const dir = fs
.readdirSync(path.resolve(process.env.GITHUB_WORKSPACE), { withFileTypes: true })
.map(entry => {
return `${entry.isDirectory() ? '> ' : ' - '}${entry.name}`
})
.join('\n')
core.debug(` Working Directory: ${process.env.GITHUB_WORKSPACE}:\n${dir}`)
if (!process.env.hasOwnProperty('GITHUB_TOKEN')) {
if (!process.env.hasOwnProperty('INPUT_GITHUB_TOKEN')) {
core.setFailed('Invalid or missing GITHUB_TOKEN.')
return
}
}
const pkg_root = core.getInput('package_root', { required: false })
const pkgfile = path.join(process.env.GITHUB_WORKSPACE, pkg_root, 'package.json')
if (!fs.existsSync(pkgfile)) {
core.setFailed('package.json does not exist.')
return
}
const pkg = require(pkgfile)
core.setOutput('version', pkg.version)
core.debug(` Detected version ${pkg.version}`)
// Get authenticated GitHub client (Ocktokit): https://github.com/actions/toolkit/tree/master/packages/github#usage
const github = new GitHub(process.env.GITHUB_TOKEN || process.env.INPUT_GITHUB_TOKEN)
// Get owner and repo from context of payload that triggered the action
const { owner, repo } = context.repo
// // Check for existing tag
// const git = new github.GitHub(process.env.INPUT_GITHUB_TOKEN || process.env.GITHUB_TOKEN)
// const owner = process.env.GITHUB_REPOSITORY.split('/').shift()
// const repo = process.env.GITHUB_REPOSITORY.split('/').pop()
let tags
try {
tags = await github.repos.listTags({
owner,
repo,
per_page: 100,
})
} catch (e) {
tags = {
data: [],
}
}
const tagPrefix = core.getInput('tag_prefix', { required: false })
const tagSuffix = core.getInput('tag_suffix', { required: false })
const getTagName = version => {
return `${tagPrefix}${version}${tagSuffix}`
}
// Check for existance of tag and abort (short circuit) if it already exists.
for (let tag of tags.data) {
if (tag.name === getTagName(pkg.version)) {
core.warning(`"${tag.name.trim()}" tag already exists.` + os.EOL)
core.setOutput('tagname', '')
return
}
}
// Create the new tag name
const tagName = getTagName(pkg.version)
let tagMsg = core.getInput('tag_message', { required: false }).trim()
if (tagMsg.length === 0 && tags.data.length > 0) {
try {
latestTag = tags.data.shift()
let changelog = await github.repos.compareCommits({
owner,
repo,
base: latestTag.name,
head: 'master',
})
tagMsg = changelog.data.commits
.map(
commit =>
`**1) ${commit.commit.message}**${
commit.hasOwnProperty('author')
? commit.author.hasOwnProperty('login')
? ' (' + commit.author.login + ')'
: ''
: ''
}\n(SHA: ${commit.sha})\n`
)
.join('\n')
} catch (e) {
core.warning('Failed to generate changelog from commits: ' + e.message + os.EOL)
tagMsg = tagName
}
}
let newTag
try {
tagMsg = tagMsg.trim().length > 0 ? tagMsg : `Version ${pkg.version}`
newTag = await github.git.createTag({
owner,
repo,
tag: tagName,
message: tagMsg,
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 github.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}` + os.EOL)
} 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)
core.setOutput('tagmessage', tagMsg.trim())
core.setOutput('tagref', newReference.data.ref)
}
} catch (error) {
core.warning(error.message)
core.setOutput('tagname', '')
core.setOutput('tagsha', '')
core.setOutput('taguri', '')
core.setOutput('tagmessage', '')
core.setOutput('tagref', '')
}
}
run()

View File

@ -1,25 +1,21 @@
{
"name": "autotag-action",
"version": "1.0.2",
"private": true,
"description": "Automatically create a tag whenever the version changes in package.json",
"main": "lib/main.js",
"name": "action-autotag-test",
"version": "1.1.0",
"description": "This is a test file for the action.",
"main": "index.js",
"dependencies": {},
"devDependencies": {},
"scripts": {
"test": "jest"
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/butlerlogic/action-autotag.git"
"url": "git+https://github.com/ButlerLogic/action-autotag.git"
},
"keywords": [
"actions",
"node",
"setup"
],
"author": "ButlerLogic",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.2",
"@actions/github": "^2.1.0"
}
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/ButlerLogic/action-autotag/issues"
},
"homepage": "https://github.com/ButlerLogic/action-autotag#readme"
}