feat: finish tasks on issue closing

also sorted some code for better readability
This commit is contained in:
Matyáš Caras 2024-07-30 17:20:00 +02:00
parent ef8d06ba0e
commit b5ab2d9b0c
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 2A3175F98820C5C6
3 changed files with 85 additions and 27 deletions

View file

@ -0,0 +1,15 @@
{
"action":"opened",
"issue":{
"body":"Testing issue through Act",
"number":"123",
"title":"GitHub Action Test",
"url":"https://github.com/hernikplays/freelo-action",
"user":{
"login":"hernikplays"
},
"assignee":{
"login":"hernikplays"
}
}
}

View file

@ -26,15 +26,40 @@ const comment = context.payload.comment;
// constants // constants
const apiEndpoint = "https://api.freelo.io/v1"; const apiEndpoint = "https://api.freelo.io/v1";
const defaultHeaders = { const defaultOptions = {
auth: {
username: email,
password: apiKey,
},
headers: {
"User-Agent": "Freelo GitHub Action/1.0.0", "User-Agent": "Freelo GitHub Action/1.0.0",
"Content-Type": "application/json", "Content-Type": "application/json",
},
}; };
const sanitizeOptions: sanitize.IOptions = { const sanitizeOptions: sanitize.IOptions = {
allowedTags: ["a", "p", "i", "b", "strong"], allowedTags: ["a", "p", "i", "b", "strong"],
allowedAttributes: false, allowedAttributes: false,
}; };
// Load GitHub:Freelo pairing if available
const userPairing: { [key: string]: string } = {};
try {
for (const u of (
await readFile("./.github/freelo.txt", { encoding: "utf-8" })
).split("\n")) {
const p = u.split(":");
userPairing[p[0]] = p[1];
}
} catch (e) {
console.log("No valid freelo.txt found in .github folder, skipping");
}
function freeloMention(username: string): string {
return Object.keys(userPairing).includes(username)
? `<div><span data-freelo-mention="1" data-freelo-user-id="${userPairing[username]}">@${username}</span></div>`
: `<a href="https://github.com/${username}">${username}</a>`;
}
try { try {
if (!action) { if (!action) {
throw new Error("No action was passed"); throw new Error("No action was passed");
@ -55,28 +80,15 @@ try {
throw new Error("Either task-id or tasklist-id needs to be set!"); throw new Error("Either task-id or tasklist-id needs to be set!");
} }
// Load GitHub:Freelo pairing if available
let userPairing: string[] | undefined;
try {
userPairing = (await readFile("./.github/freelo.txt",{encoding:"utf-8"})).split("\n");
} catch (e) {
console.log("No freelo.txt found in .github folder, skipping");
}
if (tasklistId) { if (tasklistId) {
switch (action) { switch (action) {
case "opened": { case "opened": {
// New issue has been created, create a task in tasklist // New issue has been created, create a task in tasklist
const author =
userPairing &&
userPairing.filter((u) => u.includes(issue.user.login)).length > 0
? `<div><span data-freelo-mention="1" data-freelo-user-id="${userPairing.filter((u) => u.includes(issue.user.login))[0].split(":")[1]}">@${issue.user.login}</span></div>`
: `<a href="https://github.com/${issue.user.login}">${issue.user.login}</a>`;
console.log(userPairing?.filter((u) => u.includes(issue.user.login)).length)
const taskComment = ` const taskComment = `
Created by: ${author}<br> Created by: ${freeloMention(issue.user.login)}<br>
Description: ${sanitize(issue.body ?? "None", sanitizeOptions)}<br> Description: ${sanitize(issue.body ?? "None", sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br> GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
Assigned to: ${issue.assignee ? `${freeloMention(issue.assignee.login)}` : "Nobody"}<br>
<i>(This action was performed automatically)</i> <i>(This action was performed automatically)</i>
`; `;
@ -85,18 +97,12 @@ try {
comment: { comment: {
content: taskComment, content: taskComment,
}, },
}; // TODO: assignee };
const res = await axios.post( const res = await axios.post(
`${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks`, `${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks`,
taskContent, taskContent,
{ defaultOptions,
headers: defaultHeaders,
auth: {
username: email,
password: apiKey,
},
},
); );
// handle potential error response // handle potential error response
@ -117,8 +123,45 @@ try {
case "edited": case "edited":
break; break;
case "closed": case "closed": {
// Get comments and find the related Freelo task ID
const comment = (
await octokit.rest.issues.listComments({
owner: context.payload.repository?.owner.login ?? "",
repo: context.payload.repository?.name ?? "",
issue_number: issue.number,
mediaType: {
format: "html",
},
})
).data.filter(
(i) => i.user?.login === "github-actions" && i.user.type === "Bot",
);
if (comment.length === 0) break; // not a Freelo task, skip
console.log(comment.length);
console.log(comment[0].body_html);
// Finish task in Freelo
const taskId = /https:\/\/app.freelo.io\/task\/(\d+)/.exec(
comment[0].body_html ?? "",
);
if (!taskId || taskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break; break;
}
const res = await axios.post(
`${apiEndpoint}/task/${taskId[1]}`,
null,
defaultOptions,
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "reopened": case "reopened":
break; break;
case "assigned": case "assigned":