mirror of
https://github.com/SethCohen/github-releases-to-discord
synced 2026-09-14 20:13:23 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24d166886a | ||
|
|
60ef92f147 | ||
|
|
e15eb81a91 | ||
|
|
80aca15d72 |
@@ -7,3 +7,5 @@ release.json
|
|||||||
repository.json
|
repository.json
|
||||||
user.json
|
user.json
|
||||||
tests/sample-test-release-v2.json
|
tests/sample-test-release-v2.json
|
||||||
|
tests/sample-test-release-v3.json
|
||||||
|
tests/sample-test-release-null-body.json
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.20.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.19.0...v1.20.0) (2026-04-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add manual dispatch support for GitHub Actions to test Discord webhook integration with optional release inputs. resolves [#52](https://github.com/SethCohen/github-releases-to-discord/issues/52) ([e15eb81](https://github.com/SethCohen/github-releases-to-discord/commit/e15eb81a91d940818d60143a1f57edb92ae0828c))
|
||||||
|
* enhance reduceHeadings function to handle indented and closed markdown headings and add tests for new functionality. resolves [#51](https://github.com/SethCohen/github-releases-to-discord/issues/51) ([80aca15](https://github.com/SethCohen/github-releases-to-discord/commit/80aca15d7235082187d6eee6054a69ceed9c45db))
|
||||||
|
* **tests:** add test for handling release payload with null body and update formatDescription to handle undefined input. resolves [#53](https://github.com/SethCohen/github-releases-to-discord/issues/53) ([60ef92f](https://github.com/SethCohen/github-releases-to-discord/commit/60ef92f1479987b509687244b04859040cb0f43d))
|
||||||
|
|
||||||
## [1.19.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.18.0...v1.19.0) (2025-06-17)
|
## [1.19.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.18.0...v1.19.0) (2025-06-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,51 @@ jobs:
|
|||||||
reduce_headings: true
|
reduce_headings: true
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Add Your Webhook URL as a Secret
|
### 3. Optional: Test with `workflow_dispatch`
|
||||||
|
|
||||||
|
If you want to test the action manually without relying on cloning and using `act`, you can add `workflow_dispatch` and pass release fields into the action:
|
||||||
|
|
||||||
|
Example inputs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
release_name: v1.2.3
|
||||||
|
release_body: |
|
||||||
|
## Changes
|
||||||
|
- Added manual testing support
|
||||||
|
- Verified Discord webhook output
|
||||||
|
release_html_url: https://github.com/owner/repo/releases/tag/v1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_name:
|
||||||
|
description: Release title to post
|
||||||
|
required: true
|
||||||
|
release_body:
|
||||||
|
description: Release notes body to post
|
||||||
|
required: true
|
||||||
|
release_html_url:
|
||||||
|
description: Release URL to link in Discord
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
github-releases-to-discord:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: GitHub Releases to Discord
|
||||||
|
uses: SethCohen/github-releases-to-discord@v1
|
||||||
|
with:
|
||||||
|
webhook_url: ${{ secrets.WEBHOOK_URL }}
|
||||||
|
release_name: ${{ inputs.release_name }}
|
||||||
|
release_body: ${{ inputs.release_body }}
|
||||||
|
release_html_url: ${{ inputs.release_html_url }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Add Your Webhook URL as a Secret
|
||||||
|
|
||||||
- In your GitHub repo, go to **Settings → Secrets and variables → Actions**.
|
- In your GitHub repo, go to **Settings → Secrets and variables → Actions**.
|
||||||
- Add a new secret named `WEBHOOK_URL` and paste your Discord webhook URL.
|
- Add a new secret named `WEBHOOK_URL` and paste your Discord webhook URL.
|
||||||
@@ -77,20 +121,23 @@ jobs:
|
|||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
| Input Name | Required | Default | Description |
|
| Input Name | Required | Default | Description |
|
||||||
|-------------------------------|----------|-------------|--------------------------------------------------------------------|
|
|--------------------------------|----------|-------------|--------------------------------------------------------------------|
|
||||||
| `webhook_url` | ✔ | | Discord webhook URL (use a GitHub secret). |
|
| `webhook_url` | ✔ | | Discord webhook URL (use a GitHub secret). |
|
||||||
| `color` | ❌ | 2105893 | Embed color (decimal). |
|
| `color` | ❌ | 2105893 | Embed color (decimal). |
|
||||||
| `username` | ❌ | | Webhook username. |
|
| `username` | ❌ | | Webhook username. |
|
||||||
| `avatar_url` | ❌ | | Webhook avatar image URL. |
|
| `avatar_url` | ❌ | | Webhook avatar image URL. |
|
||||||
| `custom_html_url` | ❌ | | Custom URL for the embed title (overrides GitHub release URL). |
|
| `custom_html_url` | ❌ | | Custom URL for the embed title (overrides GitHub release URL). |
|
||||||
| `content` | ❌ | | Additional message content (e.g., `@everyone`). |
|
| `content` | ❌ | | Additional message content (e.g., `@everyone`). |
|
||||||
| `footer_title` | ❌ | | Footer title. |
|
| `release_name` | ❌ | | Manual release title for `workflow_dispatch` testing. |
|
||||||
| `footer_icon_url` | ❌ | | Footer icon image URL. |
|
| `release_body` | ❌ | | Manual release body for `workflow_dispatch` testing. |
|
||||||
| `footer_timestamp` | ❌ | false | Show timestamp in footer (`true`/`false`). |
|
| `release_html_url` | ❌ | | Manual release URL for `workflow_dispatch` testing. |
|
||||||
| `max_description` | ❌ | 4096 | Max description length (Discord limit: 4096). |
|
| `footer_title` | ❌ | | Footer title. |
|
||||||
| `remove_github_reference_links`| ❌ | false | Remove PR, commit, and issue links from the description. |
|
| `footer_icon_url` | ❌ | | Footer icon image URL. |
|
||||||
| `reduce_headings` | ❌ | false | Reduce heading sizes for compact display. |
|
| `footer_timestamp` | ❌ | false | Show timestamp in footer (`true`/`false`). |
|
||||||
|
| `max_description` | ❌ | 4096 | Max description length (Discord limit: 4096). |
|
||||||
|
| `remove_github_reference_links`| ❌ | false | Remove PR, commit, and issue links from the description. |
|
||||||
|
| `reduce_headings` | ❌ | false | Reduce heading sizes for compact display. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -111,6 +158,8 @@ jobs:
|
|||||||
- Use Markdown in your release notes for best results.
|
- Use Markdown in your release notes for best results.
|
||||||
- **Private Repos:**
|
- **Private Repos:**
|
||||||
- The action works for both public and private repositories.
|
- The action works for both public and private repositories.
|
||||||
|
- **Manual Testing:**
|
||||||
|
- Use `release_name`, `release_body`, and optionally `release_html_url` when triggering the workflow with `workflow_dispatch`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ inputs:
|
|||||||
content:
|
content:
|
||||||
description: String content for webhook.
|
description: String content for webhook.
|
||||||
required: false
|
required: false
|
||||||
|
release_name:
|
||||||
|
description: Optional release title used when manually triggering the workflow with workflow_dispatch.
|
||||||
|
required: false
|
||||||
|
release_body:
|
||||||
|
description: Optional release body used when manually triggering the workflow with workflow_dispatch.
|
||||||
|
required: false
|
||||||
|
release_html_url:
|
||||||
|
description: Optional release URL used when manually triggering the workflow with workflow_dispatch.
|
||||||
|
required: false
|
||||||
footer_title:
|
footer_title:
|
||||||
description: Title for the footer.
|
description: Title for the footer.
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import core from '@actions/core';
|
import core from '@actions/core';
|
||||||
import github from '@actions/github';
|
import github from '@actions/github';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes carriage return characters.
|
* Removes carriage return characters.
|
||||||
@@ -61,8 +62,21 @@ const removeGithubReferenceLinks = (text) => text
|
|||||||
* @returns {string} The text with reduced heading sizes.
|
* @returns {string} The text with reduced heading sizes.
|
||||||
*/
|
*/
|
||||||
const reduceHeadings = (text) => text
|
const reduceHeadings = (text) => text
|
||||||
.replace(/^###\s+(.+)$/gm, '**__$1__**') // Convert H3 to bold + underline
|
.split('\n')
|
||||||
.replace(/^##\s+(.+)$/gm, '**$1**'); // Convert H2 to bold
|
.map((line) => {
|
||||||
|
const h3 = line.match(/^\s*###\s+(.+?)\s*#*\s*$/);
|
||||||
|
if (h3) {
|
||||||
|
return `**__${h3[1].trim()}__**`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const h2 = line.match(/^\s*##\s+(.+?)\s*#*\s*$/);
|
||||||
|
if (h2) {
|
||||||
|
return `**${h2[1].trim()}**`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts PR, issue, and changelog links to markdown format, ignoring existing markdown links.
|
* Converts PR, issue, and changelog links to markdown format, ignoring existing markdown links.
|
||||||
@@ -96,7 +110,7 @@ const convertLinksToMarkdown = (text) => {
|
|||||||
* @returns {string} The formatted description.
|
* @returns {string} The formatted description.
|
||||||
*/
|
*/
|
||||||
const formatDescription = (description) => {
|
const formatDescription = (description) => {
|
||||||
let edit = removeCarriageReturn(description);
|
let edit = removeCarriageReturn(description ?? '');
|
||||||
edit = removeHTMLComments(edit);
|
edit = removeHTMLComments(edit);
|
||||||
edit = reduceNewlines(edit);
|
edit = reduceNewlines(edit);
|
||||||
|
|
||||||
@@ -135,11 +149,32 @@ const getMaxDescription = () => {
|
|||||||
* @returns {object} The context with release details.
|
* @returns {object} The context with release details.
|
||||||
*/
|
*/
|
||||||
const getContext = () => {
|
const getContext = () => {
|
||||||
const { release } = github.context.payload;
|
return resolveReleaseContext(github.context.payload.release, {
|
||||||
|
body: core.getInput('release_body'),
|
||||||
|
name: core.getInput('release_name'),
|
||||||
|
html_url: core.getInput('release_html_url')
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves release data from either a GitHub release event or manual inputs.
|
||||||
|
* @param {object|null|undefined} release The release payload from the event.
|
||||||
|
* @param {object} manualInputs Manual fallback inputs.
|
||||||
|
* @returns {object} The resolved release context.
|
||||||
|
*/
|
||||||
|
const resolveReleaseContext = (release, manualInputs) => {
|
||||||
|
if (release) {
|
||||||
|
return {
|
||||||
|
body: release.body || '',
|
||||||
|
name: release.name || '',
|
||||||
|
html_url: release.html_url || ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
body: release.body,
|
body: manualInputs.body || '',
|
||||||
name: release.name,
|
name: manualInputs.name || '',
|
||||||
html_url: release.html_url
|
html_url: manualInputs.html_url || ''
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,12 +214,15 @@ const limitString = (str, maxLength, url, clipAtLine = false) => {
|
|||||||
const buildEmbedMessage = (name, html_url, description) => {
|
const buildEmbedMessage = (name, html_url, description) => {
|
||||||
const embedMsg = {
|
const embedMsg = {
|
||||||
title: limitString(name, 256),
|
title: limitString(name, 256),
|
||||||
url: html_url,
|
|
||||||
color: core.getInput('color'),
|
color: core.getInput('color'),
|
||||||
description: limitString(description, Math.min(getMaxDescription(), 6000 - name.length)),
|
description: limitString(description, Math.min(getMaxDescription(), 6000 - name.length)),
|
||||||
footer: {}
|
footer: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (html_url) {
|
||||||
|
embedMsg.url = html_url;
|
||||||
|
}
|
||||||
|
|
||||||
if (core.getInput('custom_html_url')) {
|
if (core.getInput('custom_html_url')) {
|
||||||
embedMsg.url = core.getInput('custom_html_url');
|
embedMsg.url = core.getInput('custom_html_url');
|
||||||
}
|
}
|
||||||
@@ -264,6 +302,11 @@ const run = async () => {
|
|||||||
if (!webhookUrl) return core.setFailed('webhook_url not set.');
|
if (!webhookUrl) return core.setFailed('webhook_url not set.');
|
||||||
|
|
||||||
const { body, html_url, name } = getContext();
|
const { body, html_url, name } = getContext();
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
return core.setFailed('No GitHub release payload found. When using workflow_dispatch, pass release_name to the action.');
|
||||||
|
}
|
||||||
|
|
||||||
const description = formatDescription(body);
|
const description = formatDescription(body);
|
||||||
|
|
||||||
const embedMsg = buildEmbedMessage(name, html_url, description);
|
const embedMsg = buildEmbedMessage(name, html_url, description);
|
||||||
@@ -273,9 +316,13 @@ const run = async () => {
|
|||||||
await sendWebhook(webhookUrl, requestBody);
|
await sendWebhook(webhookUrl, requestBody);
|
||||||
};
|
};
|
||||||
|
|
||||||
run()
|
const isMainModule = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
|
||||||
.then(() => core.info('Action completed successfully'))
|
|
||||||
.catch(err => core.setFailed(err.message));
|
if (isMainModule) {
|
||||||
|
run()
|
||||||
|
.then(() => core.info('Action completed successfully'))
|
||||||
|
.catch(err => core.setFailed(err.message));
|
||||||
|
}
|
||||||
|
|
||||||
// Export utility functions for testing
|
// Export utility functions for testing
|
||||||
export {
|
export {
|
||||||
@@ -287,5 +334,8 @@ export {
|
|||||||
reduceHeadings,
|
reduceHeadings,
|
||||||
convertLinksToMarkdown,
|
convertLinksToMarkdown,
|
||||||
limitString,
|
limitString,
|
||||||
formatDescription
|
formatDescription,
|
||||||
|
resolveReleaseContext,
|
||||||
|
getContext,
|
||||||
|
run
|
||||||
};
|
};
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "github-releases-to-discord",
|
"name": "github-releases-to-discord",
|
||||||
"version": "1.19.0",
|
"version": "1.20.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "github-releases-to-discord",
|
"name": "github-releases-to-discord",
|
||||||
"version": "1.19.0",
|
"version": "1.20.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "github-releases-to-discord",
|
"name": "github-releases-to-discord",
|
||||||
"version": "1.19.0",
|
"version": "1.20.0",
|
||||||
"description": "A GitHub Action that automatically sends a stylized Discord webhook of a GitHub Release description to a specified Discord channel.",
|
"description": "A GitHub Action that automatically sends a stylized Discord webhook of a GitHub Release description to a specified Discord channel.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|||||||
+40
-1
@@ -7,7 +7,8 @@ import {
|
|||||||
reduceHeadings,
|
reduceHeadings,
|
||||||
convertLinksToMarkdown,
|
convertLinksToMarkdown,
|
||||||
limitString,
|
limitString,
|
||||||
formatDescription
|
formatDescription,
|
||||||
|
resolveReleaseContext
|
||||||
} from '../index.js';
|
} from '../index.js';
|
||||||
import { jest } from '@jest/globals';
|
import { jest } from '@jest/globals';
|
||||||
|
|
||||||
@@ -70,6 +71,16 @@ describe('index.js utility functions', () => {
|
|||||||
expect(reduceHeadings('## Heading2')).toBe('**Heading2**');
|
expect(reduceHeadings('## Heading2')).toBe('**Heading2**');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('reduceHeadings reduces repeated section headings', () => {
|
||||||
|
const input = '### Bug Fixes\n- fix thing\n\n### Features\n- add thing';
|
||||||
|
expect(reduceHeadings(input)).toBe('**__Bug Fixes__**\n- fix thing\n\n**__Features__**\n- add thing');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reduceHeadings handles indented and closed markdown headings', () => {
|
||||||
|
const input = ' ## Changes ##\n ### Features ###';
|
||||||
|
expect(reduceHeadings(input)).toBe('**Changes**\n**__Features__**');
|
||||||
|
});
|
||||||
|
|
||||||
test('convertLinksToMarkdown converts PR/issue/changelog links', () => {
|
test('convertLinksToMarkdown converts PR/issue/changelog links', () => {
|
||||||
const pr = 'https://github.com/owner/repo/pull/1';
|
const pr = 'https://github.com/owner/repo/pull/1';
|
||||||
const issue = 'https://github.com/owner/repo/issues/2';
|
const issue = 'https://github.com/owner/repo/issues/2';
|
||||||
@@ -84,6 +95,34 @@ describe('index.js utility functions', () => {
|
|||||||
expect(convertLinksToMarkdown(input)).toBe('[already](https://github.com/owner/repo/pull/1) and [PR #2](https://github.com/owner/repo/pull/2)');
|
expect(convertLinksToMarkdown(input)).toBe('[already](https://github.com/owner/repo/pull/1) and [PR #2](https://github.com/owner/repo/pull/2)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('resolveReleaseContext', () => {
|
||||||
|
test('uses release payload when present', () => {
|
||||||
|
const release = {
|
||||||
|
name: 'v1.2.3',
|
||||||
|
body: 'Release notes',
|
||||||
|
html_url: 'https://example.com/releases/v1.2.3'
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(resolveReleaseContext(release, {
|
||||||
|
name: 'ignored',
|
||||||
|
body: 'ignored',
|
||||||
|
html_url: 'https://example.com/ignored'
|
||||||
|
})).toEqual(release);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('falls back to manual inputs when release payload is missing', () => {
|
||||||
|
expect(resolveReleaseContext(null, {
|
||||||
|
name: 'manual release',
|
||||||
|
body: 'manual body',
|
||||||
|
html_url: 'https://example.com/manual'
|
||||||
|
})).toEqual({
|
||||||
|
name: 'manual release',
|
||||||
|
body: 'manual body',
|
||||||
|
html_url: 'https://example.com/manual'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('limitString', () => {
|
describe('limitString', () => {
|
||||||
test('returns string unchanged if under maxLength', () => {
|
test('returns string unchanged if under maxLength', () => {
|
||||||
expect(limitString('short', 10)).toBe('short');
|
expect(limitString('short', 10)).toBe('short');
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import { jest } from '@jest/globals';
|
||||||
|
|
||||||
|
const inputValues = {
|
||||||
|
webhook_url: 'https://discord.com/api/webhooks/test/webhook',
|
||||||
|
color: '2105893',
|
||||||
|
username: 'Release Changelog',
|
||||||
|
avatar_url: 'https://example.com/avatar.png',
|
||||||
|
content: '||@everyone||',
|
||||||
|
release_name: 'v1.2.3',
|
||||||
|
release_body: '## Changes\n- Added manual dispatch support\n- Verified webhook payload',
|
||||||
|
release_html_url: 'https://github.com/owner/repo/releases/tag/v1.2.3'
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchMock = jest.fn(async () => ({
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
json: async () => ({ id: 'discord-message-id' }),
|
||||||
|
headers: {
|
||||||
|
get: () => null
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const coreMock = {
|
||||||
|
getInput: jest.fn((name) => inputValues[name] || ''),
|
||||||
|
getBooleanInput: jest.fn((name) => false),
|
||||||
|
setFailed: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
warning: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
const githubMock = {
|
||||||
|
context: {
|
||||||
|
payload: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchMock.mockClear();
|
||||||
|
coreMock.setFailed.mockClear();
|
||||||
|
coreMock.info.mockClear();
|
||||||
|
coreMock.warning.mockClear();
|
||||||
|
githubMock.context.payload = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.unstable_mockModule('@actions/core', () => ({
|
||||||
|
default: coreMock
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule('@actions/github', () => ({
|
||||||
|
default: githubMock
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule('node-fetch', () => ({
|
||||||
|
default: fetchMock
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('manual dispatch integration', () => {
|
||||||
|
test('run() posts a Discord embed using manual workflow inputs', async () => {
|
||||||
|
const { run } = await import('../index.js');
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(fetchMock.mock.calls[0][0]).toBe('https://discord.com/api/webhooks/test/webhook?wait=true');
|
||||||
|
|
||||||
|
const request = JSON.parse(fetchMock.mock.calls[0][1].body);
|
||||||
|
expect(request).toEqual({
|
||||||
|
embeds: [{
|
||||||
|
title: 'v1.2.3',
|
||||||
|
url: 'https://github.com/owner/repo/releases/tag/v1.2.3',
|
||||||
|
color: '2105893',
|
||||||
|
description: '## Changes\n- Added manual dispatch support\n- Verified webhook payload',
|
||||||
|
footer: {}
|
||||||
|
}],
|
||||||
|
username: 'Release Changelog',
|
||||||
|
avatar_url: 'https://example.com/avatar.png',
|
||||||
|
content: '||@everyone||'
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(coreMock.setFailed).not.toHaveBeenCalled();
|
||||||
|
expect(coreMock.info).toHaveBeenCalledWith('{"id":"discord-message-id"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('run() tolerates a release payload with a null body', async () => {
|
||||||
|
githubMock.context.payload.release = {
|
||||||
|
name: 'v1.2.4',
|
||||||
|
body: null,
|
||||||
|
html_url: 'https://github.com/owner/repo/releases/tag/v1.2.4'
|
||||||
|
};
|
||||||
|
|
||||||
|
const { run } = await import('../index.js');
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
const request = JSON.parse(fetchMock.mock.calls[0][1].body);
|
||||||
|
expect(request.embeds[0]).toMatchObject({
|
||||||
|
title: 'v1.2.4',
|
||||||
|
url: 'https://github.com/owner/repo/releases/tag/v1.2.4',
|
||||||
|
description: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(coreMock.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user