Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions src/reportChannels/reportChannel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { appendFile } from "node:fs/promises"
import {
DISCORD_WEBHOOK_URL_ENV_NAME,
type ReportChannelInput,
Expand All @@ -9,6 +10,91 @@ import {
type DiscordMessage
} from "./discordMessageSplitter.js"

const GITHUB_STEP_SUMMARY_ENV_NAME = "GITHUB_STEP_SUMMARY"

type AppendFileOperation = (
path: string,
content: string,
encoding: BufferEncoding
) => Promise<void>

type WorkflowReportDeliveryOptions = ReportChannelOptions & {
githubStepSummaryPath?: string
appendFile?: AppendFileOperation
}

type WorkflowReportDeliveryResult =
| { ok: true }
| {
ok: false
errorMessage: string
}

// workflow에서는 Actions summary 또는 stdout을 기본으로 기록하고 Discord를 추가 전송
export async function deliver(
input: ReportChannelInput,
options: WorkflowReportDeliveryOptions = {}
): Promise<WorkflowReportDeliveryResult> {
if (!input.markdown.trim()) {
return {
ok: true
}
}

const errorMessages: string[] = []
const summaryPath = options.githubStepSummaryPath ??
process.env[GITHUB_STEP_SUMMARY_ENV_NAME]

if (summaryPath?.trim()) {
const summaryResult = await sendGitHubActionsSummary(
input.markdown,
summaryPath,
options
)

if (!summaryResult.ok) {
errorMessages.push(summaryResult.errorMessage)

const stdoutResult = await sendStdout(input.markdown, options)

if (!stdoutResult.ok) {
errorMessages.push(
`stdout report write failed: ${stdoutResult.errorMessage}`
)
}
}
} else {
const stdoutResult = await sendStdout(input.markdown, options)

if (!stdoutResult.ok) {
errorMessages.push(
`stdout report write failed: ${stdoutResult.errorMessage}`
)
}
}
Comment thread
opficdev marked this conversation as resolved.

const webhookUrl = options.discordWebhookUrl ?? process.env[DISCORD_WEBHOOK_URL_ENV_NAME]

if (webhookUrl) {
Comment thread
opficdev marked this conversation as resolved.
const discordResult = await sendDiscord(input.markdown, webhookUrl, options)

if (!discordResult.ok) {
errorMessages.push(discordResult.errorMessage)
}
}

if (0 < errorMessages.length) {
return {
ok: false,
errorMessage: errorMessages.join("\n")
}
}

return {
ok: true
}
}

// Discord webhook URL이 있으면 Discord channel로 보내고 없으면 stdout으로 fallback
export async function send(
input: ReportChannelInput,
Expand Down Expand Up @@ -55,6 +141,27 @@ async function sendStdout(
}
}

// GitHub Actions가 제공한 step summary 파일에 전체 Markdown report를 추가 기록
async function sendGitHubActionsSummary(
markdown: string,
path: string,
options: WorkflowReportDeliveryOptions
): Promise<WorkflowReportDeliveryResult> {
try {
const write = options.appendFile ?? appendFile
await write(path, `${markdown}\n`, "utf8")

return {
ok: true
}
} catch (error) {
return {
ok: false,
errorMessage: `GitHub Actions summary write failed: ${errorMessageFor(error)}`
}
}
}

// Discord content 제한을 넘지 않도록 Markdown report를 여러 메시지로 나눠 전송
async function sendDiscord(
markdown: string,
Expand Down
7 changes: 4 additions & 3 deletions src/workflows/mergeRiskWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { build as buildAiPredictionPairRequests } from "../ai/predictionPairRequ
import { predict as predictBranchPairsWithAi } from "../ai/predictionPairRunner.js"
import { build as buildBranchPairMergeRiskReport } from "../reports/branchPairReportBuilder.js"
import { format as formatBranchPairMergeRiskReportMarkdown } from "../reports/branchPairMarkdownFormatter.js"
import { send as sendMergeRiskReport } from "../reportChannels/reportChannel.js"
import { deliver as deliverMergeRiskReport } from "../reportChannels/reportChannel.js"
import {
sanitizeAiPredictionPairFailureDebugEvent,
sanitizeAiPredictionPairPromptDebugEvent,
Expand Down Expand Up @@ -51,6 +51,7 @@ type MergeRiskWatchOptions = {
debugArtifactDir?: string
workflowRef?: string
fetch?: typeof fetch
reportDeliveryOptions?: Parameters<typeof deliverMergeRiskReport>[1]
}

type RemoteBranchLine = {
Expand Down Expand Up @@ -243,9 +244,9 @@ export async function run(options: MergeRiskWatchOptions): Promise<void> {
aiResults: predictions
})
const markdown = formatBranchPairMergeRiskReportMarkdown(report)
const result = await sendMergeRiskReport({
const result = await deliverMergeRiskReport({
markdown
})
}, options.reportDeliveryOptions)

if (!result.ok) {
throw new Error(result.errorMessage)
Expand Down
Loading