From 22f6f260d2e76c0c8c665140ba64bc48a7e61e7a Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Wed, 28 Dec 2022 15:59:36 -0600 Subject: [PATCH] ci: Fix broken URLs in discord notification In addition: - URL processing is now data driven. It pulls URLs from the latest Github Release and uses those. This makes the notification more extensible. If we add new artifacts later to the release, they "automatically" get published in the discord notification as well. New platforms must still be explicitly added, though. - Added contributing guidance for testing the notification script. --- .github/workflows/notify.yml | 49 +++++++++++++++---------- CONTRIBUTING.md | 29 +++++++++++++++ ci/notify/discord_notify.py | 69 ++++++++++++++++++++++-------------- 3 files changed, 102 insertions(+), 45 deletions(-) diff --git a/.github/workflows/notify.yml b/.github/workflows/notify.yml index ac7aed17..e7b8c82d 100644 --- a/.github/workflows/notify.yml +++ b/.github/workflows/notify.yml @@ -19,31 +19,44 @@ jobs: name: Discord Notification runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Checkout Source Code + uses: actions/checkout@v3 + + - name: Setup Inputs + run: | + cat >> $GITHUB_ENV <<"EOL" + INPUT_TAG="${{ env.TAG }}" + INPUT_ORG_REPO="${{ github.repository }}" + EOL - - uses: octokit/request-action@v2.x + - name: Get Release Info + uses: octokit/request-action@v2.x id: release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: route: GET /repos/{org_repo}/releases/tags/{tag} - org_repo: ${{ github.repository }} - tag: ${{ env.TAG }} - - uses: actions/setup-python@v2 + # Write changelog to a file to avoid certain characters from being processed by the shell + - name: Get Information from Release + run: | + echo '${{ steps.release.outputs.data }}' > release.json + jq -r '.assets[].browser_download_url' release.json > assets.txt + jq -r '.body' release.json > changelog.txt + + - name: Setup Python + uses: actions/setup-python@v4 with: python-version: '3.x' - - run: pip install discord-webhook - - # Write changelog to a file to avoid certain characters from being processed by the shell - - run: | - cat >changelog.txt <<"EOL" - ${{ fromJSON(steps.release.outputs.data).body }} - EOL - - - run: | - python ci/notify/discord_notify.py \ - '${{ env.TAG }}' \ - '${{ secrets.DISCORD_WEBHOOK }}' \ - changelog.txt + - name: Install Discord Webhook Python Module + run: pip install "discord-webhook==1.0.0" + + - name: Send Discord Notification + run: > + python ci/notify/discord_notify.py + --version ${{ env.TAG }} + --repo ${{ github.repository }} + --webhook-url ${{ secrets.DISCORD_WEBHOOK }} + --changelog changelog.txt + --assets assets.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e6e99ec..5b3ae8e3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,3 +144,32 @@ The Github Workflows manage the release process after the push by doing the foll Execute the `Update-Gitignore.ps1` script using Powershell. The working directory *must* be the root of the repo. This will pull the latest relevant `.gitignore` patterns from [gitignore.io](https://gitignore.io) and commit them automatically to your current branch. + +## Testing Discord Notifier + +Use Postman to make an HTTP `GET` request to the following URL. Note that `v4.0.0` can be any +release. + +```txt +https://api.github.com/recyclarr/recyclarr/releases/tags/v4.0.0 +``` + +Copy the resulting response JSON to a file named `ci/notify/release.json`. In the `ci/notify` +directory, run these commands to generate the other files needed: + +```bash +jq -r '.assets[].browser_download_url' release.json > assets.txt +jq -r '.body' release.json > changelog.txt +``` + +Also be sure to grab a discord webhook URL to a personal test server of yours. Then run the command +below (using a Bash terminal) + +```bash +python ./discord_notify.py \ + --version v4.0.0 \ + --repo recyclarr/recyclarr \ + --webhook-url https://discord.com/api/webhooks/your_webhook_url \ + --changelog ./changelog.txt \ + --assets ./assets.txt +``` diff --git a/ci/notify/discord_notify.py b/ci/notify/discord_notify.py index c24cc0d8..1625f70b 100644 --- a/ci/notify/discord_notify.py +++ b/ci/notify/discord_notify.py @@ -1,22 +1,17 @@ +from collections import defaultdict +import re from discord_webhook import DiscordWebhook, DiscordEmbed -import sys +import argparse -version = sys.argv[1] -if not version: - print('Pass version as first argument') - exit(1) +parser = argparse.ArgumentParser() +parser.add_argument('--repo', required=True) +parser.add_argument('--version', required=True) +parser.add_argument('--webhook-url', required=True) +parser.add_argument('--changelog', required=True) +parser.add_argument('--assets', required=True) +args = parser.parse_args() -webhook_url = sys.argv[2] -if not webhook_url: - print('Pass webhook URL as second argument') - exit(1) - -changelog = sys.argv[3] -if not changelog: - print('Pass path to changelog file as third argument') - exit(1) - -with open(changelog, 'r') as f: +with open(args.changelog, 'r') as f: changelog_text = f.read() mkdown_desc = f''' @@ -27,25 +22,45 @@ mkdown_desc = f''' ''' embed = DiscordEmbed( - title=f'New Release {version}', + title=f'New Release {args.version}', description=mkdown_desc, - url=f'https://github.com/recyclarr/recyclarr/releases/tag/{version}' - ) + url=f'https://github.com/recyclarr/recyclarr/releases/tag/{args.version}' +) embed.set_author( name='Recyclarr', url='https://github.com/recyclarr/recyclarr', icon_url='https://github.com/recyclarr/recyclarr/blob/master/ci/notify/trash-icon.png?raw=true') -def add_links(os_name, archs, os): - url_base = f'https://github.com/recyclarr/recyclarr/releases/download/{version}' - download_links = ', '.join(f'[{arch}]({url_base}/recyclarr-{os}-{arch}.zip)' for arch in archs) - embed.add_embed_field(name=os_name, value=f'[{download_links}]') +def parse_assets(): + link_groups = defaultdict(list) + with open(args.assets) as file: + for line in file.read().splitlines(): + print(f"Processing {line}") + match = re.search(r"/recyclarr-([\w-]+?)-(\w+)\.", line) + if match: + platform = match.group(1) + arch = match.group(2) + link_groups[platform].append((arch, line)) + + return link_groups + +def add_links(): + platform_display_name = { + 'win': 'Windows', + 'osx': 'macOS', + 'linux': 'Linux' + } + + assets = parse_assets() + for platform in assets.keys(): + links = ', '.join(f'[{arch}]({link})' for (arch, link) in assets[platform]) + if platform in platform_display_name: + os_name = platform_display_name[platform] + embed.add_embed_field(name=os_name, value=f'[{links}]') -add_links('Linux', ('x64', 'arm', 'arm64'), 'linux') -add_links('Windows', ('x64', 'arm64'), 'win') -add_links('MacOS', ('x64', 'arm64'), 'osx') +add_links() -webhook = DiscordWebhook(webhook_url) +webhook = DiscordWebhook(args.webhook_url) webhook.add_embed(embed) print(webhook.execute())