-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 157f1a8
Showing
10 changed files
with
2,468 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"extends": "@atlassian-partner-engineering", | ||
"rules": { | ||
"no-plusplus": "off" | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
FROM node:10-alpine | ||
|
||
LABEL "name"="Jira Comment" | ||
LABEL "maintainer"="Dima Rudzik <drudzik+githubactions@atlassian.net>" | ||
LABEL "version"="1.0.0" | ||
|
||
LABEL "com.github.actions.name"="Jira Comment" | ||
LABEL "com.github.actions.description"="Add a comment to a Jira issue" | ||
LABEL "com.github.actions.icon"="check-square" | ||
LABEL "com.github.actions.color"="blue" | ||
|
||
RUN apk update && apk add --no-cache ca-certificates | ||
|
||
ADD https://github.com/atlassian/gajira/raw/master/bin/gagas . | ||
ADD . . | ||
RUN npm i | ||
RUN chmod +x /entrypoint.sh | ||
RUN chmod +x /gagas | ||
|
||
ENTRYPOINT ["/entrypoint.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Jira Comment | ||
Add a comment to an issue | ||
|
||
|
||
## Usage | ||
To add comment to an issue you need to specify an issue key and a comment in action args, like: | ||
|
||
`"Hello from GitHub actions" --issue=INC-2` | ||
|
||
You can interpolate fields from GitHub event which triggered the workflow into a comment body. For example, you can specify pusher name in comment body by including `pusher.name` field from [push](https://developer.github.com/v3/activity/events/types/#pushevent) event: | ||
|
||
"{{ pusher.name }} pushed to repository: {{ repository.full_name }}" | ||
|
||
Which will result in comment: | ||
|
||
Codertocat pushed to repository: Codertocat/Hello-World | ||
|
||
---- | ||
## Action Spec | ||
|
||
### Environment variables | ||
- None | ||
|
||
### Arguments | ||
- `--issue` - An issue key to add a comment for | ||
|
||
### Reads fields from config file at $HOME/jira/config.yml | ||
- `issue` | ||
|
||
### Writes fields to config file at $HOME/jira/config.yml | ||
- None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const _ = require('lodash') | ||
const Jira = require('./common/net/Jira') | ||
|
||
module.exports = class { | ||
constructor ({ githubEvent, argv, config }) { | ||
this.Jira = new Jira({ | ||
baseUrl: config.baseUrl, | ||
token: config.token, | ||
email: config.email, | ||
}) | ||
|
||
this.config = config | ||
this.argv = argv | ||
this.githubEvent = githubEvent | ||
} | ||
|
||
async execute () { | ||
const issueId = this.argv.issue | ||
const rawComment = this.argv._.join(' ') | ||
|
||
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g | ||
const compiled = _.template(rawComment) | ||
const interpolatedComment = compiled({ event: this.githubEvent }) | ||
|
||
console.log(`Adding comment to ${issueId}: ${interpolatedComment}`) | ||
await this.Jira.addComment(issueId, { body: interpolatedComment }) | ||
|
||
return {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
const { get } = require('lodash') | ||
|
||
const serviceName = 'jira' | ||
const { format } = require('url') | ||
const client = require('./client')(serviceName) | ||
|
||
class Jira { | ||
constructor ({ baseUrl, token, email }) { | ||
this.baseUrl = baseUrl | ||
this.token = token | ||
this.email = email | ||
} | ||
|
||
async addComment (issueId, data) { | ||
return this.fetch('addComment', { | ||
pathname: `/rest/api/2/issue/${issueId}/comment`, | ||
}, { | ||
method: 'POST', | ||
body: data, | ||
}) | ||
} | ||
|
||
async createIssue (body) { | ||
return this.fetch('createIssue', | ||
{ pathname: '/rest/api/2/issue' }, | ||
{ method: 'POST', body }) | ||
} | ||
|
||
async getIssue (issueId, query = {}) { | ||
const { fields = [], expand = [] } = query | ||
|
||
try { | ||
return this.fetch('getIssue', { | ||
pathname: `/rest/api/2/issue/${issueId}`, | ||
query: { | ||
fields: fields.join(','), | ||
expand: expand.join(','), | ||
}, | ||
}) | ||
} catch (error) { | ||
if (get(error, 'res.status') === 404) { | ||
return | ||
} | ||
|
||
throw error | ||
} | ||
} | ||
|
||
async getIssueTransitions (issueId) { | ||
return this.fetch('getIssueTransitions', { | ||
pathname: `/rest/api/2/issue/${issueId}/transitions`, | ||
}, { | ||
method: 'GET', | ||
}) | ||
} | ||
|
||
async transitionIssue (issueId, data) { | ||
return this.fetch('transitionIssue', { | ||
pathname: `/rest/api/3/issue/${issueId}/transitions`, | ||
}, { | ||
method: 'POST', | ||
body: data, | ||
}) | ||
} | ||
|
||
async fetch (apiMethodName, | ||
{ host, pathname, query }, | ||
{ method, body, headers = {} } = {}) { | ||
const url = format({ | ||
host: host || this.baseUrl, | ||
pathname, | ||
query, | ||
}) | ||
|
||
if (!method) { | ||
method = 'GET' | ||
} | ||
|
||
if (headers['Content-Type'] === undefined) { | ||
headers['Content-Type'] = 'application/json' | ||
} | ||
|
||
if (headers.Authorization === undefined) { | ||
headers.Authorization = `Basic ${Buffer.from(`${this.email}:${this.token}`).toString('base64')}` | ||
} | ||
|
||
// strong check for undefined | ||
// cause body variable can be 'false' boolean value | ||
if (body && headers['Content-Type'] === 'application/json') { | ||
body = JSON.stringify(body) | ||
} | ||
|
||
const state = { | ||
req: { | ||
method, | ||
headers, | ||
body, | ||
url, | ||
}, | ||
} | ||
|
||
try { | ||
await client(state, `${serviceName}:${apiMethodName}`) | ||
} catch (error) { | ||
const fields = { | ||
originError: error, | ||
source: 'jira', | ||
} | ||
|
||
delete state.req.headers | ||
|
||
throw Object.assign( | ||
new Error('Jira API error'), | ||
state, | ||
fields | ||
) | ||
} | ||
|
||
return state.res.body | ||
} | ||
} | ||
|
||
module.exports = Jira |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const fetch = require('node-fetch') | ||
// const moment = require('moment') | ||
|
||
module.exports = serviceName => async (state, apiMethod = 'unknown') => { | ||
// const startTime = moment.now() | ||
|
||
const response = await fetch(state.req.url, state.req) | ||
|
||
state.res = { | ||
headers: response.headers.raw(), | ||
status: response.status, | ||
} | ||
|
||
// const totalTime = moment.now() - startTime | ||
// const tags = { | ||
// api_method: apiMethod, | ||
// method: state.req.method || 'GET', | ||
// response_code: response.status, | ||
// service: serviceName, | ||
// } | ||
|
||
state.res.body = await response.text() | ||
|
||
const isJSON = (response.headers.get('content-type') || '').includes('application/json') | ||
|
||
if (isJSON && state.res.body) { | ||
state.res.body = JSON.parse(state.res.body) | ||
} | ||
|
||
if (!response.ok) { | ||
throw new Error(response.statusText) | ||
} | ||
|
||
return state | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#!/bin/sh | ||
set -eu | ||
|
||
sh -c "node /index.js $*" | ||
|
||
actionSubjectId="comment" | ||
containerId=`echo $GITHUB_REPOSITORY | sha1sum | cut -c1-41` | ||
anonymousId=`echo $GITHUB_ACTOR | sha1sum | cut -c1-41` | ||
|
||
/gagas --container-id="$containerId" --action-subject-id="$actionSubjectId" --anonymous-id="$anonymousId" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
const fs = require('fs') | ||
const YAML = require('yaml') | ||
const yargs = require('yargs') | ||
|
||
const cliConfigPath = `${process.env.HOME}/.jira.d/config.yml` | ||
const configPath = `${process.env.HOME}/jira/config.yml` | ||
const Action = require('./action') | ||
|
||
// eslint-disable-next-line import/no-dynamic-require | ||
const githubEvent = require(process.env.GITHUB_EVENT_PATH) | ||
const config = YAML.parse(fs.readFileSync(configPath, 'utf8')) | ||
|
||
async function exec () { | ||
try { | ||
const result = await new Action({ | ||
githubEvent, | ||
argv: parseArgs(), | ||
config, | ||
}).execute() | ||
|
||
if (result) { | ||
const yamledResult = YAML.stringify(result) | ||
const extendedConfig = Object.assign({}, config, result) | ||
|
||
fs.writeFileSync(configPath, YAML.stringify(extendedConfig)) | ||
|
||
return fs.appendFileSync(cliConfigPath, yamledResult) | ||
} | ||
|
||
console.log('Failed to comment an issue.') | ||
process.exit(78) | ||
} catch (error) { | ||
console.error(error) | ||
process.exit(1) | ||
} | ||
} | ||
|
||
function parseArgs () { | ||
yargs | ||
.option('issue', { | ||
alias: 'i', | ||
describe: 'Provide an issue key to add a comment for', | ||
demandOption: !config.issue, | ||
default: config.issue, | ||
type: 'string', | ||
}) | ||
|
||
yargs | ||
.parserConfiguration({ | ||
'parse-numbers': false, | ||
}) | ||
|
||
return yargs.argv | ||
} | ||
|
||
exec() |
Oops, something went wrong.