mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
fix(formatters): localize PR buttons, cap oversized content, dedupe status logic
- PR merge/close button labels now follow the group language (actions.merge/close)
instead of hardcoded Chinese
- clamp content to Discord embed limits (title 256, description 4096, field value
1024, 25 fields) in formatters plus a render-layer safety net; Telegram gets a
tag-safe 4096-char cap (capHtml closes dangling tags)
- raise commit subject truncation from 72 to 200 chars (MAX_COMMIT_SUBJECT)
- extract workflowStatus/workflowRunStatus/statusColorKey helpers shared by
check_run/check_suite/workflow_run/workflow_job
- dedupe deployment ref/sha fields via addDeploymentRefFields
- commit_comment without a commit id uses title_plain (no dangling ???????)
- tag pushes now report 'Tag created'; zh push title includes the {ref}
- sender profile link derives from the repo's forge origin instead of github.com
- group webhook log emoji injected via emojiPrefix, removed from locale files
- dispatchEvent accepts preloaded groups (single KV read per webhook)
- webhook 401 logs distinguish 'secret not configured' from 'invalid signature'
This commit is contained in:
parent
e59b10f739
commit
a5324fb0ea
20 changed files with 425 additions and 136 deletions
|
|
@ -1,6 +1,17 @@
|
|||
import type { NeutralMessage, NeutralAuthor } from "../types";
|
||||
import { GITHUB_COLORS, WORKFLOW_CONCLUSION_EMOJI } from "./colors";
|
||||
import { branchLink, commitLink, emojiPrefix, type T, buildMessage, repoBaseUrl } from "./helpers";
|
||||
import {
|
||||
branchLink,
|
||||
cap,
|
||||
commitLink,
|
||||
emojiPrefix,
|
||||
MAX_FIELD_VALUE,
|
||||
statusColorKey,
|
||||
type T,
|
||||
buildMessage,
|
||||
repoBaseUrl,
|
||||
workflowStatus,
|
||||
} from "./helpers";
|
||||
|
||||
export function formatCheckSuite(
|
||||
payload: Record<string, unknown>,
|
||||
|
|
@ -18,21 +29,11 @@ export function formatCheckSuite(
|
|||
html_url?: string;
|
||||
};
|
||||
|
||||
const status =
|
||||
suite.status === "queued"
|
||||
? "queued"
|
||||
: suite.status === "in_progress"
|
||||
? "running"
|
||||
: (suite.conclusion ?? "pending");
|
||||
const status = workflowStatus(suite.status, suite.conclusion);
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
const emoji = WORKFLOW_CONCLUSION_EMOJI[status] ?? "⏳";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const colorKey =
|
||||
status === "success"
|
||||
? "check_run_success"
|
||||
: status === "failure"
|
||||
? "check_run_failure"
|
||||
: "check_run_other";
|
||||
const colorKey = statusColorKey("check_run", status);
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
|
|
@ -172,20 +173,10 @@ export function formatCheckRun(
|
|||
output?: { title?: string; summary?: string };
|
||||
};
|
||||
|
||||
const status =
|
||||
checkRun.status === "queued"
|
||||
? "queued"
|
||||
: checkRun.status === "in_progress"
|
||||
? "running"
|
||||
: (checkRun.conclusion ?? "pending");
|
||||
const status = workflowStatus(checkRun.status, checkRun.conclusion);
|
||||
const emoji = WORKFLOW_CONCLUSION_EMOJI[status] ?? "⏳";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const colorKey =
|
||||
status === "success"
|
||||
? "check_run_success"
|
||||
: status === "failure"
|
||||
? "check_run_failure"
|
||||
: "check_run_other";
|
||||
const colorKey = statusColorKey("check_run", status);
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
|
|
@ -198,7 +189,7 @@ export function formatCheckRun(
|
|||
if (checkRun.output?.title) {
|
||||
fields.push({
|
||||
name: t("fields.details"),
|
||||
value: checkRun.output.title,
|
||||
value: cap(checkRun.output.title, MAX_FIELD_VALUE),
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@ export function formatCommitComment(
|
|||
const truncated = comment.body && comment.body.length > 500;
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
const shortSha = comment.commit_id?.slice(0, 7) ?? "???????";
|
||||
const shaLink = comment.commit_id ? commitLink(baseUrl, comment.commit_id, shortSha) : undefined;
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
if (comment.commit_id) {
|
||||
fields.push({
|
||||
name: t("fields.commit"),
|
||||
value: commitLink(baseUrl, comment.commit_id, shortSha),
|
||||
value: shaLink!,
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
|
@ -36,10 +37,14 @@ export function formatCommitComment(
|
|||
return buildMessage(
|
||||
{
|
||||
author,
|
||||
title: t("events.commit_comment.title", {
|
||||
repo: repo ?? t("common.repository"),
|
||||
sha: commitLink(baseUrl, comment.commit_id ?? "", shortSha),
|
||||
}),
|
||||
title: shaLink
|
||||
? t("events.commit_comment.title", {
|
||||
repo: repo ?? t("common.repository"),
|
||||
sha: shaLink,
|
||||
})
|
||||
: t("events.commit_comment.title_plain", {
|
||||
repo: repo ?? t("common.repository"),
|
||||
}),
|
||||
url: comment.html_url,
|
||||
color: GITHUB_COLORS.commit_comment,
|
||||
description: `${t("events.commit_comment.action_comment", { emoji: em("💬"), action: al })}\n\n> ${commentBody}${truncated ? "..." : ""}`,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
import type { NeutralAuthor, NeutralField, NeutralMessage } from "../types";
|
||||
import { type T, buildMessage } from "./helpers";
|
||||
import {
|
||||
cap,
|
||||
MAX_DESCRIPTION,
|
||||
MAX_FIELDS,
|
||||
MAX_FIELD_VALUE,
|
||||
MAX_TITLE,
|
||||
type T,
|
||||
buildMessage,
|
||||
} from "./helpers";
|
||||
|
||||
const COLOR_WORDS: Record<string, number> = {
|
||||
red: 0xf85149,
|
||||
|
|
@ -29,12 +37,12 @@ function parseFields(raw: unknown): NeutralField[] | undefined {
|
|||
const value = (f as Record<string, unknown>).value;
|
||||
if (typeof name !== "string" || typeof value !== "string") continue;
|
||||
fields.push({
|
||||
name: name || "\u200b",
|
||||
value,
|
||||
name: cap(name || "\u200b", MAX_TITLE),
|
||||
value: cap(value, MAX_FIELD_VALUE),
|
||||
inline: (f as Record<string, unknown>).inline === true,
|
||||
});
|
||||
}
|
||||
return fields.length > 0 ? fields : undefined;
|
||||
return fields.length > 0 ? fields.slice(0, MAX_FIELDS) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,15 +58,18 @@ export function formatCustom(
|
|||
t: T,
|
||||
_showEmoji: boolean,
|
||||
): NeutralMessage {
|
||||
const title =
|
||||
const title = cap(
|
||||
typeof payload.title === "string" && payload.title.trim()
|
||||
? payload.title.trim()
|
||||
: t("custom.title_fallback");
|
||||
: t("custom.title_fallback"),
|
||||
MAX_TITLE,
|
||||
);
|
||||
const payloadRepo =
|
||||
typeof payload.repo === "string" && payload.repo.trim() ? payload.repo.trim() : undefined;
|
||||
const effectiveRepo = payloadRepo ?? repo;
|
||||
const fullTitle = effectiveRepo ? `${effectiveRepo}: ${title}` : title;
|
||||
const description = typeof payload.description === "string" ? payload.description : undefined;
|
||||
const description =
|
||||
typeof payload.description === "string" ? cap(payload.description, MAX_DESCRIPTION) : undefined;
|
||||
const url = typeof payload.url === "string" ? payload.url : undefined;
|
||||
const footer = typeof payload.footer === "string" ? payload.footer : undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,30 @@ import {
|
|||
repoBaseUrl,
|
||||
} from "./helpers";
|
||||
|
||||
/** Shared "branch/tag + commit" fields for deployment events. */
|
||||
function addDeploymentRefFields(
|
||||
fields: Array<{ name: string; value: string; inline?: boolean }>,
|
||||
deployment: { ref?: string; sha?: string },
|
||||
baseUrl: string | undefined,
|
||||
t: T,
|
||||
): void {
|
||||
if (deployment.ref) {
|
||||
const isTag = deployment.ref.startsWith("refs/tags/");
|
||||
fields.push({
|
||||
name: t("fields.branch_tag"),
|
||||
value: isTag ? tagLink(baseUrl, deployment.ref) : branchLink(baseUrl, deployment.ref),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
if (deployment.sha) {
|
||||
fields.push({
|
||||
name: t("fields.commit"),
|
||||
value: commitLink(baseUrl, deployment.sha, deployment.sha.slice(0, 7)),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDeployment(
|
||||
payload: Record<string, unknown>,
|
||||
repo: string | undefined,
|
||||
|
|
@ -29,7 +53,6 @@ export function formatDeployment(
|
|||
const emoji = "🚀";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const env = deployment.environment ?? t("common.unknown");
|
||||
const shortSha = deployment.sha?.slice(0, 7) ?? "???????";
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
|
|
@ -45,22 +68,7 @@ export function formatDeployment(
|
|||
inline: true,
|
||||
});
|
||||
|
||||
if (deployment.ref) {
|
||||
const isTag = deployment.ref.startsWith("refs/tags/");
|
||||
fields.push({
|
||||
name: t("fields.branch_tag"),
|
||||
value: isTag ? tagLink(baseUrl, deployment.ref) : branchLink(baseUrl, deployment.ref),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (deployment.sha) {
|
||||
fields.push({
|
||||
name: t("fields.commit"),
|
||||
value: commitLink(baseUrl, deployment.sha, shortSha),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
addDeploymentRefFields(fields, deployment, baseUrl, t);
|
||||
|
||||
if (deployment.description) {
|
||||
fields.push({
|
||||
|
|
@ -116,7 +124,6 @@ export function formatDeploymentStatus(
|
|||
const emoji = state === "success" ? "✅" : state === "failure" ? "❌" : "⏳";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const env = status.environment ?? deployment.environment ?? t("common.unknown");
|
||||
const shortSha = deployment.sha?.slice(0, 7) ?? "???????";
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
|
@ -133,22 +140,7 @@ export function formatDeploymentStatus(
|
|||
inline: true,
|
||||
});
|
||||
|
||||
if (deployment.ref) {
|
||||
const isTag = deployment.ref.startsWith("refs/tags/");
|
||||
fields.push({
|
||||
name: t("fields.branch_tag"),
|
||||
value: isTag ? tagLink(baseUrl, deployment.ref) : branchLink(baseUrl, deployment.ref),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (deployment.sha) {
|
||||
fields.push({
|
||||
name: t("fields.commit"),
|
||||
value: commitLink(baseUrl, deployment.sha, shortSha),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
addDeploymentRefFields(fields, deployment, baseUrl, t);
|
||||
|
||||
if (status.environment_url) {
|
||||
fields.push({
|
||||
|
|
|
|||
|
|
@ -99,3 +99,64 @@ export function tagLink(baseUrl: string | undefined, tag: string, label?: string
|
|||
? `[\`${display}\`](${baseUrl}/releases/tag/${encodeRefPath(clean)})`
|
||||
: `\`${display}\``;
|
||||
}
|
||||
|
||||
/* ---- Content size limits (mirror the Discord embed limits) ---- */
|
||||
export const MAX_TITLE = 256;
|
||||
export const MAX_DESCRIPTION = 4096;
|
||||
export const MAX_FIELD_VALUE = 1024;
|
||||
export const MAX_FIELDS = 25;
|
||||
export const MAX_FOOTER = 2048;
|
||||
/** First-line commit message length (stays well under the field value budget). */
|
||||
export const MAX_COMMIT_SUBJECT = 200;
|
||||
|
||||
/** Truncate a string to `max` characters. */
|
||||
export function cap(text: string, max: number): string {
|
||||
return text.length > max ? text.slice(0, max) : text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a check/workflow status: `queued` / `in_progress` keep their
|
||||
* value (the latter becomes `running`), anything else falls back to the
|
||||
* conclusion and finally `pending`.
|
||||
*/
|
||||
export function workflowStatus(status?: string, conclusion?: string): string {
|
||||
if (status === "queued") return "queued";
|
||||
if (status === "in_progress") return "running";
|
||||
return conclusion ?? "pending";
|
||||
}
|
||||
|
||||
/** workflow_run events derive their progress from the action, not `status`. */
|
||||
export function workflowRunStatus(action?: string, conclusion?: string): string {
|
||||
if (action === "in_progress") return "running";
|
||||
if (action === "requested") return "queued";
|
||||
return conclusion ?? "pending";
|
||||
}
|
||||
|
||||
/** GITHUB_COLORS key for a success/failure/other status. */
|
||||
export function statusColorKey(
|
||||
prefix: "check_run" | "workflow_run",
|
||||
status: string,
|
||||
): `${typeof prefix}_${"success" | "failure" | "other"}` {
|
||||
return status === "success"
|
||||
? `${prefix}_success`
|
||||
: status === "failure"
|
||||
? `${prefix}_failure`
|
||||
: `${prefix}_other`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sender's profile URL on the same forge as the repo (derived from the
|
||||
* repo's html_url origin, e.g. `https://github.com/owner/repo` →
|
||||
* `https://github.com/login`). Falls back to github.com when the repo URL is
|
||||
* unavailable or unparseable.
|
||||
*/
|
||||
export function senderProfileUrl(repoUrl: string | undefined, login: string): string {
|
||||
if (repoUrl) {
|
||||
try {
|
||||
return `${new URL(repoUrl).origin}/${encodeURIComponent(login)}`;
|
||||
} catch {
|
||||
// unparseable repo URL — fall through to github.com
|
||||
}
|
||||
}
|
||||
return `https://github.com/${login}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { Route, WebhookEvent, NeutralMessage, NeutralAuthor } from "../types";
|
||||
import type { Translations } from "../lib/i18n";
|
||||
import { makeT, type T } from "./helpers";
|
||||
import { makeT, senderProfileUrl, type T } from "./helpers";
|
||||
import { formatPush } from "./push";
|
||||
import { formatPullRequest } from "./pull-request";
|
||||
import { formatPullRequestReview, formatPullRequestReviewComment } from "./review";
|
||||
|
|
@ -41,7 +41,7 @@ export function formatEvent(
|
|||
const author: NeutralAuthor = {
|
||||
name: sender ?? t("common.unknown"),
|
||||
iconUrl: senderAvatar,
|
||||
url: senderUrl ?? (sender ? `https://github.com/${sender}` : undefined),
|
||||
url: senderUrl ?? (sender ? senderProfileUrl(repoUrl, sender) : undefined),
|
||||
};
|
||||
|
||||
switch (eventType) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { NeutralMessage, NeutralAuthor } from "../types";
|
||||
import { GITHUB_COLORS } from "./colors";
|
||||
import { emojiPrefix, type T, buildMessage } from "./helpers";
|
||||
import { cap, emojiPrefix, MAX_FIELD_VALUE, type T, buildMessage } from "./helpers";
|
||||
|
||||
export function formatIssues(
|
||||
payload: Record<string, unknown>,
|
||||
|
|
@ -47,7 +47,7 @@ export function formatIssues(
|
|||
if (issue.labels && issue.labels.length > 0) {
|
||||
fields.push({
|
||||
name: t("fields.labels"),
|
||||
value: issue.labels.map((l) => l.name).join(", "),
|
||||
value: cap(issue.labels.map((l) => l.name).join(", "), MAX_FIELD_VALUE),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ export function formatIssues(
|
|||
if (issue.assignees && issue.assignees.length > 0) {
|
||||
fields.push({
|
||||
name: t("fields.assignees"),
|
||||
value: issue.assignees.map((a) => a.login).join(", "),
|
||||
value: cap(issue.assignees.map((a) => a.login).join(", "), MAX_FIELD_VALUE),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import type { NeutralMessage, NeutralAuthor, NeutralAction } from "../types";
|
||||
import { GITHUB_COLORS } from "./colors";
|
||||
import { branchLink, emojiPrefix, type T, buildMessage, repoBaseUrl } from "./helpers";
|
||||
import {
|
||||
branchLink,
|
||||
cap,
|
||||
emojiPrefix,
|
||||
MAX_FIELD_VALUE,
|
||||
type T,
|
||||
buildMessage,
|
||||
repoBaseUrl,
|
||||
} from "./helpers";
|
||||
|
||||
export function formatPullRequest(
|
||||
payload: Record<string, unknown>,
|
||||
|
|
@ -82,7 +90,7 @@ export function formatPullRequest(
|
|||
if (pr.labels && pr.labels.length > 0) {
|
||||
fields.push({
|
||||
name: t("fields.labels"),
|
||||
value: pr.labels.map((l) => l.name).join(", "),
|
||||
value: cap(pr.labels.map((l) => l.name).join(", "), MAX_FIELD_VALUE),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
|
@ -91,8 +99,16 @@ export function formatPullRequest(
|
|||
const actionable = pr.state === "open" && !!repoOwner && !!repoName && pr.number != null;
|
||||
const actions: NeutralAction[] | undefined = actionable
|
||||
? [
|
||||
{ id: `ghpr|merge|${repoOwner}|${repoName}|${pr.number}`, label: "合并", style: "primary" },
|
||||
{ id: `ghpr|close|${repoOwner}|${repoName}|${pr.number}`, label: "关闭", style: "danger" },
|
||||
{
|
||||
id: `ghpr|merge|${repoOwner}|${repoName}|${pr.number}`,
|
||||
label: t("actions.merge"),
|
||||
style: "primary",
|
||||
},
|
||||
{
|
||||
id: `ghpr|close|${repoOwner}|${repoName}|${pr.number}`,
|
||||
label: t("actions.close"),
|
||||
style: "danger",
|
||||
},
|
||||
]
|
||||
: undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import type { NeutralMessage, NeutralAuthor } from "../types";
|
||||
import { GITHUB_COLORS } from "./colors";
|
||||
import { branchLink, emojiPrefix, tagLink, type T, buildMessage, repoBaseUrl } from "./helpers";
|
||||
import {
|
||||
branchLink,
|
||||
emojiPrefix,
|
||||
MAX_COMMIT_SUBJECT,
|
||||
tagLink,
|
||||
type T,
|
||||
buildMessage,
|
||||
repoBaseUrl,
|
||||
} from "./helpers";
|
||||
|
||||
export function formatPush(
|
||||
payload: Record<string, unknown>,
|
||||
|
|
@ -55,7 +63,10 @@ export function formatPush(
|
|||
descriptionParts.push(em("⚠️") + t("events.push.force_push"));
|
||||
}
|
||||
if (created) {
|
||||
descriptionParts.push(em("🆕") + t("events.push.branch_created"));
|
||||
descriptionParts.push(
|
||||
em("🆕") +
|
||||
t(isTagPush ? "events.push.tag_created" : "events.push.branch_created"),
|
||||
);
|
||||
}
|
||||
|
||||
if (compareUrl) {
|
||||
|
|
@ -66,7 +77,8 @@ export function formatPush(
|
|||
|
||||
const commitField = (c: (typeof commits)[number]): { name: string; value: string } => {
|
||||
const shortId = c.id?.slice(0, 7) ?? "???????";
|
||||
const msg = (c.message?.split("\n")[0] ?? "").slice(0, 72) || t("common.no_message");
|
||||
const msg = (c.message?.split("\n")[0] ?? "").slice(0, MAX_COMMIT_SUBJECT) ||
|
||||
t("common.no_message");
|
||||
const url = baseUrl && c.id ? `${baseUrl}/commit/${c.id}` : null;
|
||||
const hash = url ? `[\`${shortId}\`](${url})` : `\`${shortId}\``;
|
||||
return { name: `\u200b`, value: `${hash} ${msg}` };
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
import type { NeutralMessage, NeutralAuthor } from "../types";
|
||||
import { GITHUB_COLORS, WORKFLOW_CONCLUSION_EMOJI } from "./colors";
|
||||
import { emojiPrefix, type T, buildMessage, branchLink, commitLink, repoBaseUrl } from "./helpers";
|
||||
import {
|
||||
branchLink,
|
||||
cap,
|
||||
commitLink,
|
||||
emojiPrefix,
|
||||
MAX_FIELD_VALUE,
|
||||
statusColorKey,
|
||||
type T,
|
||||
buildMessage,
|
||||
repoBaseUrl,
|
||||
workflowRunStatus,
|
||||
workflowStatus,
|
||||
} from "./helpers";
|
||||
|
||||
export function formatWorkflowJob(
|
||||
payload: Record<string, unknown>,
|
||||
|
|
@ -20,21 +32,11 @@ export function formatWorkflowJob(
|
|||
run_id?: number;
|
||||
};
|
||||
|
||||
const status =
|
||||
job.status === "queued"
|
||||
? "queued"
|
||||
: job.status === "in_progress"
|
||||
? "running"
|
||||
: (job.conclusion ?? "pending");
|
||||
const status = workflowStatus(job.status, job.conclusion ?? undefined);
|
||||
const emoji = WORKFLOW_CONCLUSION_EMOJI[status] ?? "⏳";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
const colorKey =
|
||||
status === "success"
|
||||
? "workflow_run_success"
|
||||
: status === "failure"
|
||||
? "workflow_run_failure"
|
||||
: "workflow_run_other";
|
||||
const colorKey = statusColorKey("workflow_run", status);
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
|
|
@ -114,21 +116,11 @@ export function formatWorkflowRun(
|
|||
};
|
||||
|
||||
const action = payload.action as string | undefined;
|
||||
const status =
|
||||
action === "in_progress"
|
||||
? "running"
|
||||
: action === "requested"
|
||||
? "queued"
|
||||
: (workflow.conclusion ?? "pending");
|
||||
const status = workflowRunStatus(action, workflow.conclusion);
|
||||
const emoji = WORKFLOW_CONCLUSION_EMOJI[status] ?? "⏳";
|
||||
const em = (e: string): string => emojiPrefix(e, showEmoji);
|
||||
const baseUrl = repoBaseUrl(payload, repo);
|
||||
const colorKey =
|
||||
status === "success"
|
||||
? "workflow_run_success"
|
||||
: status === "failure"
|
||||
? "workflow_run_failure"
|
||||
: "workflow_run_other";
|
||||
const colorKey = statusColorKey("workflow_run", status);
|
||||
|
||||
const fields: Array<{ name: string; value: string; inline?: boolean }> = [];
|
||||
|
||||
|
|
@ -139,12 +131,13 @@ export function formatWorkflowRun(
|
|||
});
|
||||
|
||||
if (workflow.jobs?.length) {
|
||||
// Many-jobs workflows must stay under the Discord field value limit.
|
||||
const jobLines = workflow.jobs.map(
|
||||
(j) => `${em(WORKFLOW_CONCLUSION_EMOJI[j.conclusion ?? ""] ?? "⏳")}${j.name ?? ""}`,
|
||||
(j) => `${em(WORKFLOW_CONCLUSION_EMOJI[j.conclusion ?? ""] ?? "⏳")}${cap(j.name ?? "", 200)}`,
|
||||
);
|
||||
fields.push({
|
||||
name: t("fields.job"),
|
||||
value: jobLines.join("\n"),
|
||||
value: cap(jobLines.join("\n"), MAX_FIELD_VALUE),
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue