-
Notifications
You must be signed in to change notification settings - Fork 97
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 af4968d
Showing
10 changed files
with
6,349 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 Find" | ||
LABEL "maintainer"="Dima Rudzik <[email protected]>" | ||
LABEL "version"="1.0.0" | ||
|
||
LABEL "com.github.actions.name"="Jira Find" | ||
LABEL "com.github.actions.description"="Find an issue inside event" | ||
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,24 @@ | ||
# Jira Find Issue Key | ||
Extract issue key from string | ||
|
||
## Usage | ||
|
||
TBD | ||
|
||
---- | ||
## Action Spec: | ||
|
||
### Environment variables | ||
- None | ||
|
||
### Arguments | ||
- None | ||
|
||
### Reads fields from config file at $HOME/jira/config.yml | ||
- None | ||
|
||
### Writes fields to config file at $HOME/jira/config.yml | ||
- `issue` - a key of a found issue | ||
|
||
### Writes fields to CLI config file at $HOME/.jira.d/config.yml | ||
- `issue` - a key of a found issue |
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,50 @@ | ||
const _ = require('lodash') | ||
const Jira = require('./common/net/Jira') | ||
|
||
const issueIdRegEx = /([a-zA-Z0-9]+-[0-9]+)/g | ||
|
||
const eventTemplates = { | ||
branch: '{{event.ref}}', | ||
commits: "{{event.commits.map(c=>c.message).join(' ')}}", | ||
} | ||
|
||
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 template = eventTemplates[this.argv.from] || this.argv._.join(' ') | ||
const extractString = this.preprocessString(template) | ||
const match = extractString.match(issueIdRegEx) | ||
|
||
if (!match) { | ||
console.log(`String "${extractString}" does not contain issueKeys`) | ||
|
||
return | ||
} | ||
|
||
for (const issueKey of match) { | ||
const issue = await this.Jira.getIssue(issueKey) | ||
|
||
if (issue) { | ||
return { issue: issue.key } | ||
} | ||
} | ||
} | ||
|
||
preprocessString (str) { | ||
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g | ||
const tmpl = _.template(str) | ||
|
||
return tmpl({ event: this.githubEvent }) | ||
} | ||
} |
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,116 @@ | ||
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 createIssue (body) { | ||
return this.fetch('createIssue', | ||
{ pathname: '/rest/api/2/issue' }, | ||
{ method: 'POST', body }) | ||
} | ||
|
||
async getIssue (issueId, query = {}) { | ||
const { fields = [], expand = [] } = query | ||
|
||
try { | ||
const res = await this.fetch('getIssue', { | ||
pathname: `/rest/api/2/issue/${issueId}`, | ||
query: { | ||
fields: fields.join(','), | ||
expand: expand.join(','), | ||
}, | ||
}) | ||
|
||
return res | ||
} 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="find" | ||
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,70 @@ | ||
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) { | ||
console.log(`Detected issueKey: ${result.issue}`) | ||
console.log(`Saving ${result.issue} to ${cliConfigPath}`) | ||
console.log(`Saving ${result.issue} to ${configPath}`) | ||
|
||
const yamledResult = YAML.stringify(result) | ||
const extendedConfig = Object.assign({}, config, result) | ||
|
||
fs.writeFileSync(configPath, YAML.stringify(extendedConfig)) | ||
|
||
return fs.appendFileSync(cliConfigPath, yamledResult) | ||
} | ||
|
||
console.log('No issueKeys found.') | ||
process.exit(78) | ||
} catch (error) { | ||
console.error(error) | ||
process.exit(1) | ||
} | ||
} | ||
|
||
function parseArgs () { | ||
yargs | ||
.option('event', { | ||
alias: 'e', | ||
describe: 'Provide jsonpath for the GitHub event to extract issue from', | ||
default: config.event, | ||
type: 'string', | ||
}) | ||
.option('string', { | ||
alias: 's', | ||
describe: 'Provide a string to extract issue key from', | ||
default: config.string, | ||
type: 'string', | ||
}) | ||
.option('from', { | ||
describe: 'Find from predefined place', | ||
type: 'string', | ||
choices: ['branch', 'commits'], | ||
}) | ||
|
||
yargs | ||
.parserConfiguration({ | ||
'parse-numbers': false, | ||
}) | ||
|
||
return yargs.argv | ||
} | ||
|
||
exec() |
Oops, something went wrong.