Skip to content

Commit 165783c

Browse files
jsweep: clean messages_run_status.cjs (#23824)
1 parent 9ed852e commit 165783c

2 files changed

Lines changed: 176 additions & 53 deletions

File tree

actions/setup/js/messages_run_status.cjs

Lines changed: 20 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// @ts-check
2-
/// <reference types="@actions/github-script" />
32

43
/**
54
* Run Status Message Module
@@ -10,6 +9,19 @@
109

1110
const { getMessages, renderTemplate, toSnakeCase } = require("./messages_core.cjs");
1211

12+
/**
13+
* Renders a message using a custom template from config or a default template.
14+
* @param {string} messageKey - Key in the messages config (e.g., "runStarted")
15+
* @param {string} defaultTemplate - Default template string with {placeholder} syntax
16+
* @param {Object} ctx - Context object for template substitution
17+
* @returns {string} Rendered message
18+
*/
19+
function renderConfiguredMessage(messageKey, defaultTemplate, ctx) {
20+
const messages = getMessages();
21+
const template = messages?.[messageKey] ?? defaultTemplate;
22+
return renderTemplate(template, toSnakeCase(ctx));
23+
}
24+
1325
/**
1426
* @typedef {Object} RunStartedContext
1527
* @property {string} workflowName - Name of the workflow
@@ -23,16 +35,7 @@ const { getMessages, renderTemplate, toSnakeCase } = require("./messages_core.cj
2335
* @returns {string} Run-started message
2436
*/
2537
function getRunStartedMessage(ctx) {
26-
const messages = getMessages();
27-
28-
// Create context with both camelCase and snake_case keys
29-
const templateContext = toSnakeCase(ctx);
30-
31-
// Default run-started template
32-
const defaultMessage = "🚀 [{workflow_name}]({run_url}) has started processing this {event_type}";
33-
34-
// Use custom message if configured
35-
return messages?.runStarted ? renderTemplate(messages.runStarted, templateContext) : renderTemplate(defaultMessage, templateContext);
38+
return renderConfiguredMessage("runStarted", "🚀 [{workflow_name}]({run_url}) has started processing this {event_type}", ctx);
3639
}
3740

3841
/**
@@ -47,16 +50,7 @@ function getRunStartedMessage(ctx) {
4750
* @returns {string} Run-success message
4851
*/
4952
function getRunSuccessMessage(ctx) {
50-
const messages = getMessages();
51-
52-
// Create context with both camelCase and snake_case keys
53-
const templateContext = toSnakeCase(ctx);
54-
55-
// Default run-success template
56-
const defaultMessage = "✅ [{workflow_name}]({run_url}) completed successfully!";
57-
58-
// Use custom message if configured
59-
return messages?.runSuccess ? renderTemplate(messages.runSuccess, templateContext) : renderTemplate(defaultMessage, templateContext);
53+
return renderConfiguredMessage("runSuccess", "✅ [{workflow_name}]({run_url}) completed successfully!", ctx);
6054
}
6155

6256
/**
@@ -72,16 +66,7 @@ function getRunSuccessMessage(ctx) {
7266
* @returns {string} Run-failure message
7367
*/
7468
function getRunFailureMessage(ctx) {
75-
const messages = getMessages();
76-
77-
// Create context with both camelCase and snake_case keys
78-
const templateContext = toSnakeCase(ctx);
79-
80-
// Default run-failure template
81-
const defaultMessage = "❌ [{workflow_name}]({run_url}) {status}. Please review the logs for details.";
82-
83-
// Use custom message if configured
84-
return messages?.runFailure ? renderTemplate(messages.runFailure, templateContext) : renderTemplate(defaultMessage, templateContext);
69+
return renderConfiguredMessage("runFailure", "❌ [{workflow_name}]({run_url}) {status}. Please review the logs for details.", ctx);
8570
}
8671

8772
/**
@@ -96,16 +81,7 @@ function getRunFailureMessage(ctx) {
9681
* @returns {string} Detection-failure message
9782
*/
9883
function getDetectionFailureMessage(ctx) {
99-
const messages = getMessages();
100-
101-
// Create context with both camelCase and snake_case keys
102-
const templateContext = toSnakeCase(ctx);
103-
104-
// Default detection-failure template
105-
const defaultMessage = "⚠️ Security scanning failed for [{workflow_name}]({run_url}). Review the logs for details.";
106-
107-
// Use custom message if configured
108-
return messages?.detectionFailure ? renderTemplate(messages.detectionFailure, templateContext) : renderTemplate(defaultMessage, templateContext);
84+
return renderConfiguredMessage("detectionFailure", "⚠️ Security scanning failed for [{workflow_name}]({run_url}). Review the logs for details.", ctx);
10985
}
11086

11187
/**
@@ -120,10 +96,7 @@ function getDetectionFailureMessage(ctx) {
12096
* @returns {string} Pull-request-created message
12197
*/
12298
function getPullRequestCreatedMessage(ctx) {
123-
const messages = getMessages();
124-
const templateContext = toSnakeCase(ctx);
125-
const defaultMessage = "Pull request created: [#{item_number}]({item_url})";
126-
return messages?.pullRequestCreated ? renderTemplate(messages.pullRequestCreated, templateContext) : renderTemplate(defaultMessage, templateContext);
99+
return renderConfiguredMessage("pullRequestCreated", "Pull request created: [#{item_number}]({item_url})", ctx);
127100
}
128101

129102
/**
@@ -138,10 +111,7 @@ function getPullRequestCreatedMessage(ctx) {
138111
* @returns {string} Issue-created message
139112
*/
140113
function getIssueCreatedMessage(ctx) {
141-
const messages = getMessages();
142-
const templateContext = toSnakeCase(ctx);
143-
const defaultMessage = "Issue created: [#{item_number}]({item_url})";
144-
return messages?.issueCreated ? renderTemplate(messages.issueCreated, templateContext) : renderTemplate(defaultMessage, templateContext);
114+
return renderConfiguredMessage("issueCreated", "Issue created: [#{item_number}]({item_url})", ctx);
145115
}
146116

147117
/**
@@ -157,10 +127,7 @@ function getIssueCreatedMessage(ctx) {
157127
* @returns {string} Commit-pushed message
158128
*/
159129
function getCommitPushedMessage(ctx) {
160-
const messages = getMessages();
161-
const templateContext = toSnakeCase(ctx);
162-
const defaultMessage = "Commit pushed: [`{short_sha}`]({commit_url})";
163-
return messages?.commitPushed ? renderTemplate(messages.commitPushed, templateContext) : renderTemplate(defaultMessage, templateContext);
130+
return renderConfiguredMessage("commitPushed", "Commit pushed: [`{short_sha}`]({commit_url})", ctx);
164131
}
165132

166133
module.exports = {
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// @ts-check
2+
import { describe, it, expect, beforeEach, vi } from "vitest";
3+
4+
// messages_core.cjs calls core.warning on parse failures - provide a stub
5+
const mockCore = {
6+
info: vi.fn(),
7+
warning: vi.fn(),
8+
error: vi.fn(),
9+
setFailed: vi.fn(),
10+
setOutput: vi.fn(),
11+
};
12+
global.core = mockCore;
13+
14+
const { getRunStartedMessage, getRunSuccessMessage, getRunFailureMessage, getDetectionFailureMessage, getPullRequestCreatedMessage, getIssueCreatedMessage, getCommitPushedMessage } = require("./messages_run_status.cjs");
15+
16+
const WORKFLOW = "My Workflow";
17+
const RUN_URL = "https://github.com/owner/repo/actions/runs/99";
18+
19+
describe("messages_run_status", () => {
20+
beforeEach(() => {
21+
vi.clearAllMocks();
22+
delete process.env.GH_AW_SAFE_OUTPUT_MESSAGES;
23+
});
24+
25+
describe("getRunStartedMessage", () => {
26+
it("returns default template with all placeholders substituted", () => {
27+
const msg = getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "issue" });
28+
expect(msg).toBe(`🚀 [${WORKFLOW}](${RUN_URL}) has started processing this issue`);
29+
});
30+
31+
it("supports different event types", () => {
32+
expect(getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "pull request" })).toContain("pull request");
33+
expect(getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "discussion" })).toContain("discussion");
34+
});
35+
36+
it("uses custom template from config", () => {
37+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ runStarted: "Custom: {workflow_name} started" });
38+
const msg = getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "issue" });
39+
expect(msg).toBe(`Custom: ${WORKFLOW} started`);
40+
});
41+
42+
it("substitutes camelCase keys as well as snake_case", () => {
43+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ runStarted: "{workflowName} at {runUrl}" });
44+
const msg = getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "issue" });
45+
expect(msg).toBe(`${WORKFLOW} at ${RUN_URL}`);
46+
});
47+
});
48+
49+
describe("getRunSuccessMessage", () => {
50+
it("returns default template with placeholders substituted", () => {
51+
const msg = getRunSuccessMessage({ workflowName: WORKFLOW, runUrl: RUN_URL });
52+
expect(msg).toBe(`✅ [${WORKFLOW}](${RUN_URL}) completed successfully!`);
53+
});
54+
55+
it("uses custom template from config", () => {
56+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ runSuccess: "Done: {workflow_name}" });
57+
const msg = getRunSuccessMessage({ workflowName: WORKFLOW, runUrl: RUN_URL });
58+
expect(msg).toBe(`Done: ${WORKFLOW}`);
59+
});
60+
61+
it("ignores unrelated config keys and uses default", () => {
62+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ runStarted: "overridden" });
63+
const msg = getRunSuccessMessage({ workflowName: WORKFLOW, runUrl: RUN_URL });
64+
expect(msg).toContain("completed successfully");
65+
});
66+
});
67+
68+
describe("getRunFailureMessage", () => {
69+
it("returns default template with status substituted", () => {
70+
const msg = getRunFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, status: "failed" });
71+
expect(msg).toBe(`❌ [${WORKFLOW}](${RUN_URL}) failed. Please review the logs for details.`);
72+
});
73+
74+
it("handles different status values", () => {
75+
expect(getRunFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, status: "was cancelled" })).toContain("was cancelled");
76+
expect(getRunFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, status: "timed out" })).toContain("timed out");
77+
});
78+
79+
it("uses custom template from config", () => {
80+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ runFailure: "FAILED: {workflow_name} - {status}" });
81+
const msg = getRunFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, status: "failed" });
82+
expect(msg).toBe(`FAILED: ${WORKFLOW} - failed`);
83+
});
84+
});
85+
86+
describe("getDetectionFailureMessage", () => {
87+
it("returns default template with placeholders substituted", () => {
88+
const msg = getDetectionFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL });
89+
expect(msg).toBe(`⚠️ Security scanning failed for [${WORKFLOW}](${RUN_URL}). Review the logs for details.`);
90+
});
91+
92+
it("uses custom template from config", () => {
93+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ detectionFailure: "Security alert for {workflow_name}" });
94+
const msg = getDetectionFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL });
95+
expect(msg).toBe(`Security alert for ${WORKFLOW}`);
96+
});
97+
});
98+
99+
describe("getPullRequestCreatedMessage", () => {
100+
it("returns default template with item_number and item_url substituted", () => {
101+
const msg = getPullRequestCreatedMessage({ itemNumber: 42, itemUrl: "https://github.com/owner/repo/pull/42" });
102+
expect(msg).toBe("Pull request created: [#42](https://github.com/owner/repo/pull/42)");
103+
});
104+
105+
it("uses custom template from config", () => {
106+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ pullRequestCreated: "PR #{item_number} ready" });
107+
const msg = getPullRequestCreatedMessage({ itemNumber: 7, itemUrl: "https://github.com/owner/repo/pull/7" });
108+
expect(msg).toBe("PR #7 ready");
109+
});
110+
});
111+
112+
describe("getIssueCreatedMessage", () => {
113+
it("returns default template with item_number and item_url substituted", () => {
114+
const msg = getIssueCreatedMessage({ itemNumber: 15, itemUrl: "https://github.com/owner/repo/issues/15" });
115+
expect(msg).toBe("Issue created: [#15](https://github.com/owner/repo/issues/15)");
116+
});
117+
118+
it("uses custom template from config", () => {
119+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ issueCreated: "New issue #{item_number}" });
120+
const msg = getIssueCreatedMessage({ itemNumber: 3, itemUrl: "https://github.com/owner/repo/issues/3" });
121+
expect(msg).toBe("New issue #3");
122+
});
123+
});
124+
125+
describe("getCommitPushedMessage", () => {
126+
const SHA = "abc1234def5678901234567890123456789012ab";
127+
const SHORT = "abc1234";
128+
const COMMIT_URL = `https://github.com/owner/repo/commit/${SHA}`;
129+
130+
it("returns default template with short_sha and commit_url substituted", () => {
131+
const msg = getCommitPushedMessage({ commitSha: SHA, shortSha: SHORT, commitUrl: COMMIT_URL });
132+
expect(msg).toBe(`Commit pushed: [\`${SHORT}\`](${COMMIT_URL})`);
133+
});
134+
135+
it("uses custom template from config", () => {
136+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ commitPushed: "Pushed {short_sha} to repo" });
137+
const msg = getCommitPushedMessage({ commitSha: SHA, shortSha: SHORT, commitUrl: COMMIT_URL });
138+
expect(msg).toBe(`Pushed ${SHORT} to repo`);
139+
});
140+
141+
it("supports full SHA in custom template", () => {
142+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ commitPushed: "{commit_sha}" });
143+
const msg = getCommitPushedMessage({ commitSha: SHA, shortSha: SHORT, commitUrl: COMMIT_URL });
144+
expect(msg).toBe(SHA);
145+
});
146+
});
147+
148+
describe("fallback when config is missing keys", () => {
149+
it("uses default template when only unrelated config keys are set", () => {
150+
process.env.GH_AW_SAFE_OUTPUT_MESSAGES = JSON.stringify({ footer: "custom footer" });
151+
expect(getRunStartedMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, eventType: "issue" })).toContain("has started processing");
152+
expect(getRunSuccessMessage({ workflowName: WORKFLOW, runUrl: RUN_URL })).toContain("completed successfully");
153+
expect(getRunFailureMessage({ workflowName: WORKFLOW, runUrl: RUN_URL, status: "failed" })).toContain("failed");
154+
});
155+
});
156+
});

0 commit comments

Comments
 (0)