Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ansi control chars from PR comment message #1231

Merged
merged 6 commits into from
Jul 24, 2024
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## HEAD (Unreleased)

**(none)**
- feat: strip ansi control characters from pull request comment
([#1231](https://github.com/pulumi/actions/pull/1231))

---

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@actions/tool-cache": "^2.0.1",
"@pulumi/pulumi": "3.109.0",
"actions-parsers": "^1.0.2",
"ansi-to-html": "^0.7.2",
"dedent": "^0.7.0",
"envalid": "^7.3.1",
"got": "^11.8.6",
Expand Down
29 changes: 24 additions & 5 deletions src/libs/__tests__/pr.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as gh from '@actions/github';
import gh from '@actions/github';
import { Config } from '../../config';
import { handlePullRequestMessage } from '../pr';

Expand Down Expand Up @@ -50,7 +50,26 @@ describe('pr.ts', () => {

await handlePullRequestMessage(defaultOptions, projectName, 'test');
expect(createComment).toHaveBeenCalledWith({
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n```\ntest\n```\n\n</details>',
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n<pre>\ntest\n</pre>\n\n</details>',
issue_number: 123,
});
});

it('should convert ansi control character to html and add to pull request message', async () => {
// @ts-ignore
gh.context = {
payload: {
pull_request: {
number: 123,
},
},
};

process.env.GITHUB_REPOSITORY = 'pulumi/actions';

await handlePullRequestMessage(defaultOptions, projectName, '\x1b[30mblack\x1b[37mwhite');
expect(createComment).toHaveBeenCalledWith({
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n<pre>\n<span style="color:#000">black<span style="color:#AAA">white</span></span>\n</pre>\n\n</details>',
issue_number: 123,
});
});
Expand All @@ -74,7 +93,7 @@ describe('pr.ts', () => {

await handlePullRequestMessage(options, projectName, 'test');
expect(createComment).toHaveBeenCalledWith({
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n```\ntest\n```\n\n</details>',
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n<pre>\ntest\n</pre>\n\n</details>',
issue_number: 87,
});
});
Expand All @@ -101,7 +120,7 @@ describe('pr.ts', () => {

await handlePullRequestMessage(options, projectName, 'test');
expect(createComment).toHaveBeenCalledWith({
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n```\ntest\n```\n\n</details>',
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n<pre>\ntest\n</pre>\n\n</details>',
issue_number: 87,
});
});
Expand Down Expand Up @@ -142,7 +161,7 @@ describe('pr.ts', () => {
await handlePullRequestMessage(options, projectName, 'test');
expect(updateComment).toHaveBeenCalledWith({
comment_id: 2,
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n```\ntest\n```\n\n</details>',
body: '#### :tropical_drink: `preview` on myFirstProject/staging\n\n<details>\n<summary>Pulumi report</summary>\n\n<pre>\ntest\n</pre>\n\n</details>',
});
});
});
52 changes: 43 additions & 9 deletions src/libs/pr.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
import * as core from '@actions/core';
import { context, getOctokit } from '@actions/github';
import * as dedent from 'dedent';
import AnsiToHtml from 'ansi-to-html';
import dedent from 'dedent';
import invariant from 'ts-invariant';
import { Config } from '../config';

function ansiToHtml(
message: string,
maxLength: number,
): [string, boolean] {
/**
* Converts an ansi string to html by for example removing color escape characters.
* message: ansi string to convert
* maxLength: Maximum number of characters of final message incl. HTML tags
*
* return message as html and information if message was trimmed because of length
*/
const convert = new AnsiToHtml();
let trimmed = false;

let htmlBody: string = convert.toHtml(message);

// Check if htmlBody exceeds max characters
if (htmlBody.length > maxLength) {

// trim input message by number of exceeded characters
const dif: number = htmlBody.length - maxLength;
message = message.substring(0, message.length - dif);
jmrt47 marked this conversation as resolved.
Show resolved Hide resolved
trimmed = true;

// convert trimmed message to html
htmlBody = convert.toHtml(message);
}

return [htmlBody, trimmed];
}

export async function handlePullRequestMessage(
config: Config,
projectName: string,
Expand All @@ -16,25 +48,27 @@ export async function handlePullRequestMessage(
editCommentOnPr,
} = config;

// GitHub limits comment characters to 65535, use lower max to keep buffer for variable values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ thanks for documenting this!

const MAX_CHARACTER_COMMENT = 64_000;

const heading = `#### :tropical_drink: \`${command}\` on ${projectName}/${stackName}`;

const summary = '<summary>Pulumi report</summary>';

const rawBody = output.substring(0, 64_000);
// a line break between heading and rawBody is needed
// otherwise the backticks won't work as intended
const [htmlBody, trimmed]: [string, boolean] = ansiToHtml(output, MAX_CHARACTER_COMMENT);

const body = dedent`
${heading}

<details>
${summary}

\`\`\`
${rawBody}
\`\`\`
<pre>
${htmlBody}
</pre>
${
rawBody.length === 64_000
? '**Warn**: The output was too long and trimmed.'
trimmed
? ':warning: **Warn**: The output was too long and trimmed.'
: ''
}
</details>
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"target": "es2015",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"allowJs": false,
"importHelpers": true,
"alwaysStrict": true,
Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,13 @@ ansi-styles@^6.1.0, ansi-styles@^6.2.1:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==

ansi-to-html@^0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.7.2.tgz#a92c149e4184b571eb29a0135ca001a8e2d710cb"
integrity sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==
dependencies:
entities "^2.2.0"

anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
Expand Down Expand Up @@ -2558,6 +2565,11 @@ enquirer@^2.3.5:
dependencies:
ansi-colors "^4.1.1"

entities@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==

env-paths@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
Expand Down
Loading