Compare commits

...
12 Commits
Author SHA1 Message Date
SethCohen de60879a86 chore(master): release 1.18.0 (#49) 2025-06-17 01:12:36 -04:00
SethCohen 82d906cc6f chore: update README for clarity and conciseness, improve formatting, and add new sections for better user guidance
chore: remove unnecessary test file from .gitignore and add sample test release JSON for local testing
2025-06-17 01:09:24 -04:00
SethCohen feb5a40237 feat(index.js): enhance sendWebhook function to handle rate limits with retries for improved reliability when sending requests to Discord 2025-06-17 00:46:40 -04:00
meatvegsandwichandSethCohen 9fe781fdc7 Add custom url (#44)
* add custom_html_url parameter

* Update action.yml

* Update README.md

* Update test.yml

* fix: fixed embedMsg url property

---------

Co-authored-by: SethCohen <47002293+SethCohen@users.noreply.github.com>
2025-06-17 00:28:13 -04:00
SethCohen 74ded4247d Add option to strip PR and commit links (#48)
* feat: add option to remove PR and commit links

* feat(github-action): rename input from remove_pr_commit_links to remove_github_reference_links for clarity and expand functionality to include issue links
fix(github-action): update removeGithubReferenceLinks function to remove all GitHub PR, commit, and issue links from the text, including markdown links

resolves #41
2025-06-17 00:10:47 -04:00
SethCohen e1dc0826fe chore(master): release 1.17.0 (#47) 2025-06-16 22:50:30 -04:00
SethCohen e768ce1023 feat(workflow): add GitHub Actions workflow to automatically update SemVer tags on tag push events 2025-06-16 22:49:57 -04:00
SethCohen 6ac5abea42 chore(master): release 1.16.2 (#40) 2024-10-18 00:14:56 -04:00
SethCohen 6aa0dd988c docs: update README output example 2024-10-18 00:09:28 -04:00
SethCohen 1e7bdfd173 chore(master): release 1.16.1 (#39) 2024-10-18 00:03:36 -04:00
SethCohen 47869497ed fix: correct conversion of standalone PR, issue, and changelog URLs to markdown format
resolves #38
2024-10-18 00:02:43 -04:00
SethCohen 9737dc9002 docs: update README with details on markdown link conversion and other features 2024-10-17 23:37:47 -04:00
10 changed files with 287 additions and 122 deletions
+2 -1
View File
@@ -15,10 +15,11 @@ jobs:
color: ${{ inputs.COLOR }}
username: ${{ inputs.USERNAME }}
avatar_url: ${{ inputs.AVATAR_URL }}
custom_html_url: ${{ inputs.CUSTOM_HTML_URL }}
content: ${{ inputs.CONTENT }}
footer_title: ${{ inputs.FOOTER_TITLE }}
footer_icon_url: ${{ inputs.FOOTER_ICON_URL }}
footer_timestamp: ${{ inputs.FOOTER_TIMESTAMP }}
max_description: ${{ inputs.MAX_DESCRIPTION }}
reduce_headings: ${{ inputs.REDUCE_HEADINGS }}
remove_github_reference_links: ${{ inputs.REMOVE_GITHUB_REFERENCE_LINKS }}
+15
View File
@@ -0,0 +1,15 @@
name: Update SemVer Tags
on:
push:
branches-ignore:
- '**'
tags:
- 'v*.*.*'
jobs:
update_semver:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Update semver tags
uses: haya14busa/action-update-semver@v1
-1
View File
@@ -3,7 +3,6 @@
out
gen
.env
tests/sample-test-release.json
release.json
repository.json
user.json
+39
View File
@@ -1,5 +1,44 @@
# Changelog
## [1.18.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.17.0...v1.18.0) (2025-06-17)
### Features
* **index.js:** enhance sendWebhook function to handle rate limits with retries for improved reliability when sending requests to Discord ([feb5a40](https://github.com/SethCohen/github-releases-to-discord/commit/feb5a402377bc3da9cb9ea788964ece4e56f48cd))
### Miscellaneous
* remove unnecessary test file from .gitignore and add sample test release JSON for local testing ([82d906c](https://github.com/SethCohen/github-releases-to-discord/commit/82d906cc6f29adbe413b3f26b55deafc3f08ceee))
* update README for clarity and conciseness, improve formatting, and add new sections for better user guidance ([82d906c](https://github.com/SethCohen/github-releases-to-discord/commit/82d906cc6f29adbe413b3f26b55deafc3f08ceee))
## [1.17.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.16.2...v1.17.0) (2025-06-17)
### Features
* **workflow:** add GitHub Actions workflow to automatically update SemVer tags on tag push events ([e768ce1](https://github.com/SethCohen/github-releases-to-discord/commit/e768ce10237a6100cccd7e80b2e994e9a2609150))
## [1.16.2](https://github.com/SethCohen/github-releases-to-discord/compare/v1.16.1...v1.16.2) (2024-10-18)
### Documentation
* update README output example ([6aa0dd9](https://github.com/SethCohen/github-releases-to-discord/commit/6aa0dd988c547f3b3a73463bc6e69d944621c613))
## [1.16.1](https://github.com/SethCohen/github-releases-to-discord/compare/v1.16.0...v1.16.1) (2024-10-18)
### Bug Fixes
* correct conversion of standalone PR, issue, and changelog URLs to markdown format ([4786949](https://github.com/SethCohen/github-releases-to-discord/commit/47869497ed80cf0d6188692d82d71dff7a55dffe)), closes [#38](https://github.com/SethCohen/github-releases-to-discord/issues/38)
### Documentation
* update README with details on markdown link conversion and other features ([9737dc9](https://github.com/SethCohen/github-releases-to-discord/commit/9737dc900274be227db48f8e23c715aa00b4af59))
## [1.16.0](https://github.com/SethCohen/github-releases-to-discord/compare/v1.15.3...v1.16.0) (2024-10-18)
+137 -86
View File
@@ -1,44 +1,49 @@
# GitHub Releases To Discord Action
# GitHub Releases to Discord Action
A GitHub Action that sends a stylized Discord webhook containing the description of a GitHub Release to a specified Discord channel. It formats the description to improve readability and includes various configuration options to customize the message.
Easily notify your Discord community about new GitHub releases! This GitHub Action automatically sends a beautifully formatted Discord embed message with your release notes whenever you publish a release on GitHub.
## Features
**Main Benefits:**
- Formats release descriptions by:
- Removing carriage returns and HTML comments.
- Styling headers for better readability in Discord (optional).
- Cleaning up redundant whitespace and newlines.
- Converting common GitHub links (e.g., PRs, Issues) into clickable URLs.
- Limits description length to avoid exceeding Discord's character limits.
- Provides customization for the Discord message, including:
- Webhook URL, message color, footer text/icon, and timestamp.
- Username and avatar for the webhook.
- Optional message content outside the embed.
- Instantly share release changelogs with your Discord server.
- Highly customizable message appearance and content.
- Simple setup—no coding required.
- Supports advanced formatting and filtering for professional notifications.
---
## Output
## Features
![output](https://i.imgur.com/Zf3TXtb.png)
- **Automatic Release Notifications:** Sends a Discord embed when a GitHub release is published.
- **Clean Formatting:**
- Removes carriage returns and HTML comments.
- Optimizes whitespace and paragraph spacing.
- **Mention & Link Handling:**
- Converts `@mentions` to clickable GitHub profile links.
- Converts PR, issue, and changelog URLs to Markdown links.
- Optionally removes PR, commit, and issue links for cleaner messages.
- **Heading Reduction:**
- Optionally reduces heading sizes for compact display.
- **Custom Embed Appearance:**
- Set color, username, avatar, footer, and more.
- **Length Management:**
- Ensures messages fit Discord's embed limits, trimming and linking as needed.
- **Error Handling:**
- Clear errors for missing or invalid inputs.
- **Easy Integration:**
- Works with any public or private repository.
## Configuration
---
| Variable | Required | Default | Description |
|-----------------|----------|-------------------------------------------------------------------------------------------------------|-------------------------------------------------|
| webhook_url | ✔ | | Discord's webhook url. Use GH repo secrets. |
| color | ❌ | "2105893" | Decimal color value for embed. |
| username | ❌ | | String username for webhook. |
| avatar_url | ❌ | | String url to webhook avatar picture. |
| content | ❌ | | String content for webhook. |
| footer_title | ❌ | | String title for the webhook footer. |
| footer_icon_url | ❌ | | String url for the webhook footer picture. |
| footer_timestamp| ❌ | | Boolean to enable footer timestamp. |
| max_description | ❌ | "4096" | Max length for the description. |
| reduce_headings | ❌ | false | Converts H3 to bold, h2 to bold & underline. |
## Quick Start
## Example Usage
### 1. Create a Discord Webhook
`.github/workflows/github-releases-to-discord.yml`
- Go to your Discord server settings → **Integrations****Webhooks**.
- Click **Create Webhook** and copy the webhook URL.
### 2. Add the Action to Your Workflow
Create (or update) `.github/workflows/github-releases-to-discord.yml`:
```yaml
on:
@@ -51,7 +56,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Github Releases To Discord
- name: GitHub Releases to Discord
uses: SethCohen/github-releases-to-discord@v1
with:
webhook_url: ${{ secrets.WEBHOOK_URL }}
@@ -60,72 +65,118 @@ jobs:
avatar_url: "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png"
content: "||@everyone||"
footer_title: "Changelog"
footer_icon_url: "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png"
footer_timestamp: true
max_description: '4096'
reduce_headings: true
```
## Setup Instructions
### 3. Add Your Webhook URL as a Secret
1. Open your **Server Settings** and head into the **Integrations** tab:
2. Click the "**Create Webhook**" button to create a new webhook!
![create webhook](https://support.discord.com/hc/article_attachments/1500000463501/Screen_Shot_2020-12-15_at_4.41.53_PM.png)
![created webhook](https://support.discord.com/hc/article_attachments/360101553853/Screen_Shot_2020-12-15_at_4.51.38_PM.png)
3. Copy the webhook url
4. Create a new GitHub repository secret called WEBHOOK_URL and paste the webhook url into it.
![repository secret](https://i.imgur.com/hAaNOds.png)
5. Save the secret.
6. Add the secret to your action configuration.
- In your GitHub repo, go to **Settings → Secrets and variables → Actions**.
- Add a new secret named `WEBHOOK_URL` and paste your Discord webhook URL.
And you're done! Whenever you create a new release, the workflow should run and, if properly setup, post to your specified Discord channel.
---
## Configuration Options
| Input Name | Required | Default | Description |
|-------------------------------|----------|-------------|--------------------------------------------------------------------|
| `webhook_url` | ✔ | | Discord webhook URL (use a GitHub secret). |
| `color` | ❌ | 2105893 | Embed color (decimal). |
| `username` | ❌ | | Webhook username. |
| `avatar_url` | ❌ | | Webhook avatar image URL. |
| `custom_html_url` | ❌ | | Custom URL for the embed title (overrides GitHub release URL). |
| `content` | ❌ | | Additional message content (e.g., `@everyone`). |
| `footer_title` | ❌ | | Footer title. |
| `footer_icon_url` | ❌ | | Footer icon image URL. |
| `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. |
---
## Example Output
![Discord Embed Example](https://i.imgur.com/ovr0gTL.png)
---
## Best Practices & Notes
- **Use Secrets for Webhook URLs:** Never commit your Discord webhook URL directly to your repository.
- **Discord Embed Limits:**
- Title: 256 characters max
- Description: 4096 characters max
- The action will trim and link if limits are exceeded.
- **Release Body Formatting:**
- Use Markdown in your release notes for best results.
- **Private Repos:**
- The action works for both public and private repositories.
---
## Troubleshooting & FAQ
**Q: The action didn't post to Discord!**
- Check that your webhook URL is correct and not expired.
- Ensure the `webhook_url` secret is set in your repository.
- Review the Actions log for error messages.
**Q: My message is cut off.**
- Discord has strict embed limits. The action trims long messages and adds a link if needed.
**Q: How do I customize the embed?**
- Use the configuration options above to set color, username, avatar, footer, and more.
**Q: Can I mention everyone or specific roles?**
- Use the `content` input (e.g., `content: "@everyone"`).
---
## Contributing
If you have suggestions for how GitHub Releases To Discord Action could be improved, or want to report a bug, open an issue! We'd love all and any contributions.
We welcome contributions! To get started:
1. Fork the repository.
2. Install node and run `npm install`.
3. Install [Github Action tester `act`](https://github.com/nektos/act)
4. Create a sample test Release file to simulate a webhook payload object such as `tests/sample-test-release.json` with the following structure:
```json
{
"action": "published",
"release": {
...
},
"repository": {
...
},
"sender": {
...
}
}
```
1. **Fork** this repository.
2. **Clone** your fork and run `npm install`.
3. **Create a test release payload:**
- Copy `tests/sample-test-release.json` and edit as needed.
4. **Create a `.env` file** in the root with your webhook and config (see below):
This file will be used to test the action locally and simulate a real release event webhook payload. Refer to the [GitHub Webhook documentation](https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=published#release) and the [Github API Documentation](https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-a-release) for more information on the webhook payload structure.
```env
INPUT_WEBHOOK_URL=your_webhook_url
INPUT_COLOR=2105893
...
```
6. Fill the test json file with the necessary fields to simulate a release event.
5. **Test locally** with [`act`](https://github.com/nektos/act):
5. Create a test file called `.env` in the main root of the project with the following environmental variables:
```bash
act release -e tests/sample-test-release.json
```
```bash
INPUT_WEBHOOK_URL=
INPUT_COLOR=
INPUT_USERNAME=
INPUT_AVATAR_URL=
INPUT_CONTENT=
INPUT_FOOTER_TITLE=
INPUT_FOOTER_ICON_URL=
INPUT_FOOTER_TIMESTAMP=
INPUT_MAX_DESCRIPTION=
INPUT_REDUCE_HEADINGS=
```
6. **Make your changes** and commit using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
7. **Open a pull request** with a clear description of your changes.
8. Fill the `.env` file with your chosen environmental variables values.
9. Create a Discord webhook in your server, making sure to add the webhook url to the `.env` file under `INPUT_WEBHOOK_URL=`.
10. Run the action locally with `act release -e <your.json>` (e.g. `act release -e tests/sample-test-release.json`) and check the output in your Discord server.
11. Confirm that the action works as expected.
12. Make your changes and commit them: `git commit -m '<commit_message>'`. Please follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
13. Create the pull request.
---
## License
[MIT License](LICENSE)
---
## Support & Feedback
- **Issues:** [Open an issue](https://github.com/SethCohen/github-releases-to-discord/issues) for bugs, questions, or feature requests.
- **Pull Requests:** Contributions are welcome—see above!
---
## Acknowledgements
- Inspired by the needs of open source maintainers and Discord communities.
- Built and maintained by [SethCohen](https://github.com/SethCohen).
+8 -1
View File
@@ -15,6 +15,9 @@ inputs:
avatar_url:
description: String url to webhook avatar picture.
required: false
custom_html_url:
description: If filled, replaces github's release url with your custom html url.
required: false
content:
description: String content for webhook.
required: false
@@ -31,6 +34,10 @@ inputs:
description: Max length for the description.
required: false
default: '4096'
remove_github_reference_links:
description: Remove any PR, commit, and issue links from the description.
required: false
default: 'false'
reduce_headings:
description: Converts H3 to bold, h2 to bold & underline.
required: false
@@ -40,4 +47,4 @@ runs:
main: 'index.js'
branding:
icon: file-text
color: blue
color: blue
+71 -30
View File
@@ -37,6 +37,23 @@ const convertMentionsToLinks = (text) => text.replace(
(match, name) => `[@${name}](https://github.com/${name})`
);
/**
* Removes any GitHub PR, commit, or issue links from the text, including markdown links.
* @param {string} text The input text.
* @returns {string} The text without GitHub PR and commit links.
*/
const removeGithubReferenceLinks = (text) => text
// Remove markdown links to PRs, commits, and issues
.replace(/\[[^\]]*\]\(https:\/\/github\.com\/[^(\s)]+\/pull\/\d+\)/g, '')
.replace(/\[[^\]]*\]\(https:\/\/github\.com\/[^(\s)]+\/commit\/\w+\)/g, '')
.replace(/\[[^\]]*\]\(https:\/\/github\.com\/[^(\s)]+\/issues\/\d+\)/g, '')
// Remove bare PR, commit, and issue URLs
.replace(/https:\/\/github\.com\/[^(\s)]+\/pull\/\d+/g, '')
.replace(/https:\/\/github\.com\/[^(\s)]+\/commit\/\w+/g, '')
.replace(/https:\/\/github\.com\/[^(\s)]+\/issues\/\d+/g, '')
// Remove empty parentheses left behind
.replace(/\(\s*\)/g, '');
/**
* Reduces headings to a smaller format if 'reduce_headings' is enabled.
* Converts H3 to bold+underline, H2 to bold.
@@ -48,7 +65,7 @@ const reduceHeadings = (text) => text
.replace(/^##\s+(.+)$/gm, '**$1**'); // Convert H2 to bold
/**
* Converts PR links, issue links, and changelog links to markdown format.
* Converts PR, issue, and changelog links to markdown format, ignoring existing markdown links.
* - PR links: `https://github.com/OWNER/REPO/pull/1` -> `[PR #1](https://github.com/OWNER/REPO/pull/1)`
* - Issue links: `https://github.com/OWNER/REPO/issues/1` -> `[Issue #30](https://github.com/OWNER/REPO/issues/1)`
* - Changelog links: `https://github.com/OWNER/REPO/compare/v1.0.0...v1.1.0` -> `[v1.0.0...v1.1.0](https://github.com/OWNER/REPO/compare/v1.0.0...v1.1.0)`
@@ -56,25 +73,21 @@ const reduceHeadings = (text) => text
* @returns {string} The text with links converted to markdown format.
*/
const convertLinksToMarkdown = (text) => {
// Convert PR links
text = text.replace(
/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/pull\/(\d+)/g,
(match, owner, repo, prNumber) => `[PR #${prNumber}](${match})`
);
// Extract existing markdown links and replace them with placeholders
const markdownLinks = [];
const textWithoutMarkdownLinks = text.replace(/\[.*?\]\(.*?\)/g, (link) => {
markdownLinks.push(link);
return `__MARKDOWN_LINK_PLACEHOLDER_${markdownLinks.length - 1}__`;
});
// Convert issue links
text = text.replace(
/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/issues\/(\d+)/g,
(match, owner, repo, issueNumber) => `[Issue #${issueNumber}](${match})`
);
// Convert standalone PR, issue, and changelog URLs to markdown format
let processedText = textWithoutMarkdownLinks
.replace(/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/pull\/(\d+)/g, (match, owner, repo, prNumber) => `[PR #${prNumber}](${match})`)
.replace(/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/issues\/(\d+)/g, (match, owner, repo, issueNumber) => `[Issue #${issueNumber}](${match})`)
.replace(/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/compare\/([v\w.-]+)\.\.\.([v\w.-]+)/g, (match, owner, repo, fromVersion, toVersion) => `[${fromVersion}...${toVersion}](${match})`);
// Convert changelog comparison links
text = text.replace(
/https:\/\/github\.com\/([\w-]+)\/([\w-]+)\/compare\/([v\w.-]+)\.\.\.([v\w.-]+)/g,
(match, owner, repo, fromVersion, toVersion) => `[${fromVersion}...${toVersion}](${match})`
);
return text;
// Reinsert the original markdown links
return processedText.replace(/__MARKDOWN_LINK_PLACEHOLDER_(\d+)__/g, (match, index) => markdownLinks[parseInt(index, 10)]);
};
/**
@@ -86,6 +99,10 @@ const formatDescription = (description) => {
let edit = removeCarriageReturn(description);
edit = removeHTMLComments(edit);
edit = reduceNewlines(edit);
if (core.getBooleanInput('remove_github_reference_links')) {
edit = removeGithubReferenceLinks(edit);
}
edit = convertMentionsToLinks(edit);
edit = convertLinksToMarkdown(edit);
edit = edit.trim();
@@ -168,6 +185,9 @@ const buildEmbedMessage = (name, html_url, description) => {
footer: {}
};
if (core.getInput('custom_html_url')) {
embedMsg.url = core.getInput('custom_html_url');
}
if (core.getInput('footer_title')) {
embedMsg.footer.text = limitString(core.getInput('footer_title'), 2048);
}
@@ -182,21 +202,42 @@ const buildEmbedMessage = (name, html_url, description) => {
};
/**
* Sends the webhook request to Discord.
* Sends the webhook request to Discord, handling rate limits (429) with retries.
* @param {string} webhookUrl The URL of the Discord webhook.
* @param {object} requestBody The payload to send in the webhook.
* @param {number} [maxRetries=3] Maximum number of retries on rate limit.
*/
const sendWebhook = async (webhookUrl, requestBody) => {
try {
const response = await fetch(`${webhookUrl}?wait=true`, {
method: 'POST',
body: JSON.stringify(requestBody),
headers: { 'Content-Type': 'application/json' }
});
const data = await response.json();
core.info(JSON.stringify(data));
} catch (err) {
core.setFailed(err.message);
const sendWebhook = async (webhookUrl, requestBody, maxRetries = 3) => {
let attempt = 0;
while (attempt <= maxRetries) {
try {
const response = await fetch(`${webhookUrl}?wait=true`, {
method: 'POST',
body: JSON.stringify(requestBody),
headers: { 'Content-Type': 'application/json' }
});
if (response.status === 429) {
// Rate limited, get retry-after
const retryAfter = parseInt(response.headers.get('retry-after') || '1', 10);
core.warning(`Rate limited by Discord. Retrying after ${retryAfter} seconds (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(res => setTimeout(res, retryAfter * 1000));
attempt++;
continue;
}
const data = await response.json();
if (!response.ok) {
core.setFailed(`Discord webhook error: ${JSON.stringify(data)}`);
} else {
core.info(JSON.stringify(data));
}
break;
} catch (err) {
core.setFailed(err.message);
break;
}
}
if (attempt > maxRetries) {
core.setFailed('Exceeded maximum Discord webhook retry attempts due to rate limiting.');
}
};
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "github-releases-to-discord",
"version": "1.16.0",
"version": "1.18.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "github-releases-to-discord",
"version": "1.16.0",
"version": "1.18.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "github-releases-to-discord",
"version": "1.16.0",
"version": "1.18.0",
"description": "A GitHub Action that automatically sends a stylized Discord webhook of a GitHub Release description to a specified Discord channel.",
"type": "module",
"main": "index.js",
+12
View File
@@ -0,0 +1,12 @@
{
"action": "published",
"release": {
"html_url": "https://example.com/releases/tag/v1.0.0",
"name": "v1.0.0",
"body": "## [1.0.0](https://example.com/compare/v0.9.0...v1.0.0) (1970-01-01)\n\n### Features\n* **core:** added initial release ([abc1234](https://example.com/commit/abc1234))\n* **api:** implemented endpoints ([def5678](https://example.com/commit/def5678))\n\n### Bug Fixes\n* **ui:** fixed button alignment ([#42](https://example.com/issues/42)) ([789abcd](https://example.com/commit/789abcd))\n\n### Miscellaneous\n* see [PR #7](https://example.com/pull/7) for details\n"
},
"repository": {
"full_name": "example/repo",
"html_url": "https://example.com/example/repo"
}
}