Compare commits

...

10 Commits

Author SHA1 Message Date
dependabot[bot]
ed72c423be
Bump anothrNick/github-tag-action from 1.61.0 to 1.62.0 (#20407)
Bumps [anothrNick/github-tag-action](https://github.com/anothrNick/github-tag-action) from 1.61.0 to 1.62.0.
- [Release notes](https://github.com/anothrNick/github-tag-action/releases)
- [Commits](https://github.com/anothrNick/github-tag-action/compare/1.61.0...1.62.0)

---
updated-dependencies:
- dependency-name: anothrNick/github-tag-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 23:49:53 +01:00
Vertex-kb
bc6db2823c
[Keyboard] Update angle65 VID/PID (#20401) 2023-04-10 13:32:16 -06:00
Nick Brassel
fb706f42a2
Run CI builds for each push, limit queued workflow depth to 1. (#20362) 2023-04-09 22:38:09 +01:00
Ryan
9132c64389
Add numpad 0-9 to second layer, update keycodes for QMK 0.17.5, fix layout (#20375) 2023-04-09 22:32:40 +01:00
Dasky
6e0acf0548
Add autocomplete to generate-compilation-database (#20387) 2023-04-09 17:41:30 +01:00
Drashna Jaelre
2c375e6478
[Keyboard] Add audio support to Adafruit MacroPad RP2040 (#20353) 2023-04-08 10:59:13 +10:00
Duncan Sutherland
a5e68e5f74
Convertors documentation: Removed duplicate table entry (#20360) 2023-04-07 23:11:56 +01:00
Joel Challis
e9b36bebb2
Avoid generating empty ENCODER_RESOLUTION (#20179) 2023-04-07 14:07:59 +01:00
Nick Brassel
df7b56e0ea
Fixup CI build variables. (#20357) 2023-04-07 18:38:16 +10:00
Nick Brassel
2e766a9c7a
Add Discord webhook at end of each CI run. (#20355) 2023-04-07 16:37:06 +10:00
17 changed files with 153 additions and 30 deletions

View File

@ -31,7 +31,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Bump version and push tag - name: Bump version and push tag
uses: anothrNick/github-tag-action@1.61.0 uses: anothrNick/github-tag-action@1.62.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEFAULT_BUMP: 'patch' DEFAULT_BUMP: 'patch'

View File

@ -4,22 +4,27 @@ permissions:
contents: read contents: read
on: on:
push:
branches: [master, develop]
workflow_dispatch: workflow_dispatch:
schedule: inputs:
- cron: '0 0,12 * * *' branch:
type: choice
description: 'Branch to build'
options: [master, develop]
concurrency: ci_build-${{ github.event.inputs.branch || github.ref_name }}
jobs: jobs:
ci_builds: ci_builds:
if: github.repository == 'qmk/qmk_firmware'
name: "CI Build" name: "CI Build"
runs-on: self-hosted runs-on: self-hosted
timeout-minutes: 1380 timeout-minutes: 1380
if: github.repository == 'qmk/qmk_firmware'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
branch: [master, develop]
keymap: [default, via] keymap: [default, via]
container: qmkfm/qmk_cli container: qmkfm/qmk_cli
@ -31,7 +36,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
ref: ${{ matrix.branch }} ref: ${{ github.event.inputs.branch || github.ref }}
- name: Install dependencies - name: Install dependencies
run: pip3 install -r requirements.txt run: pip3 install -r requirements.txt
@ -51,10 +56,19 @@ jobs:
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
if: always() if: always()
with: with:
name: artifacts-${{ matrix.branch }}-${{ matrix.keymap }} name: artifacts-${{ github.event.inputs.branch || github.ref_name }}-${{ matrix.keymap }}
if-no-files-found: ignore if-no-files-found: ignore
path: | path: |
*.bin *.bin
*.hex *.hex
*.uf2 *.uf2
.build/failed.* .build/failed.*
- name: 'CI Discord Notification'
if: always()
working-directory: util/ci/
env:
DISCORD_WEBHOOK: ${{ secrets.CI_DISCORD_WEBHOOK }}
run: |
python3 -m pip install -r requirements.txt
python3 ./discord-results.py --branch ${{ github.event.inputs.branch || github.ref_name }} --keymap ${{ matrix.keymap }} --url ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

View File

@ -17,7 +17,6 @@ Currently the following converters are available:
| `promicro` | `bit_c_pro` | | `promicro` | `bit_c_pro` |
| `promicro` | `stemcell` | | `promicro` | `stemcell` |
| `promicro` | `bonsai_c4` | | `promicro` | `bonsai_c4` |
| `promicro` | `elite_pi` |
| `promicro` | `rp2040_ce` | | `promicro` | `rp2040_ce` |
| `promicro` | `elite_pi` | | `promicro` | `elite_pi` |
| `promicro` | `helios` | | `promicro` | `helios` |

View File

@ -42,9 +42,14 @@
#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED GP13 #define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED GP13
#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 500U #define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 500U
/* Audio (Unsupported for now)*/ /* Audio */
// #define AUDIO_PIN GP16 #define AUDIO_PIN GP16
// #define SPEAKER_SHUTDOWN GP14 #define AUDIO_PWM_DRIVER PWMD0
#define AUDIO_PWM_CHANNEL RP2040_PWM_CHANNEL_A
#define AUDIO_INIT_DELAY
#define AUDIO_CLICKY
#define SPEAKER_SHUTDOWN GP14
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE

View File

@ -26,3 +26,6 @@
#undef SPI_SELECT_MODE #undef SPI_SELECT_MODE
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD #define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
#undef HAL_USE_PWM
#define HAL_USE_PWM TRUE

View File

@ -18,17 +18,25 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT( [0] = LAYOUT(
KC_MUTE, LT(1,KC_MUTE),
KC_ENT, KC_0, KC_BSPC, KC_ENT, KC_0, KC_BSPC,
KC_7, KC_8, KC_9, KC_7, KC_8, KC_9,
KC_4, KC_5, KC_6, KC_4, KC_5, KC_6,
KC_1, KC_2, KC_3 KC_1, KC_2, KC_3
) ),
[1] = LAYOUT(
_______,
CK_TOGG, AU_TOGG, _______,
_______, _______, _______,
_______, _______, _______,
_______, _______, _______
),
}; };
#ifdef ENCODER_MAP_ENABLE #ifdef ENCODER_MAP_ENABLE
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, [0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
}; };
#endif #endif
@ -111,4 +119,3 @@ bool oled_task_user(void) {
} }
#endif #endif

View File

@ -18,7 +18,7 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT( [0] = LAYOUT(
KC_MUTE, LT(1,KC_MUTE),
KC_ENT, KC_0, KC_BSPC, KC_ENT, KC_0, KC_BSPC,
KC_7, KC_8, KC_9, KC_7, KC_8, KC_9,
KC_4, KC_5, KC_6, KC_4, KC_5, KC_6,
@ -26,7 +26,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
), ),
[1] = LAYOUT( [1] = LAYOUT(
_______, _______,
_______, _______, _______, CK_TOGG, AU_TOGG, _______,
_______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______,
_______, _______, _______ _______, _______, _______
@ -135,4 +135,3 @@ bool oled_task_user(void) {
} }
#endif #endif

View File

@ -41,6 +41,31 @@ led_config_t g_led_config = { {
#endif #endif
#ifdef AUDIO_ENABLE
void keyboard_pre_init_kb(void) {
// ensure pin is set and enabled pre-audio init
setPinOutput(SPEAKER_SHUTDOWN);
writePinHigh(SPEAKER_SHUTDOWN);
keyboard_pre_init_user();
}
void keyboard_post_init_kb(void) {
// set pin based on active status
writePin(SPEAKER_SHUTDOWN, audio_is_on());
keyboard_post_init_user();
}
void audio_on_user(void) {
writePinHigh(SPEAKER_SHUTDOWN);
}
void audio_off_user(void) {
// needs a delay or it runs right after play note.
wait_ms(200);
writePinLow(SPEAKER_SHUTDOWN);
}
#endif
#ifdef ENCODER_ENABLE #ifdef ENCODER_ENABLE
bool encoder_update_kb(uint8_t index, bool clockwise) { bool encoder_update_kb(uint8_t index, bool clockwise) {
if (!encoder_update_user(index, clockwise)) { return false; } if (!encoder_update_user(index, clockwise)) { return false; }

View File

@ -20,3 +20,6 @@
#undef RP_SPI_USE_SPI1 #undef RP_SPI_USE_SPI1
#define RP_SPI_USE_SPI1 TRUE #define RP_SPI_USE_SPI1 TRUE
#undef RP_PWM_USE_PWM0
#define RP_PWM_USE_PWM0 TRUE

View File

@ -9,8 +9,8 @@ COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = yes # Enable N-Key Rollover NKRO_ENABLE = yes # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output AUDIO_ENABLE = yes # Audio output
# AUDIO_DRIVER = pwm_software AUDIO_DRIVER = pwm_hardware
ENCODER_ENABLE = yes ENCODER_ENABLE = yes
RGB_MATRIX_ENABLE = yes RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = WS2812 RGB_MATRIX_DRIVER = WS2812

View File

@ -1,7 +1,21 @@
#include QMK_KEYBOARD_H #include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_ansi(KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_GRV, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT), [0] = LAYOUT_ansi(QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
[1] = LAYOUT_ansi(KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_INS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, BL_DOWN,BL_TOGG, BL_UP, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, MO(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R), KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
[2] = LAYOUT_ansi(KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, QK_BOOT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO) KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_GRV,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_HOME, MO(1), KC_END, KC_LEFT, KC_DOWN, KC_RGHT),
[1] = LAYOUT_ansi(KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS,
KC_TRNS, KC_P7, KC_P8, KC_P9, KC_NUM, BL_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME,
KC_TRNS, KC_P4, KC_P5, KC_P6, KC_TRNS, BL_TOGG, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_END,
KC_TRNS, KC_P1, KC_P2, KC_P3, KC_TRNS, BL_DOWN, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, MO(2), KC_TRNS, KC_TRNS, KC_RALT, KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT),
[2] = LAYOUT_ansi(KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, KC_NO, QK_BOOT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO)
}; };

View File

@ -4,8 +4,8 @@
"url": "", "url": "",
"maintainer": "EasonQian1, Vertex-kb", "maintainer": "EasonQian1, Vertex-kb",
"usb": { "usb": {
"vid": "0x7374", "vid": "0x9954",
"pid": "0x9770", "pid": "0x9970",
"device_version": "0.0.1" "device_version": "0.0.1"
}, },
"processor": "STM32F103", "processor": "STM32F103",

View File

@ -7,7 +7,7 @@ from milc import cli
from qmk.path import normpath from qmk.path import normpath
py_file_suffixes = ('py',) py_file_suffixes = ('py',)
py_dirs = ['lib/python'] py_dirs = ['lib/python', 'util/ci']
def yapf_run(files): def yapf_run(files):

View File

@ -15,6 +15,8 @@ from milc import cli, MILC
from qmk.commands import create_make_command from qmk.commands import create_make_command
from qmk.constants import QMK_FIRMWARE from qmk.constants import QMK_FIRMWARE
from qmk.decorators import automagic_keyboard, automagic_keymap from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.keymap import keymap_completer
@lru_cache(maxsize=10) @lru_cache(maxsize=10)
@ -74,8 +76,8 @@ def parse_make_n(f: Iterator[str]) -> List[Dict[str, str]]:
return records return records
@cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard\'s name')
@cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') @cli.argument('-km', '--keymap', completer=keymap_completer, help='The keymap\'s name')
@cli.subcommand('Create a compilation database.') @cli.subcommand('Create a compilation database.')
@automagic_keyboard @automagic_keyboard
@automagic_keymap @automagic_keymap
@ -104,7 +106,7 @@ def generate_compilation_database(cli: MILC) -> Union[bool, int]:
if not command: if not command:
cli.log.error('You must supply both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.') cli.log.error('You must supply both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.')
cli.echo('usage: qmk compiledb [-kb KEYBOARD] [-km KEYMAP]') cli.echo('usage: qmk generate-compilation-database [-kb KEYBOARD] [-km KEYMAP]')
return False return False
# remove any environment variable overrides which could trip us up # remove any environment variable overrides which could trip us up

View File

@ -119,7 +119,9 @@ def generate_encoder_config(encoder_json, config_h_lines, postfix=''):
config_h_lines.append(generate_define(f'ENCODERS_PAD_B{postfix}', f'{{ {", ".join(b_pads)} }}')) config_h_lines.append(generate_define(f'ENCODERS_PAD_B{postfix}', f'{{ {", ".join(b_pads)} }}'))
if None in resolutions: if None in resolutions:
cli.log.debug("Unable to generate ENCODER_RESOLUTION configuration") cli.log.debug(f"Unable to generate ENCODER_RESOLUTION{postfix} configuration")
elif len(resolutions) == 0:
cli.log.debug(f"Skipping ENCODER_RESOLUTION{postfix} configuration")
elif len(set(resolutions)) == 1: elif len(set(resolutions)) == 1:
config_h_lines.append(generate_define(f'ENCODER_RESOLUTION{postfix}', resolutions[0])) config_h_lines.append(generate_define(f'ENCODER_RESOLUTION{postfix}', resolutions[0]))
else: else:

49
util/ci/discord-results.py Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
import argparse
import os
import re
import sys
from pathlib import Path
from discord_webhook import DiscordWebhook, DiscordEmbed
parser = argparse.ArgumentParser(prog='discord-results.py', description='Sends a Discord webhook notification at the end of a CI run.')
parser.add_argument('-b', '--branch')
parser.add_argument('-k', '--keymap')
parser.add_argument('-u', '--url')
args = parser.parse_args()
qmk_dir = Path(__file__).resolve().parents[2].resolve()
keyboard_re = re.compile(r'CI Metadata: KEYBOARD=(.*)$', re.MULTILINE)
keymap_re = re.compile(r'CI Metadata: KEYMAP=(.*)$', re.MULTILINE)
successful_builds = sum([len(list(qmk_dir.glob(f'*.{extension}'))) for extension in ['uf2', 'bin', 'hex']])
failures = list(sorted([f.resolve() for f in (qmk_dir / '.build/').glob('failed.log.*')]))
failed_builds = []
for f in failures:
with open(f) as fh:
data = fh.read()
kb = keyboard_re.search(data).group(1)
km = keymap_re.search(data).group(1)
failed_builds.append(f'{kb}:{km}')
webhook = DiscordWebhook(url=os.getenv('DISCORD_WEBHOOK'), username="QMK GitHub CI")
if len(failed_builds) > 0:
failstr = ''
for f in failed_builds:
if len(failstr) >= 1800:
failstr += '<<snip>>'
break
failstr += f'{f}\n'
embed = DiscordEmbed(title=f':infinity: CI Build Failure ({args.branch}, {args.keymap})', description=f'**{successful_builds}** builds succeeded, **{len(failed_builds)}** builds failed:```{failstr}```', color='ff9999')
else:
embed = DiscordEmbed(title=f':infinity: CI Build Success ({args.branch}, {args.keymap})', description=f'**{successful_builds}** builds succeeded.', color='99ff99')
embed.add_embed_field(name='Build Target', value=f'[**{args.branch}**](https://github.com/qmk/qmk_firmware/tree/{args.branch}) / **{args.keymap}** keymap')
embed.add_embed_field(name='Workflow Run', value=f'[**Link**]({args.url})')
embed.set_timestamp()
webhook.add_embed(embed)
webhook.execute()

1
util/ci/requirements.txt Normal file
View File

@ -0,0 +1 @@
discord-webhook