diff options
| -rw-r--r-- | .github/workflows/ci_builds.yml | 12 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/format/python.py | 2 | ||||
| -rwxr-xr-x | util/ci/discord-results.py | 49 | ||||
| -rw-r--r-- | util/ci/requirements.txt | 1 |
4 files changed, 61 insertions, 3 deletions
diff --git a/.github/workflows/ci_builds.yml b/.github/workflows/ci_builds.yml index ce2d0b509e..366b5e0dde 100644 --- a/.github/workflows/ci_builds.yml +++ b/.github/workflows/ci_builds.yml | |||
| @@ -10,12 +10,11 @@ on: | |||
| 10 | 10 | ||
| 11 | jobs: | 11 | jobs: |
| 12 | ci_builds: | 12 | ci_builds: |
| 13 | if: github.repository == 'qmk/qmk_firmware' | ||
| 13 | name: "CI Build" | 14 | name: "CI Build" |
| 14 | runs-on: self-hosted | 15 | runs-on: self-hosted |
| 15 | timeout-minutes: 1380 | 16 | timeout-minutes: 1380 |
| 16 | 17 | ||
| 17 | if: github.repository == 'qmk/qmk_firmware' | ||
| 18 | |||
| 19 | strategy: | 18 | strategy: |
| 20 | fail-fast: false | 19 | fail-fast: false |
| 21 | matrix: | 20 | matrix: |
| @@ -58,3 +57,12 @@ jobs: | |||
| 58 | *.hex | 57 | *.hex |
| 59 | *.uf2 | 58 | *.uf2 |
| 60 | .build/failed.* | 59 | .build/failed.* |
| 60 | |||
| 61 | - name: 'CI Discord Notification' | ||
| 62 | if: always() | ||
| 63 | working-directory: util/ci/ | ||
| 64 | env: | ||
| 65 | DISCORD_WEBHOOK: ${{ secrets.CI_DISCORD_WEBHOOK }} | ||
| 66 | run: | | ||
| 67 | python3 -m pip install -r requirements.txt | ||
| 68 | python3 ./discord-results.py --branch ${{ matrix.branch }} --keymap ${{ matrix.keymap }} --url ${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }} | ||
diff --git a/lib/python/qmk/cli/format/python.py b/lib/python/qmk/cli/format/python.py index 008622cac1..e7b545109f 100755 --- a/lib/python/qmk/cli/format/python.py +++ b/lib/python/qmk/cli/format/python.py | |||
| @@ -7,7 +7,7 @@ from milc import cli | |||
| 7 | from qmk.path import normpath | 7 | from qmk.path import normpath |
| 8 | 8 | ||
| 9 | py_file_suffixes = ('py',) | 9 | py_file_suffixes = ('py',) |
| 10 | py_dirs = ['lib/python'] | 10 | py_dirs = ['lib/python', 'util/ci'] |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | def yapf_run(files): | 13 | def yapf_run(files): |
diff --git a/util/ci/discord-results.py b/util/ci/discord-results.py new file mode 100755 index 0000000000..0c09a4213a --- /dev/null +++ b/util/ci/discord-results.py | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | |||
| 3 | import argparse | ||
| 4 | import os | ||
| 5 | import re | ||
| 6 | import sys | ||
| 7 | from pathlib import Path | ||
| 8 | from discord_webhook import DiscordWebhook, DiscordEmbed | ||
| 9 | |||
| 10 | parser = argparse.ArgumentParser(prog='discord-results.py', description='Sends a Discord webhook notification at the end of a CI run.') | ||
| 11 | parser.add_argument('-b', '--branch') | ||
| 12 | parser.add_argument('-k', '--keymap') | ||
| 13 | parser.add_argument('-u', '--url') | ||
| 14 | args = parser.parse_args() | ||
| 15 | |||
| 16 | qmk_dir = Path(__file__).resolve().parents[2].resolve() | ||
| 17 | |||
| 18 | keyboard_re = re.compile(r'CI Metadata: KEYBOARD=(.*)$', re.MULTILINE) | ||
| 19 | keymap_re = re.compile(r'CI Metadata: KEYMAP=(.*)$', re.MULTILINE) | ||
| 20 | |||
| 21 | successful_builds = sum([len(list(qmk_dir.glob(f'*.{extension}'))) for extension in ['uf2', 'bin', 'hex']]) | ||
| 22 | failures = list(sorted([f.resolve() for f in (qmk_dir / '.build/').glob('failed.log.*')])) | ||
| 23 | failed_builds = [] | ||
| 24 | for f in failures: | ||
| 25 | with open(f) as fh: | ||
| 26 | data = fh.read() | ||
| 27 | kb = keyboard_re.search(data).group(1) | ||
| 28 | km = keymap_re.search(data).group(1) | ||
| 29 | failed_builds.append(f'{kb}:{km}') | ||
| 30 | |||
| 31 | webhook = DiscordWebhook(url=os.getenv('DISCORD_WEBHOOK'), username="QMK GitHub CI") | ||
| 32 | if len(failed_builds) > 0: | ||
| 33 | failstr = '' | ||
| 34 | for f in failed_builds: | ||
| 35 | if len(failstr) >= 1800: | ||
| 36 | failstr += '<<snip>>' | ||
| 37 | break | ||
| 38 | failstr += f'{f}\n' | ||
| 39 | |||
| 40 | 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') | ||
| 41 | else: | ||
| 42 | embed = DiscordEmbed(title=f':infinity: CI Build Success ({args.branch}, {args.keymap})', description=f'**{successful_builds}** builds succeeded.', color='99ff99') | ||
| 43 | |||
| 44 | embed.add_embed_field(name='Build Target', value=f'[**{args.branch}**](https://github.com/qmk/qmk_firmware/tree/{args.branch}) / **{args.keymap}** keymap') | ||
| 45 | embed.add_embed_field(name='Workflow Run', value=f'[**Link**]({args.url})') | ||
| 46 | embed.set_timestamp() | ||
| 47 | |||
| 48 | webhook.add_embed(embed) | ||
| 49 | webhook.execute() | ||
diff --git a/util/ci/requirements.txt b/util/ci/requirements.txt new file mode 100644 index 0000000000..3196568e1a --- /dev/null +++ b/util/ci/requirements.txt | |||
| @@ -0,0 +1 @@ | |||
| discord-webhook | |||
