feat: complete the other actions

This commit is contained in:
Matyáš Caras 2024-07-30 19:19:20 +02:00
parent 398f274b40
commit 9a098134dd
Signed by: hernik
GPG key ID: 2A3175F98820C5C6
4 changed files with 607 additions and 222 deletions

238
dist/index.js vendored
View file

@ -42183,6 +42183,7 @@ var require_sanitize_html = __commonJS((exports, module) => {
// src/index.ts
var core = __toESM(require_core(), 1);
var github = __toESM(require_github(), 1);
import {readFile} from "node:fs/promises";
// node_modules/axios/lib/helpers/bind.js
function bind(fn, thisArg) {
@ -45309,10 +45310,21 @@ var axios_default = axios;
// src/index.ts
var import_sanitize_html = __toESM(require_sanitize_html(), 1);
import {readFile} from "node:fs/promises";
var freeloMention = function(username) {
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>`;
};
async function freeloId(issue_number) {
const comment = (await octokit.rest.issues.listComments({
...github.context.repo,
issue_number,
mediaType: {
format: "html"
}
})).data.filter((i) => i.user?.type === "Bot" && i.user.login === "github-actions[bot]");
if (comment.length === 0)
return;
return /https:\/\/app.freelo.io\/task\/(\d+)/.exec(comment[0].body_html ?? "")?.[1];
}
var email = core.getInput("email");
var apiKey = core.getInput("api-key");
var projectId = core.getInput("project-id");
@ -45358,30 +45370,34 @@ try {
if (!email || !apiKey || !projectId) {
throw new Error("You are missing a required parameter. Check the documentation for details.");
}
if (issue) {
if (issue.pull_request) {
throw new Error("Pull requests are not yet supported");
}
if (!comment && issue) {
if (!tasklistId && !taskId) {
throw new Error("Either task-id or tasklist-id needs to be set!");
}
if (tasklistId) {
switch (action) {
case "opened": {
const taskComment = `
Created by: ${freeloMention(issue.user.login)}<br>
Description: ${import_sanitize_html.default(issue.body ?? "None", sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
GitHub issue: <a href="${issue.pull_request ? issue.pull_request.url : issue.url}">#${issue.number}</a><br>
Assigned to: ${issue.assignee ? `${freeloMention(issue.assignee.login)}` : "Nobody"}<br>
${issue.pull_request ? "<b>This is a pull request<b><br>" : ""}
<i>(This action was performed automatically)</i>
`;
const labels = [];
if (issue.labels) {
for (const label of issue.labels) {
labels.push({ name: label.name, color: `#${label.color}` });
}
}
const taskContent = {
name: issue.title,
comment: {
content: taskComment
}
},
labels
};
const res = await axios_default.post(`${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks`, taskContent, defaultOptions);
const res = await axios_default.post(!taskId ? `${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks` : `${apiEndpoint}/task/${taskId}/subtasks`, taskContent, defaultOptions);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
@ -45393,24 +45409,54 @@ try {
});
break;
}
case "edited":
break;
case "closed": {
const comment2 = (await octokit.rest.issues.listComments({
...github.context.repo,
issue_number: issue.number,
mediaType: {
format: "html"
}
})).data.filter((i) => i.user?.type === "Bot" && i.user.login === "github-actions[bot]");
if (comment2.length === 0)
break;
const taskId2 = /https:\/\/app.freelo.io\/task\/(\d+)/.exec(comment2[0].body_html ?? "");
if (!taskId2 || taskId2.length === 0) {
case "edited": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const res = await axios_default.post(`${apiEndpoint}/task/${taskId2[1]}/finish`, null, defaultOptions);
const titleRes = await axios_default.post(`${apiEndpoint}/task/${currentTaskId[1]}`, {
name: issue.title
}, defaultOptions);
if (titleRes.status > 399) {
console.error(titleRes.data);
throw new Error("Got an error response from Freelo API");
}
const taskComment = `
Created by: ${freeloMention(issue.user.login)}<br>
Description: ${import_sanitize_html.default(issue.body ?? "None", sanitizeOptions)}<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>
`;
const labels = [];
if (issue.labels) {
for (const label of issue.labels) {
labels.push({ name: label.name, color: `#${label.color}` });
}
}
const labelRes = await axios_default.post(`${apiEndpoint}/task-labels/add-to-task/${currentTaskId}`, { labels }, defaultOptions);
if (labelRes.status > 399) {
console.error(labelRes.data);
throw new Error("Got an error response from Freelo API");
}
const bodyRes = await axios_default.post(`${apiEndpoint}/task/${currentTaskId[1]}/description`, {
comment: { content: taskComment },
labels
}, defaultOptions);
if (bodyRes.status > 399) {
console.error(bodyRes.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "closed": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("No Freelo task ID identified");
break;
}
const res = await axios_default.post(`${apiEndpoint}/task/${currentTaskId[1]}/finish`, null, defaultOptions);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
@ -45418,38 +45464,148 @@ try {
break;
}
case "reopened": {
const comment2 = (await octokit.rest.issues.listComments({
...github.context.repo,
issue_number: issue.number,
mediaType: {
format: "html"
}
})).data.filter((i) => i.user?.type === "Bot" && i.user.login === "github-actions[bot]");
if (comment2.length === 0)
break;
const taskId2 = /https:\/\/app.freelo.io\/task\/(\d+)/.exec(comment2[0].body_html ?? "");
if (!taskId2 || taskId2.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
const currentTaskid = await freeloId(issue.number);
if (!currentTaskid || currentTaskid.length === 0) {
console.log("No Freelo task ID identified");
break;
}
const res = await axios_default.post(`${apiEndpoint}/task/${taskId2[1]}/activate`, null, defaultOptions);
const res = await axios_default.post(`${apiEndpoint}/task/${currentTaskid[1]}/activate`, null, defaultOptions);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "assigned":
case "assigned": {
if (!github.context.payload.assignee || !userPairing[github.context.payload.assignee.login])
break;
case "unassigned":
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const res = await axios_default.post(`${apiEndpoint}/task/${currentTaskId[1]}`, {
worker: userPairing[github.context.payload.assignee.login]
}, defaultOptions);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "unassigned": {
if (!github.context.payload.assignee || !userPairing[github.context.payload.assignee.login])
break;
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const checkAssignee = await axios_default.get(`${apiEndpoint}/task/${currentTaskId}`, defaultOptions);
if (checkAssignee.status > 399) {
console.error(checkAssignee.data);
throw new Error("Got an error response from Freelo API");
}
if (!checkAssignee.data.worker || checkAssignee.data.worker.id !== userPairing[github.context.payload.assignee.login]) {
break;
}
const res = await axios_default.post(`${apiEndpoint}/task/${currentTaskId[1]}`, {
worker: null
}, defaultOptions);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
default:
throw new Error("Unknown action passed");
}
} else if (comment && issue) {
switch (action) {
case "created": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const taskComment = `
Comment <a href="${comment.url}">${comment.id}</a> by: ${freeloMention(comment.user.login)}<br>
${import_sanitize_html.default(comment.body, sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
<i>(This action was performed automatically)</i>
`;
const res = await axios_default.post(`${apiEndpoint}/task/${currentTaskId}/comments`, {
content: taskComment
});
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Created comment ${res.data.id}`);
break;
}
case "deleted": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const getTaskComments = await axios_default.get(`${apiEndpoint}/task/${currentTaskId}`, defaultOptions);
if (getTaskComments.status > 399) {
console.error(getTaskComments.data);
throw new Error("Got an error response from Freelo API");
}
const findComment = getTaskComments.data.comments.filter((c) => />(\d+)</gm.test(c.content));
if (findComment.length === 0) {
console.log("Comment found, but no GitHub comment ID identified");
break;
}
const res = await axios_default.delete(`${apiEndpoint}/comment/${findComment[0].id}`);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Deleted comment ${findComment[0].id}`);
break;
}
case "edited": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const getTaskComments = await axios_default.get(`${apiEndpoint}/task/${currentTaskId}`, defaultOptions);
if (getTaskComments.status > 399) {
console.error(getTaskComments.data);
throw new Error("Got an error response from Freelo API");
}
const findComment = getTaskComments.data.comments.filter((c) => />(\d+)</gm.test(c.content));
if (findComment.length === 0) {
console.log("Comment found, but no GitHub comment ID identified");
break;
}
const taskComment = `
Comment <a href="${comment.url}">${comment.id}</a> by: ${freeloMention(comment.user.login)}<br>
${import_sanitize_html.default(comment.body, sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
<i>(This action was performed automatically)</i>
`;
const res = await axios_default.post(`${apiEndpoint}/comment/${findComment[0].id}`, {
content: taskComment
});
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Edited comment ${findComment[0].id}`);
break;
}
default:
break;
}
} else if (comment) {
} else {
throw new Error("You are running this action through an unsupported trigger");
console.error("You are running this through an unsupported trigger!");
}
} catch (error) {
core.setFailed(error?.message ?? "Unknown error");

View file

@ -1,9 +1,9 @@
import { readFile } from "node:fs/promises";
import { getInput, setFailed } from "@actions/core";
import { context, getOctokit } from "@actions/github";
import axios from "axios";
import sanitize from "sanitize-html";
import type { NewTask } from "./freelo";
import { readFile } from "node:fs/promises";
import type { Label, NewTask } from "./freelo";
// user input
const email = getInput("email");
@ -60,6 +60,26 @@ function freeloMention(username: string): string {
: `<a href="https://github.com/${username}">${username}</a>`;
}
async function freeloId(issue_number: number): Promise<string | undefined> {
const comment = (
await octokit.rest.issues.listComments({
...context.repo,
issue_number: issue_number,
mediaType: {
format: "html",
},
})
).data.filter(
(i) => i.user?.type === "Bot" && i.user.login === "github-actions[bot]",
);
if (comment.length === 0) return undefined; // not a Freelo task, skip
// Finish task in Freelo
return /https:\/\/app.freelo.io\/task\/(\d+)/.exec(
comment[0].body_html ?? "",
)?.[1];
}
try {
if (!action) {
// TODO: Is run manually, check all issues
@ -70,38 +90,46 @@ try {
"You are missing a required parameter. Check the documentation for details.",
);
}
if (issue) {
if (!comment && issue) {
// is a created/edited/closed etc. issue
if (issue.pull_request) {
throw new Error("Pull requests are not yet supported");
}
// depending on whether taskId or tasklistId is set, do something
if (!tasklistId && !taskId) {
throw new Error("Either task-id or tasklist-id needs to be set!");
}
if (tasklistId) {
// Use a task inside of a tasklist
switch (action) {
case "opened": {
// New issue has been created, create a task in tasklist
const taskComment = `
Created by: ${freeloMention(issue.user.login)}<br>
Description: ${sanitize(issue.body ?? "None", sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
GitHub issue: <a href="${issue.pull_request ? issue.pull_request.url : issue.url}">#${issue.number}</a><br>
Assigned to: ${issue.assignee ? `${freeloMention(issue.assignee.login)}` : "Nobody"}<br>
${issue.pull_request ? "<b>This is a pull request<b><br>" : ""}
<i>(This action was performed automatically)</i>
`;
const labels: Label[] = [];
if (issue.labels) {
for (const label of issue.labels) {
labels.push({ name: label.name, color: `#${label.color}` });
}
}
const taskContent: NewTask = {
name: issue.title,
comment: {
content: taskComment,
},
labels,
};
const res = await axios.post(
`${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks`,
!taskId
? `${apiEndpoint}/project/${projectId}/tasklist/${tasklistId}/tasks`
: `${apiEndpoint}/task/${taskId}/subtasks`,
taskContent,
defaultOptions,
);
@ -121,34 +149,76 @@ try {
break;
}
case "edited":
break;
case "closed": {
// Get comments and find the related Freelo task ID
const comment = (
await octokit.rest.issues.listComments({
...context.repo,
issue_number: issue.number,
mediaType: {
format: "html",
},
})
).data.filter(
(i) =>
i.user?.type === "Bot" && i.user.login === "github-actions[bot]",
);
if (comment.length === 0) break; // not a Freelo task, skip
// Finish task in Freelo
const taskId = /https:\/\/app.freelo.io\/task\/(\d+)/.exec(
comment[0].body_html ?? "",
);
if (!taskId || taskId.length === 0) {
case "edited": {
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
// Edit task title
const titleRes = await axios.post(
`${apiEndpoint}/task/${currentTaskId[1]}`,
{
name: issue.title,
},
defaultOptions,
);
if (titleRes.status > 399) {
console.error(titleRes.data);
throw new Error("Got an error response from Freelo API");
}
const taskComment = `
Created by: ${freeloMention(issue.user.login)}<br>
Description: ${sanitize(issue.body ?? "None", sanitizeOptions)}<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>
`;
const labels: Label[] = [];
if (issue.labels) {
for (const label of issue.labels) {
labels.push({ name: label.name, color: `#${label.color}` });
}
}
// Edit task labels
const labelRes = await axios.post(
`${apiEndpoint}/task-labels/add-to-task/${currentTaskId}`,
{ labels },
defaultOptions,
);
if (labelRes.status > 399) {
console.error(labelRes.data);
throw new Error("Got an error response from Freelo API");
}
// Edit task body
const bodyRes = await axios.post(
`${apiEndpoint}/task/${currentTaskId[1]}/description`,
{
comment: { content: taskComment },
labels,
},
defaultOptions,
);
if (bodyRes.status > 399) {
console.error(bodyRes.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "closed": {
// Issue closed, finish task
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("No Freelo task ID identified");
break;
}
const res = await axios.post(
`${apiEndpoint}/task/${taskId[1]}/finish`,
`${apiEndpoint}/task/${currentTaskId[1]}/finish`,
null,
defaultOptions,
);
@ -160,33 +230,16 @@ try {
break;
}
case "reopened": {
// Get comments and find the related Freelo task ID
const comment = (
await octokit.rest.issues.listComments({
...context.repo,
issue_number: issue.number,
mediaType: {
format: "html",
},
})
).data.filter(
(i) =>
i.user?.type === "Bot" && i.user.login === "github-actions[bot]",
);
if (comment.length === 0) break; // not a Freelo task, skip
// 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");
// Issue re-opened, activate task
const currentTaskid = await freeloId(issue.number);
if (!currentTaskid || currentTaskid.length === 0) {
console.log("No Freelo task ID identified");
break;
}
// Reactivate
const res = await axios.post(
`${apiEndpoint}/task/${taskId[1]}/activate`,
`${apiEndpoint}/task/${currentTaskid[1]}/activate`,
null,
defaultOptions,
);
@ -197,21 +250,197 @@ try {
}
break;
}
case "assigned":
case "assigned": {
// New assignee, check if mapping exists and update in Freelo
if (
!context.payload.assignee ||
!userPairing[context.payload.assignee.login]
)
break;
case "unassigned":
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const res = await axios.post(
`${apiEndpoint}/task/${currentTaskId[1]}`,
{
worker: userPairing[context.payload.assignee.login],
},
defaultOptions,
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
case "unassigned": {
// Unassigned, check if user has Freelo pairing, is currently assigned to the Freelo task and unassign them
if (
!context.payload.assignee ||
!userPairing[context.payload.assignee.login]
)
break;
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const checkAssignee = await axios.get(
`${apiEndpoint}/task/${currentTaskId}`,
defaultOptions,
);
if (checkAssignee.status > 399) {
console.error(checkAssignee.data);
throw new Error("Got an error response from Freelo API");
}
if (
!checkAssignee.data.worker ||
checkAssignee.data.worker.id !==
userPairing[context.payload.assignee.login]
) {
// if the current user is not assigned, ignore
break;
}
const res = await axios.post(
`${apiEndpoint}/task/${currentTaskId[1]}`,
{
worker: null,
},
defaultOptions,
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
break;
}
default:
throw new Error("Unknown action passed");
}
}
} else if (comment) {
} else if (comment && issue) {
// should be an issue comment
} else {
throw new Error(
"You are running this action through an unsupported trigger",
switch (action) {
case "created": {
// New comment, add to Freelo task
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const taskComment = `
Comment <a href="${comment.url}">${comment.id}</a> by: ${freeloMention(comment.user.login)}<br>
${sanitize(comment.body, sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
<i>(This action was performed automatically)</i>
`;
// Create comment
const res = await axios.post(
`${apiEndpoint}/task/${currentTaskId}/comments`,
{
content: taskComment,
},
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Created comment ${res.data.id}`);
break;
}
case "deleted": {
// Find comment, delete it
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const getTaskComments = await axios.get(
`${apiEndpoint}/task/${currentTaskId}`,
defaultOptions,
);
if (getTaskComments.status > 399) {
console.error(getTaskComments.data);
throw new Error("Got an error response from Freelo API");
}
const findComment = (
getTaskComments.data.comments as { id: number; content: string }[]
).filter((c) => />(\d+)</gm.test(c.content));
if (findComment.length === 0) {
console.log("Comment found, but no GitHub comment ID identified");
break;
}
const res = await axios.delete(
`${apiEndpoint}/comment/${findComment[0].id}`,
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Deleted comment ${findComment[0].id}`);
break;
}
case "edited": {
// Find comment, edit it
const currentTaskId = await freeloId(issue.number);
if (!currentTaskId || currentTaskId.length === 0) {
console.log("Comment found, but no Freelo task ID identified");
break;
}
const getTaskComments = await axios.get(
`${apiEndpoint}/task/${currentTaskId}`,
defaultOptions,
);
if (getTaskComments.status > 399) {
console.error(getTaskComments.data);
throw new Error("Got an error response from Freelo API");
}
const findComment = (
getTaskComments.data.comments as { id: number; content: string }[]
).filter((c) => />(\d+)</gm.test(c.content));
if (findComment.length === 0) {
console.log("Comment found, but no GitHub comment ID identified");
break;
}
const taskComment = `
Comment <a href="${comment.url}">${comment.id}</a> by: ${freeloMention(comment.user.login)}<br>
${sanitize(comment.body, sanitizeOptions)}<br>
GitHub issue: <a href="${issue.url}">#${issue.number}</a><br>
<i>(This action was performed automatically)</i>
`;
// Create comment
const res = await axios.post(
`${apiEndpoint}/comment/${findComment[0].id}`,
{
content: taskComment,
},
);
if (res.status > 399) {
console.error(res.data);
throw new Error("Got an error response from Freelo API");
}
console.log(`Edited comment ${findComment[0].id}`);
break;
}
default:
break;
}
} else {
console.error("You are running this through an unsupported trigger!");
}
} catch (error) {
setFailed((error as Error)?.message ?? "Unknown error");