forked from everphone-gmbh/github-asana-action
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.js
177 lines (165 loc) · 5.97 KB
/
action.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
const core = require('@actions/core');
const github = require('@actions/github');
const asana = require('asana');
async function moveSection(client, taskId, targets) {
const task = await client.tasks.findById(taskId);
targets.forEach(async target => {
const targetProject = task.projects.find(project => project.name === target.project);
if (!targetProject) {
core.info(`This task does not exist in "${target.project}" project`);
return;
}
let targetSection = await client.sections.findByProject(targetProject.gid)
.then(sections => sections.find(section => section.name === target.section));
if (targetSection) {
await client.sections.addTask(targetSection.gid, { task: taskId });
core.info(`Moved to: ${target.project}/${target.section}`);
} else {
core.error(`Asana section ${target.section} not found.`);
}
});
}
async function findComment(client, taskId, commentId) {
let stories;
try {
const storiesCollection = await client.tasks.stories(taskId);
stories = await storiesCollection.fetch(200);
} catch (error) {
throw error;
}
return stories.find(story => story.text.indexOf(commentId) !== -1);
}
async function addComment(client, taskId, commentId, text, isPinned) {
if(commentId){
text += '\n'+commentId+'\n';
}
try {
const comment = await client.tasks.addComment(taskId, {
text: text,
is_pinned: isPinned,
});
return comment;
} catch (error) {
console.error('rejecting promise', error);
}
}
async function buildClient(asanaPAT) {
return asana.Client.create({
defaultHeaders: { 'asana-enable': 'new-sections,string_ids' },
logAsanaChangeWarnings: false
}).useAccessToken(asanaPAT).authorize();
}
async function action() {
const
ASANA_PAT = core.getInput('asana-pat', {required: true}),
ACTION = core.getInput('action', {required: true}),
TRIGGER_PHRASE = core.getInput('trigger-phrase') || '',
PULL_REQUEST = github.context.payload.pull_request,
V0_REGEX_STRING = `${TRIGGER_PHRASE}(?:\s*)https:\\/\\/app.asana.com\\/(\\d+)\\/(?<v0_project>\\d+)\\/(?<v0_task>\\d+)`,
V1_REGEX_STRING = `${TRIGGER_PHRASE}(?:\s*)https:\\/\\/app.asana.com\\/\\d\\/\\d+\\/project\\/(?<v1_project>\\d+)\\/task\\/(?<v1_task>\\d+)`,
REGEX_STRING = `(${V0_REGEX_STRING})|(${V1_REGEX_STRING})`,
REGEX = new RegExp(REGEX_STRING,'g')
;
console.log('pull_request', PULL_REQUEST);
const client = await buildClient(ASANA_PAT);
if(client === null){
throw new Error('client authorization failed');
}
console.info('looking in body', PULL_REQUEST.body, 'regex', REGEX_STRING);
let foundAsanaTasks = [];
while ((parseAsanaURL = REGEX.exec(PULL_REQUEST.body)) !== null) {
const taskId = parseAsanaURL.groups.v0_task || parseAsanaURL.groups.v1_task;
if (!taskId) {
core.error(`Invalid Asana task URL after the trigger phrase ${TRIGGER_PHRASE}`);
continue;
}
foundAsanaTasks.push(taskId);
}
console.info(`found ${foundAsanaTasks.length} taskIds:`, foundAsanaTasks.join(','));
console.info('calling', ACTION);
switch(ACTION){
case 'assert-link': {
const githubToken = core.getInput('github-token', {required: true});
const linkRequired = core.getInput('link-required', {required: true}) === 'true';
const octokit = new github.GitHub(githubToken);
const statusState = (!linkRequired || foundAsanaTasks.length > 0) ? 'success' : 'error';
core.info(`setting ${statusState} for ${github.context.payload.pull_request.head.sha}`);
octokit.repos.createStatus({
...github.context.repo,
'context': 'asana-link-presence',
'state': statusState,
'description': 'asana link not found',
'sha': github.context.payload.pull_request.head.sha,
});
break;
}
case 'add-comment': {
const commentId = core.getInput('comment-id'),
htmlText = core.getInput('text', {required: true}),
isPinned = core.getInput('is-pinned') === 'true';
const comments = [];
for(const taskId of foundAsanaTasks) {
if(commentId){
const comment = await findComment(client, taskId, commentId);
if(comment){
console.info('found existing comment', comment.gid);
continue;
}
}
const comment = await addComment(client, taskId, commentId, htmlText, isPinned);
comments.push(comment);
};
return comments;
}
case 'remove-comment': {
const commentId = core.getInput('comment-id', {required: true});
const removedCommentIds = [];
for(const taskId of foundAsanaTasks) {
const comment = await findComment(client, taskId, commentId);
if(comment){
console.info("removing comment", comment.gid);
try {
await client.stories.delete(comment.gid);
} catch (error) {
console.error('rejecting promise', error);
}
removedCommentIds.push(comment.gid);
}
}
return removedCommentIds;
}
case 'complete-task': {
const isComplete = core.getInput('is-complete') === 'true';
const taskIds = [];
for(const taskId of foundAsanaTasks) {
console.info("marking task", taskId, isComplete ? 'complete' : 'incomplete');
try {
await client.tasks.update(taskId, {
completed: isComplete
});
} catch (error) {
console.error('rejecting promise', error);
}
taskIds.push(taskId);
};
return taskIds;
}
case 'move-section': {
const targetJSON = core.getInput('targets', {required: true});
const targets = JSON.parse(targetJSON);
const movedTasks = [];
for(const taskId of foundAsanaTasks) {
await moveSection(client, taskId, targets);
movedTasks.push(taskId);
}
return movedTasks;
}
default:
core.setFailed("unexpected action ${ACTION}");
}
}
module.exports = {
action,
default: action,
buildClient: buildClient
};