Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
523b1f2
fix(startup): report an alert channel still holding the sample values…
misiektoja Sep 18, 2026
d94b908
test(startup): cover the unset channel rows and the channel rollups
misiektoja Sep 18, 2026
743d5a8
build: declare version 2.7.1
misiektoja Sep 18, 2026
e9c60e5
docs(release-notes): add the 2.7.1 section
misiektoja Sep 18, 2026
0db007b
fix(runtime): close the outage reminder after the alert it carries
misiektoja Sep 18, 2026
78eed63
test(runtime): cover the deferred outage reminder trailer
misiektoja Sep 18, 2026
ba64e18
fix(runtime): report a change over the window the run observed
misiektoja Sep 18, 2026
45bf7b9
test(runtime): cover the observed change window
misiektoja Sep 18, 2026
92bdd48
docs(release-notes): describe the observed window and the alert kept …
misiektoja Sep 18, 2026
ee9600f
fix(color): keep the whole-line log rules off the startup summary rows
misiektoja Sep 18, 2026
e4d49ca
test(color): cover the summary rows a log keyword must not paint
misiektoja Sep 18, 2026
47578f0
feat(runtime): cap the commit detail a push event reports
misiektoja Sep 20, 2026
119372b
build: declare version 2.8
misiektoja Sep 20, 2026
45fc6f3
test(runtime): cover the push commit and changed-file limits
misiektoja Sep 20, 2026
c98c1dc
docs(site): document the push event commit limits
misiektoja Sep 20, 2026
2222499
docs(release-notes): describe the push event commit limits
misiektoja Sep 20, 2026
ffec52c
feat(startup): name the push event limits in the startup summary
misiektoja Sep 20, 2026
d11d8e0
test(startup): cover the push limit summary rows
misiektoja Sep 20, 2026
03a8060
docs(site): note where the push event limits are reported
misiektoja Sep 20, 2026
dbd9e40
docs(release-notes): mention the push limits in the startup summary
misiektoja Sep 20, 2026
08cb465
fix(color): align the grc recipe
misiektoja Sep 20, 2026
cdf1996
fix(color): keep the padded column before a date out of the date
misiektoja Sep 20, 2026
4b044bb
test(color): cover the padded column before a date
misiektoja Sep 20, 2026
1609de7
feat(alerts): give every failure alert one subject and body and follo…
misiektoja Sep 20, 2026
2f33174
test(alerts): cover the shared failure alert shape and the recovery a…
misiektoja Sep 20, 2026
66a9619
docs: describe the shared failure alert and the connection problems g…
misiektoja Sep 20, 2026
0dbd6dd
docs(release-notes): describe the unified failure alerts in the 2.8 s…
misiektoja Sep 21, 2026
06e1bb6
docs(config): name the recovery alert in the error notification setti…
misiektoja Sep 21, 2026
f740641
fix(config): send each failure to the page that covers it
misiektoja Sep 21, 2026
86d2ea7
fix(alerts): name a transport failure that arrives without a message
misiektoja Sep 21, 2026
b2c082c
fix(alerts): bold the failing since timestamp in the HTML alert body
misiektoja Sep 21, 2026
6527219
fix(alerts): send every profile change as HTML and match the plain te…
misiektoja Sep 21, 2026
9091bfe
test(alerts): cover the HTML alert bodies and their match with the pl…
misiektoja Sep 21, 2026
242948e
docs(config): describe the HTML email part every alert carries
misiektoja Sep 21, 2026
fbca1ea
fix(runtime): keep a failed profile visibility lookup from ending the…
misiektoja Sep 21, 2026
a6a27a3
fix(alerts): bold the outage length in the recovery alert
misiektoja Sep 21, 2026
0ffcb52
fix(runtime): name the monitored account lookup in the degraded featu…
misiektoja Sep 21, 2026
b9d5d62
feat(alerts): tell a channel that missed the failure alert about the …
misiektoja Sep 21, 2026
019d62f
test(runtime): expect the renamed monitored account lookup
misiektoja Sep 21, 2026
81ea957
test(alerts): cover the recovery of a channel that missed the failure…
misiektoja Sep 21, 2026
6e7702b
docs(usage): describe the combined failure and recovery alert
misiektoja Sep 21, 2026
426e99f
fix(runtime): name the public repository list alerts apart from the d…
misiektoja Sep 21, 2026
76bfc0e
fix(runtime): name the operation and the classified cause in a GitHub…
misiektoja Sep 21, 2026
8ae9484
test(runtime): expect the renamed degraded feature notice
misiektoja Sep 21, 2026
0409244
test(runtime): cover the named and classified GitHub retry line
misiektoja Sep 21, 2026
e4f6aee
fix(runtime): retry every GitHub request on one schedule and stop at …
misiektoja Sep 21, 2026
caeb54e
fix(runtime): name a retry line after the feature its caller reports
misiektoja Sep 21, 2026
16c8ad1
test(runtime): cover the shared retry schedule, the outage breaker an…
misiektoja Sep 21, 2026
95e7b11
docs(troubleshooting): explain why only the first request prints its …
misiektoja Sep 21, 2026
3e78899
docs(release-notes): consolidate release notes changes
misiektoja Sep 21, 2026
2038e18
test(alerts): drop the unused pytest import and mark the paired zip s…
misiektoja Sep 21, 2026
85d3a44
test(runtime): expect a network error from the call that is not retried
misiektoja Sep 21, 2026
79aee09
docs(citation): update for the 2.8 release
misiektoja Sep 21, 2026
0867b74
docs(release-notes): date the 2.8 release
misiektoja Sep 21, 2026
aa5036b
build: bump ruff to 0.16.8 in the lint extra
misiektoja Sep 22, 2026
7d97912
chore(pre-commit): run the installed ruff instead of a second pinned …
misiektoja Sep 22, 2026
6c352cb
test(docs): require the lint hook to run the ruff the pinned extra in…
misiektoja Sep 22, 2026
2ce0257
docs(contributing): say the lint hook uses the ruff installed by the …
misiektoja Sep 22, 2026
8db4ba3
ci(codeql): apply source suppressions before uploading results
misiektoja Sep 22, 2026
3fc83ad
test(codeql): cover suppression filtering and upload ordering
misiektoja Sep 22, 2026
82b94d5
docs(contributing): explain CodeQL source suppressions
misiektoja Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/scripts/filter_codeql_sarif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Apply CodeQL source suppressions before uploading SARIF to GitHub."""

import argparse
import json
from pathlib import Path


# Removes accepted source suppressions while retaining all other results and analysis metadata
def filter_source_suppressions(report):
if report.get("version") != "2.1.0" or not isinstance(report.get("runs"), list) or not report["runs"]:
raise ValueError("Expected a SARIF 2.1.0 report with at least one run")
removed = 0
for run in report["runs"]:
if run["tool"]["driver"]["name"] not in ("CodeQL", "CodeQL command-line toolchain") or "results" not in run:
continue
retained = []
for result in run["results"]:
suppressed = any(suppression.get("kind") == "inSource" and suppression.get("status", "accepted") == "accepted" for suppression in (result.get("suppressions") or []))
if suppressed:
removed += 1
else:
retained.append(result)
run["results"] = retained
return removed


# Writes a filtered copy of one CodeQL report and reports how many source suppressions were applied
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("source", type=Path)
parser.add_argument("destination", type=Path)
args = parser.parse_args()
if args.source.resolve() == args.destination.resolve():
parser.error("Source and destination must differ to preserve the original report")
report = json.loads(args.source.read_text(encoding="utf-8"))
removed = filter_source_suppressions(report)
args.destination.write_text(json.dumps(report) + "\n", encoding="utf-8")
print(f"Applied {removed} CodeQL source suppressions")


if __name__ == "__main__":
main()
13 changes: 12 additions & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,21 @@ jobs:
build-mode: none
# The extended suite adds security queries that the default suite leaves out
queries: security-extended
# The suppression query turns the in-code codeql[...] comments into suppressed alerts
# Mark results covered by source suppression comments for the upload filter
packs: codeql/python-queries:AlertSuppression.ql

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
category: "/language:python"
output: sarif-results
upload: failure-only

- name: Apply source suppressions
run: python .github/scripts/filter_codeql_sarif.py sarif-results/python.sarif sarif-results/python-filtered.sarif

- name: Upload CodeQL results
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
sarif_file: sarif-results/python-filtered.sarif
category: "/language:python"
10 changes: 7 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Optional local hooks that catch what CI would reject, before a commit is written.
# Enable them once with:
# pip install pre-commit
# pip install -e '.[lint]'
# pre-commit install
# Check the whole repository at any time with:
# pre-commit run --all-files
Expand All @@ -24,10 +25,13 @@ repos:
# where it needs no Go toolchain on a contributor's machine
- id: detect-private-key

# The same linter and version CI runs
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.7
# Runs the ruff already installed from the [lint] extra rather than a second copy pinned here.
# One pin in pyproject.toml is what keeps the hook and CI on the same version
- repo: local
hooks:
- id: ruff-check
name: ruff check
entry: ruff check
args: [--no-fix]
language: system
files: '^(github_monitor\.py|tests/.*\.py)$'
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ authors:
given-names: Michal
alias: misiektoja
email: misiektoja-github@rm-rf.ninja
version: "2.7"
date-released: 2026-09-18
version: "2.8"
date-released: 2026-09-22
license: GPL-3.0-or-later
repository-code: "https://github.com/misiektoja/github_monitor"
keywords:
Expand Down
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ cd github_monitor
pip install -e '.[test]'
```

Optional local hooks catch what CI would reject before a commit is written:
Optional local hooks catch what CI would reject before a commit is written. The lint hook calls the Ruff installed by the `lint` extra rather than a copy of its own, so it always matches the version CI runs:

```sh
pip install pre-commit
pip install -e '.[lint]'
pre-commit install
```

Expand All @@ -41,6 +42,8 @@ mkdocs build --strict

The default suite is offline. It never contacts GitHub and network calls are replaced with local test doubles. See [tests/README.md](tests/README.md) for what each test file covers.

CodeQL runs the extended security queries. For a verified false positive, put a `codeql[rule-id]` comment immediately above the reported line and explain why it is safe. The workflow filters results with accepted source suppressions before upload. Other findings remain reportable.

CI runs the same three checks on every push and pull request, across Python 3.10 through 3.14. The linter is pinned in the `lint` extra so a new ruff release cannot fail a build on a rule that did not exist when the change was written; the pre-commit hook pins the same version.

A change to the monitoring loop, authentication or GitHub data handling is not verified by the offline suite alone. Exercise it against a real account and say so in the pull request, without usernames or credentials.
Expand Down
19 changes: 19 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

This is a high-level summary of the most important changes.

# Changes in 2.8 (22 Sep 2026)

Version **2.8** caps how much of a large push a single notification reports and gives every monitoring failure unified subject and body across email and webhook, followed by a **recovery alert** when monitoring resumes. Network failures now link to a new **Connection Problems** page section. Alert delivery messages stay within the correct check report and alert channels that still use placeholder configuration values are shown as not configured.

**Features and improvements**:

- **NEW:** **Push event commit limits** - A push with hundreds of commits no longer spends one API request per commit and no longer fills the notification. **`PUSH_COMMITS_LIMIT`** (default **10**, also **`--push-commits-limit`**) sets how many commits of one push are reported with their date, author URL, statistics and changed files. **`PUSH_COMMITS_ORDER`** picks which end of the push keeps them, **`newest`** by default. The remaining commits are replaced by one line naming how many were left out, or listed one line each with their SHA, author and first message line by setting **`PUSH_COMMITS_OVERFLOW = 'summary'`**. **`PUSH_FILES_LIMIT`** (default **20**, also **`--push-files-limit`**) caps the changed files listed per commit. Set either limit to **0** to report everything in full.
- **IMPROVE:** **Every profile change is sent as HTML** - The alerts about a changed **blog URL**, an **updated account**, a **profile visibility** switch and a **block** now carry an HTML part like the other alerts
- **IMPROVE:** **Failure alerts share one shape** - Every monitoring failure email and webhook uses the subject **`GitHub Monitor error: <what went wrong> (user: <username>)`** and lists the fix, the guide link, how many checks failed in a row, since when and when the next retry happens. A **recovery alert** follows on the channels that received the failure alert once monitoring resumes. `-e` / `--no-error-notify` and `--no-webhook-error-notify` switch both off

**Bug fixes**:

- **BUGFIX:** **An unset profile value reads the same in both email parts** - A bio, location, name, company, email or blog URL that was not set printed **`None`** in the plain text part while the HTML part left the line empty. Both parts now say the same thing
- **BUGFIX:** **Network failures point at the right page** - A timed-out or unreachable GitHub request ended with a **`Guide:`** now link to the new **Connection Problems** section, which explains the automatic retries and what to check if the failure continues.
- **BUGFIX:** **A failed visibility check no longer ends the run** - The profile visibility lookup only handled GitHub API errors, so a timed-out or blocked connection ended the monitoring run with a traceback. The lookup now survives any failure and reports that it could not answer
- **BUGFIX:** **Reported changes name the window they were observed in** - The **`Check interval:`** line under a change always showed the configured polling interval and a date range built from it, so a change found after a failed check was reported over a window the tool had not been watching. It now measures from the previous successful check, which is the configured interval while checks run on schedule
- **BUGFIX:** **Alert deliveries stay inside their report** - The hourly **`Monitoring degraded`** reminder closed its report before the error alert was sent, so **`Sending email notification to ...`** and its webhook equivalent landed under the separator and started a second, headless block. The reminder now closes below its delivery lines, keeping one check's report in one block
- **BUGFIX:** **Unset alert channels are reported as unset** - The verbose startup summary read the values the sample configuration ships as a real destination, so a run that had never been given a mail server printed **`Email transport: your_smtp_server_ssl:587`**, a recipient of **`your_receiver_email`** and a webhook provider of **`Discord`**. Those rows now read **`Not configured`** and the channel rollup above them reads **`Off (not configured)`** rather than naming alert types nothing could deliver

# Changes in 2.7 (18 Sep 2026)

Version **2.7** adds **guided setup**, a read-only **Doctor preflight check** and **private SMTP password entry**. **Coloured output**, startup summaries and verbose/debug modes make monitoring easier to follow. It improves **contribution and repository-closure alerts**, preserves history during failed checks and protects configuration and credentials. Documentation is searchable and release downloads can be verified.
Expand Down
27 changes: 27 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ By default all events are monitored, but if you want to limit it, then remove th
EVENTS_TO_MONITOR=['PushEvent', 'PullRequestEvent', 'IssuesEvent', 'ForkEvent', 'ReleaseEvent', 'DiscussionEvent']
```

<a id="push-event-commits"></a>
## Push Event Commits

A push can carry hundreds of commits. Reporting every one in full costs an extra GitHub API request each and produces a notification nobody reads, so only `PUSH_COMMITS_LIMIT` commits of a push are reported with their date, author URL, statistics and changed files. The rest are replaced by one line naming how many were left out.

```ini
PUSH_COMMITS_LIMIT = 10
PUSH_COMMITS_ORDER = 'newest'
PUSH_COMMITS_OVERFLOW = 'count'
PUSH_FILES_LIMIT = 20
```

| Option | Values | Effect |
| --- | --- | --- |
| `PUSH_COMMITS_LIMIT` | integer, `0` for no limit | Commits of one push reported in full, also `--push-commits-limit` |
| `PUSH_COMMITS_ORDER` | `'newest'`, `'oldest'` | Which end of the push keeps the detailed commits |
| `PUSH_COMMITS_OVERFLOW` | `'count'`, `'summary'` | Whether the remaining commits become a single count or get one line each |
| `PUSH_FILES_LIMIT` | integer, `0` for no limit | Changed files listed per commit, also `--push-files-limit` |

With the built-in values a 300-commit push spends about 12 requests instead of about 300. It reports the 10 newest commits in full and replaces the other 290 with `Commits 1-290 not reported in full`. The compare URL in the same report links the complete diff.

The limits in effect appear as `Push commit details` and `Push changed files` in the startup summary, which `--verbose` and `--debug` print on screen and every run writes to the log file.

Set `PUSH_COMMITS_OVERFLOW = 'summary'` to list those commits one line each instead, with their SHA, author and first message line. Those lines are built from data the tool already fetched, so they cost no extra requests, but a large push then produces a long notification. Set `PUSH_COMMITS_LIMIT = 0` to report every commit of every push in full.

<a id="repositories-to-monitor"></a>
## Repositories to Monitor

Expand Down Expand Up @@ -122,6 +147,8 @@ python3 -c "import pytz; print('\n'.join(pytz.all_timezones))"

Email notifications need SMTP server details for the sending account. Add them to `github_monitor.conf` or use the setup wizard. Setup checks the login without sending an email. To replace only the password, run `github_monitor --set-smtp-password`. Password entry is hidden and preserves spaces.

Every alert is sent as both HTML and plain text in one message. Mail clients that render HTML show the account, the changed value and the check interval in bold, with repositories, commits, issues and profile addresses linked. Clients that do not fall back to the plain text, which is unchanged.

Send one test message to verify the settings:

```sh
Expand Down
20 changes: 20 additions & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,29 @@ Every failure is reported in the same three-part shape: what went wrong, a `To f
| Webhook alerts never arrive | Provider mismatch or a stale destination | [Webhook Settings](configuration.md#webhook-settings) then run `github_monitor --send-test-webhook` |
| `github_monitor` is not found after installation | The shell has not picked up the new command | [Installation and Command Problems](#installation-and-command-problems) |
| Escape sequences such as `[36m` printed as text or no colour at all | The terminal cannot display ANSI colour or colour was switched off | [Terminal Colours Look Wrong](#terminal-colours-look-wrong) |
| `GitHub did not answer in time`, `GitHub could not be reached` or `GitHub is temporarily unavailable` | A network problem between this machine and GitHub or a GitHub outage | [Connection Problems](#connection-problems) |
| `This process ran out of file descriptors` | The operating system limit on open files was reached | [Too Many Open Files](#too-many-open-files) |

A continuing outage produces a `* Monitoring degraded` reminder once an hour, even when the [liveness reminder](usage.md#liveness-reminder) is switched off. `* Monitoring recovered` marks recovery. Use `--verbose` to see the first failed check.

<a id="connection-problems"></a>
## Connection Problems

`GitHub did not answer in time` and `GitHub could not be reached` mean a check got no answer from GitHub. `GitHub is temporarily unavailable` means GitHub answered with a server error. The report names the interval after which the check is retried, so a short outage needs no action. While the network is down only the first request prints its retry attempts, because the requests behind it stop retrying once it has shown that GitHub cannot be reached. A failure that lasts produces the hourly `Monitoring degraded` reminder and `Monitoring recovered` when it clears.

If the failure continues, check the internet connection, DNS and any firewall or proxy between this machine and GitHub. A certificate error points at TLS interception on the network, see [TLS Verification](configuration.md#tls-verification). A server error that lasts is a GitHub outage, so wait for it to end.

To confirm that GitHub is reachable from this machine, run:

```sh
github_monitor --doctor
```

<a id="too-many-open-files"></a>
## Too Many Open Files

`This process ran out of file descriptors` means the operating system limit on open files was reached. It is a local limit and not a GitHub problem. Raise it with `ulimit -n 4096` in the shell that starts the tool or set `LimitNOFILE=` in the systemd unit, then restart the tool.

<a id="terminal-colours-look-wrong"></a>
## Terminal Colours Look Wrong

Expand Down
16 changes: 11 additions & 5 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ Monitoring mode prints the settings that are actually in effect before the first

Optional features appear once you switch them on.

Use `--verbose` or `--debug` for the full startup summary, including output paths, notification settings, secret sources and runtime information.
Use `--verbose` or `--debug` for the full startup summary, including output paths, notification settings, push event limits, secret sources and runtime information.

Use `--truncate N` or `TRUNCATE_CHARS` to limit screen line width. Set it to `999` to detect the terminal width automatically. Truncation does not change log files and is ignored when logging is disabled with `-d`.

Use `--push-commits-limit N` and `--push-files-limit N` to control how much of a large push is reported in full. See [Push Event Commits](configuration.md#push-event-commits).

The tool clears the terminal when monitoring starts. Set `CLEAR_SCREEN` to `False` to keep whatever is already on the screen.

The screen is never cleared when output is redirected to a file or a pipe, in debug mode or for a command that prints a result and exits, such as `--doctor`, `--help` and the test senders.
Expand Down Expand Up @@ -219,16 +221,18 @@ github_monitor github_username -m -y

The `-y` flag only works if tracking of daily contributions is enabled (`-m`).

To disable sending an email on errors (enabled by default):
To disable sending an email on errors and the recovery alert that follows (both enabled by default):

- set `ERROR_NOTIFICATION` to `False`
- or use the `-e` flag
- or use the `-e` / `--no-error-notify` flag

```sh
github_monitor github_username -e
```

Email and webhook error alerts are sent after **5 minutes** of a continuing failure. Problems that need your action, such as a rejected token, alert immediately. Each kind of failure alerts once per channel. Failed deliveries are retried after 5 minutes, with increasing waits up to an hour. Alerts can fire again after monitoring recovers.
Email and webhook error alerts are sent after **5 minutes** of a continuing failure. Problems that need your action, such as a rejected token, alert immediately. Each kind of failure alerts once per channel. Failed deliveries are retried after 5 minutes, with increasing waits up to an hour. A new outage after a recovery alerts again. A channel that could not receive the failure alert while the outage lasted is told about the failure and its recovery together, so a blocked channel is not left without any word of an outage.

A failure alert carries the subject `GitHub Monitor error: <what went wrong> (user: <username>)` and lists the fix, the guide link, how many checks failed in a row, since when and when the next retry is. When the failure clears, a matching `GitHub Monitor recovered: ...` alert goes to the channels the failure alert reached. `-e` / `--no-error-notify` switches both off for email and `--no-webhook-error-notify` switches both off for webhooks.

Missing optional details, such as a push event's file list, are reported on screen without triggering an error alert. When several checks fail, the alert shows the action to take and the number of other failures.

Expand All @@ -254,7 +258,9 @@ Webhook event controls mirror the email categories but work independently:
| Repository changes | `WEBHOOK_REPO_NOTIFICATION` | `--webhook-repo-changes` |
| Repository update date changes | `WEBHOOK_REPO_UPDATE_DATE_NOTIFICATION` | `--webhook-repo-update-date` |
| Daily contribution changes | `WEBHOOK_CONTRIB_NOTIFICATION` | `--webhook-daily-contribs` |
| Monitoring errors | `WEBHOOK_ERROR_NOTIFICATION` | Enable with `--webhook-errors` or disable with `--no-webhook-error-notify` |
| Monitoring errors and recoveries | `WEBHOOK_ERROR_NOTIFICATION` | Enable with `--webhook-errors` or disable with `--no-webhook-error-notify` |

A monitoring error webhook carries the same title and fields as the error email, without the timestamp the webhook service shows itself, and the matching recovery alert follows on the same channel. `--no-webhook-error-notify` switches both off.

Use `--webhook` or `--no-webhook` to turn all configured webhook alerts on or off for one run. A category override also enables the master webhook switch. For example:

Expand Down
Loading
Loading