Skip to content

Instantly share code, notes, and snippets.

@robfe
Created February 18, 2019 07:44
Show Gist options
  • Save robfe/720b37c72be1038cda989128aec2e11e to your computer and use it in GitHub Desktop.
Save robfe/720b37c72be1038cda989128aec2e11e to your computer and use it in GitHub Desktop.
// Thanks to Michael Rush for the original version of this rule (https://software-development.dfstudio.com/youtracks-new-javascript-workflows-make-slack-integration-a-breeze-d3275605d565)
// IMPORTANT: Use a valid Incoming Webhook from Slack. To get one, go to https://my.slack.com/services/new/incoming-webhook/
var SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services';
var entities = require('@jetbrains/youtrack-scripting-api/entities');
var http = require('@jetbrains/youtrack-scripting-api/http');
var workflow = require('@jetbrains/youtrack-scripting-api/workflow');
function formatIssueAsAttachment(i) {
var tags = '';
i.tags.forEach(function(t) {
tags += ' `#' + t.name + '`';
});
return {
"title": i.id + ' ' + i.summary,
"title_link":i.url,
"text":tags.trim(),
"footer":'(' + i.fields.State.name + ' / ' + i.fields.Priority.name + ' / ' + i.fields.Type.name + ' ' +typeEmoji(i.fields.Type.name)+ ')',
"color":i.fields.Priority.backgroundColor
};
}
function formatIssueShort(i) {
return '<' + i.url + "|" + i.id + ' ' + i.summary + '>';
}
function typeEmoji(type) {
switch (type) {
case 'Epic': return 'πŸ“š';
case 'Story': return 'πŸ“–';
case 'Feature': return 'πŸ’»';
case 'Task': return 'πŸ“‹';
case 'Bug': return 'πŸ›';
case 'Tech Improvement': return 'πŸ’…';
}
return '';
}
function escapeForSlack(s){
return s.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
exports.rule = entities.Issue.onChange({
title: 'πŸ‘» Send notification to slack when an issue is reported, resolved, or reopened',
guard: function(ctx) {
return ctx.issue.becomesReported ||
ctx.issue.becomesResolved ||
ctx.issue.becomesUnresolved ||
!ctx.issue.comments.added.isEmpty() ||
ctx.issue.fields.becomes(ctx.State, ctx.State.InProgress);
},
action: function(ctx) {
var issue = ctx.issue;
var message = ctx.currentUser.fullName;
if (issue.becomesReported) {
message += " ✨ *Created*: ";
} else if (issue.becomesResolved) {
message += " βœ” *Resolved*: ";
} else if (ctx.issue.fields.becomes(ctx.State, ctx.State.InProgress)) {
message += " πŸ”œ *Started*: ";
} else if (issue.becomesUnresolved) {
message += " 🧟 *Reopened*: ";
} else{
message += " πŸ’¬ *Commented*: ";
}
var payload = {
"text": message,
"attachments": [formatIssueAsAttachment(issue)],
};
ctx.issue.comments.added.forEach(function(comment){
payload.attachments.push({
"title": "Comment",
"title_link":comment.url,
"text": escapeForSlack(comment.text),
"color":"#999999"
});
});
function visitParents(i, d) {
if (d > 10) return;
i.links['subtask of'].forEach(function(p) {
var indent = 'parent: ';
for(var x = 0; x < d; x++ ){
indent = (x === 0 ? 'grand' : 'great ')+indent;
}
indent = indent.replace(/^./, function(x){return x.toUpperCase();});
payload.attachments.push({
"text": indent + formatIssueShort(p),
"color": p.fields.Priority.backgroundColor || "#edb431",
});
visitParents(p, d + 1);
});
}
visitParents(issue, 0);
//workflow.message('πŸ‘» slacking! ' + JSON.stringify(payload));
var connection = new http.Connection(SLACK_WEBHOOK_URL, null, 2000);
var response = connection.postSync('', null, JSON.stringify(payload));
if (!response.isSuccess) {
console.warn('Failed to post notification to Slack. Details: ' + response.toString());
}
},
requirements: {
Priority: {
type: entities.EnumField.fieldType
},
State: {
type: entities.State.fieldType,
InProgress: {
name: 'In Progress'
}
},
Type: {
type: entities.EnumField.fieldType,
name: 'Priority',
},
Assignee: {
type: entities.User.fieldType,
multi: true
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment