diff --git a/README.md b/README.md index a2f8073..66c5b67 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,6 @@ Run a container. ```bash docker run --rm -p 3000:3000 \ -e SLACK_WEBHOOK=https://hooks.slack.com/... \ - -e SLACK_USERNAME=JIRA \ - -e SLACK_ICON_URL=https://lh3.googleusercontent.com/GkgChJMixx9JAmoUi1majtfpjg1Ra86gZR0GCehJfVcOGQI7Ict_TVafXCtJniVn3R0 \ int128/jira-to-slack ``` @@ -39,7 +37,9 @@ slack: ## Slack icon emoji # iconEmoji: ":speech_baloon:" ## Slack icon image URL - #iconImageURL: https://lh3.googleusercontent.com/GkgChJMixx9JAmoUi1majtfpjg1Ra86gZR0GCehJfVcOGQI7Ict_TVafXCtJniVn3R0 + # iconImageURL: https://lh3.googleusercontent.com/GkgChJMixx9JAmoUi1majtfpjg1Ra86gZR0GCehJfVcOGQI7Ict_TVafXCtJniVn3R0 + ## Slack API dialect + # dialect: slack ``` ```bash @@ -58,12 +58,13 @@ If both the JIRA server and jira-to-slack are running in the same namespace, poi You can set the BOT username and icon in the Slack webhook settings. Instead you can set the following environment variables to the container: -Name | Value | Example ------|-------|-------- +Name | Value | Example value +-----|-------|-------------- `SLACK_WEBHOOK` | Slack webhook URL (Required) | `https://hooks.slack.com/...` `SLACK_USERNAME` | Username of the BOT (Optional) | `JIRA` `SLACK_ICON_EMOJI` | Icon emoji of the BOT (Optional) | `:speech_baloon:` `SLACK_ICON_URL` | Icon URL of the BOT (Optional) | `http://.../jira.png` +`SLACK_API_DIALECT` | Slack API dialect, defaults to `slack` | `slack` or `mattermost` ### JIRA diff --git a/charts/jira-to-slack/templates/deployment.yaml b/charts/jira-to-slack/templates/deployment.yaml index f018464..ef5b66d 100644 --- a/charts/jira-to-slack/templates/deployment.yaml +++ b/charts/jira-to-slack/templates/deployment.yaml @@ -28,6 +28,8 @@ spec: value: {{ .Values.slack.iconEmoji }} - name: SLACK_ICON_URL value: {{ .Values.slack.iconImageURL }} + - name: SLACK_API_DIALECT + value: {{ .Values.slack.dialect }} ports: - containerPort: {{ .Values.service.internalPort }} livenessProbe: diff --git a/charts/jira-to-slack/values.yaml b/charts/jira-to-slack/values.yaml index 1a33c9a..ef50128 100644 --- a/charts/jira-to-slack/values.yaml +++ b/charts/jira-to-slack/values.yaml @@ -9,6 +9,8 @@ slack: {} # iconEmoji: ":speech_baloon:" ## Slack icon image URL # iconImageURL: https://lh3.googleusercontent.com/GkgChJMixx9JAmoUi1majtfpjg1Ra86gZR0GCehJfVcOGQI7Ict_TVafXCtJniVn3R0 + ## Slack API dialect + # dialect: slack replicaCount: 1 image: diff --git a/src/webhook_handler.js b/src/webhook_handler.js index 2707e33..70686a5 100644 --- a/src/webhook_handler.js +++ b/src/webhook_handler.js @@ -8,20 +8,23 @@ const slack = new Slack( iconUrl: process.env.SLACK_ICON_URL, }); +const dialect = process.env.SLACK_API_DIALECT; + module.exports = async req => { if (typeof req !== 'object') { throw new TypeError(`Request must be a valid object: ${req}`); } - const message = new WebhookMessage(req.body); + const message = new WebhookMessage(req.body, { dialect }); if (message.isValid()) { return await slack.send({ + // Use text instead of pretext in attachment, + // due to the issue that @username in pretext is not linked on Mattermost. + text: message.getPretext(), attachments: [ { title: message.getTitle(), title_link: message.getTitleLink(), - pretext: message.getPretext(), text: message.getText(), - footer: message.getFooter(), ts: message.getUpdatedTimestamp(), }, ], diff --git a/src/webhook_message.js b/src/webhook_message.js index cd1afdc..973e4ef 100644 --- a/src/webhook_message.js +++ b/src/webhook_message.js @@ -1,11 +1,16 @@ const JIRA_FIELDS_TO_NOTIFY_UPDATE = ['summary', 'description', 'assignee']; module.exports = class WebhookMessage { - constructor(body) { + /** + * Constructor. + * @param {object} body JSON payload + */ + constructor(body, { dialect }) { if (typeof body !== 'object') { throw new TypeError(`Request body must be a valid object: ${body}`); } this._body = body; + this._dialect = dialect; } /** @@ -50,19 +55,29 @@ module.exports = class WebhookMessage { * @returns {string} pretext of the message (who) */ getPretext() { - const { webhookEvent, user, comment } = this._body; + const { webhookEvent, user, comment, issue } = this._body; + const username = this._formatUsername(user); + let verb; switch (webhookEvent) { case 'jira:issue_updated': if (comment) { - return `<@${user.name}> commented:`; + verb = 'commented to'; } else { - return `<@${user.name}> updated:`; + verb = 'updated'; } + break; case 'jira:issue_created': - return `<@${user.name}> created:`; + verb = 'created'; + break; case 'jira:issue_deleted': - return `<@${user.name}> deleted:`; + verb = 'deleted'; + break; + } + let assignee = ''; + if (issue.fields.assignee) { + assignee = `(assigned to ${this._formatUsername(issue.fields.assignee)}>)`; } + return `${username} ${verb} the issue: ${assignee}` } /** @@ -84,15 +99,23 @@ module.exports = class WebhookMessage { } } - getFooter() { - const { issue } = this._body; - if (issue.fields.assignee) { - return `Assigned to <@${issue.fields.assignee.name}>`; + getUpdatedTimestamp() { + const { timestamp } = this._body; + if (typeof timestamp === 'number') { + return timestamp / 1000; } } - getUpdatedTimestamp() { - const { timestamp } = this._body; - return parseInt(timestamp) / 1000; + /** + * Format the username. + * @param {object} user user object that has user.name + */ + _formatUsername(user) { + switch (this._dialect) { + case 'mattermost': + return `@${user.name}`; + default: + return `<@${user.name}>`; + } } }