Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
dc3aeba
Dependency updates arrive on dev, grouped, and patch and minor ones m…
EaZyCheaZ Oct 25, 2026
8d5b191
Ignore Python bytecode folders
EaZyCheaZ Oct 25, 2026
29a77b3
Merge pull request #44 from RunemarkLabs/p1-dependency-updates
EaZyCheaZ Oct 25, 2026
b02370e
Dependency updates: size and group an update from its commit message …
EaZyCheaZ Oct 25, 2026
49dfe2e
Merge pull request #45 from RunemarkLabs/p1-dependency-updates-sizes
EaZyCheaZ Oct 25, 2026
0068f73
Dependency updates: a run waiting for approval isn't a failed build (…
EaZyCheaZ Oct 25, 2026
52a66d2
Merge pull request #50 from RunemarkLabs/p1-dependency-updates-approval
EaZyCheaZ Oct 25, 2026
21a0679
Dependency updates: merge as soon as build passes, and one place for …
EaZyCheaZ Oct 25, 2026
17254fa
Web app build tools: fast-uri 3.1.9, which fixes its four open securi…
EaZyCheaZ Oct 25, 2026
4178601
Merge pull request #52 from RunemarkLabs/p1-dependency-updates-retry
EaZyCheaZ Oct 25, 2026
594c8e8
Dependency updates: make the version commit through GitHub's API so i…
EaZyCheaZ Oct 25, 2026
c72c9b8
Dependency updates: wait for the build the workflow started, then mer…
EaZyCheaZ Oct 25, 2026
a722de1
Merge pull request #53 from RunemarkLabs/p1-dependency-updates-signed
EaZyCheaZ Oct 25, 2026
0c9b4de
Dependency updates: try GitHub's API again after a pause when it does…
EaZyCheaZ Oct 25, 2026
eab4e7c
Merge pull request #54 from RunemarkLabs/p1-dependency-updates-retry-api
EaZyCheaZ Oct 25, 2026
5902a89
Web app packages: Bump the frontend group across 1 directory with 7 u…
dependabot[bot] Oct 25, 2026
fc4951b
Version 0.4.9 and its changelog section for this dependency update
github-actions[bot] Oct 25, 2026
fdc7b70
Merge pull request #48 from RunemarkLabs/dependabot/npm_and_yarn/fron…
github-actions[bot] Oct 25, 2026
d59ab40
Dark icons on the header gray, a full-height header and sign-in logo,…
EaZyCheaZ Oct 25, 2026
b7a7bb3
Merge pull request #55 from RunemarkLabs/p1-dark-icon-background
EaZyCheaZ Oct 25, 2026
0e42c90
Charcoal arrow, a header logo for the purple light header, and logos …
EaZyCheaZ Oct 25, 2026
c28d06e
Merge pull request #56 from RunemarkLabs/p1-charcoal-arrow
EaZyCheaZ Oct 25, 2026
2613fff
The bot keeps its own Discord picture and banner up to date (version …
EaZyCheaZ Oct 25, 2026
459b3d6
Test stacks: no botProfile section yet, so the shared provisioning fi…
EaZyCheaZ Oct 25, 2026
b0962cf
Merge pull request #57 from RunemarkLabs/p1-bot-profile-sync
EaZyCheaZ Oct 25, 2026
cc9aaa2
Sign-in logo from the dark set in both themes, and the environment's …
EaZyCheaZ Oct 25, 2026
eb59945
Merge pull request #58 from RunemarkLabs/p1-signin-loading-skips
EaZyCheaZ Oct 25, 2026
68f67c9
One port band per environment, counting down to the standard ports (v…
EaZyCheaZ Oct 25, 2026
43467a9
Merge pull request #59 from RunemarkLabs/p1-port-bands
EaZyCheaZ Oct 25, 2026
3425b98
QA checklist file with items from 0.4.3 on, and its pull request chec…
EaZyCheaZ Oct 25, 2026
ac7ce25
QA checklist in Discord, bug reports with GitHub filing, and the gate…
EaZyCheaZ Oct 25, 2026
3d983eb
Live check for the QA checklist and bug reports; the gate can read a …
EaZyCheaZ Oct 25, 2026
0d4915b
Docker build copies the QA checklist the app is built with
EaZyCheaZ Oct 25, 2026
d145eb4
Dates stored as UTC DateTime like the other records; GitHub client te…
EaZyCheaZ Oct 25, 2026
78eee23
Channel groups test: the first users group now holds four channels, b…
EaZyCheaZ Oct 25, 2026
eb150a6
Merge pull request #61 from RunemarkLabs/p1-qa-checklist-bug-reports
EaZyCheaZ Oct 25, 2026
6a931d4
QA checklist fixes: Passes answers without breaking the card, admins …
EaZyCheaZ Oct 26, 2026
143bfe7
Panels already showing the right thing are left alone on start, so a …
EaZyCheaZ Oct 26, 2026
d6e02ff
Merge pull request #62 from RunemarkLabs/p1-qa-checklist-fixes
EaZyCheaZ Oct 26, 2026
f4e6b67
Test stacks: Requestarr's bot picture and banner win over one uploade…
EaZyCheaZ Oct 26, 2026
b4b3cb8
Merge pull request #63 from RunemarkLabs/p1-qa-bot-profile-takeover
EaZyCheaZ Oct 26, 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
142 changes: 142 additions & 0 deletions .github/checklist_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""Checks QA-CHECKLIST.md against CHANGELOG.md (docs/development.md#qa-checklist). CI's Changelog job runs it on every
pull request; run it locally with `python3 .github/checklist_check.py QA-CHECKLIST.md CHANGELOG.md`.

The QA checklist is what admins on the QA server test, in Discord, before a version goes to staging. Every pull request
adds its version's items, the way it adds its changelog entry. Checked:
- versions: every changelog version from 0.4.3 on has a "## x.y.z (YYYY-MM-DD)" section here, with the same date, in
the same order, and there are no others;
- a version with nothing anyone can test by hand has only its heading (the same escape as a heading-only changelog
entry); otherwise only "- " item lines;
- each item: "- **Name:** what to do. You should see what happens.", with a name unique in its version and the
words "You should see" saying what a pass looks like;
- plain words, as in the changelog: no backticks, file names, paths, command flags, settings keys or environment
variable names, since admins read these in Discord.
"""
import os
import re
import sys

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from changelog_check import CODE # noqa: E402

FIRST = (0, 4, 3)
VERSION = re.compile(r"^## (\d+)\.(\d+)\.(\d+) \((\d{4}-\d{2}-\d{2})\)$")
ITEM = re.compile(r"^- \*\*([^*:]+):\*\* (.+)$")


def versions(text):
found = []
for number, line in enumerate(text.splitlines(), 1):
match = VERSION.match(line.strip())
if match:
found.append((tuple(int(match.group(i)) for i in (1, 2, 3)), match.group(4), number))
return found


def check(checklist, changelog):
problems = []
wanted = [(v, d) for v, d, _ in versions(changelog) if v >= FIRST]
have = versions(checklist)
if [(v, d) for v, d, _ in have] != wanted:
missing = [v for v, _ in wanted if v not in [h[0] for h in have]]
extra = [v for v, _, _ in have if v not in [w[0] for w in wanted]]
problems.append((1, "versions don't match the changelog from 0.4.3 on (same versions, dates and order): missing %s, extra %s"
% (", ".join("%d.%d.%d" % v for v in missing) or "none", ", ".join("%d.%d.%d" % v for v in extra) or "none")))

current = None
names = set()
for number, line in enumerate(checklist.splitlines(), 1):
text = line.strip()
if VERSION.match(text):
current = text
names = set()
continue
if current is None or not text:
continue
if text.startswith("#"):
problems.append((number, "only version headings: '%s'" % text))
continue
item = ITEM.match(text)
if not item:
problems.append((number, "only '- **Name:** what to do. You should see ...' lines inside a version"))
continue
name, body = item.group(1).strip(), item.group(2)
if name.lower() in names:
problems.append((number, "item '%s' appears twice in this version" % name))
names.add(name.lower())
if "you should see" not in body.lower():
problems.append((number, "item '%s' must say 'You should see' what a pass looks like" % name))
for pattern, what in CODE:
if pattern.search(text):
problems.append((number, "plain words only: '%s' has %s" % (name, what)))
return problems


BAD_CHANGELOG = """# Changelog

## 0.4.4 (2026-10-25)

## 0.4.3 (2026-10-25)
"""

BAD = """# QA checklist

## 0.4.4 (2026-10-25)
- **Logo:** look at the logo.
- **Logo:** open `provisioning.yml`. You should see it.
Some loose text.
### Section
"""

GOOD = """# QA checklist

Intro text is free.

## 0.4.4 (2026-10-25)
- **Logo:** open the web app and look at the header. You should see the Dev logo.

## 0.4.3 (2026-10-25)
"""


def self_test():
found = check(BAD, BAD_CHANGELOG)
expected = ["versions don't match", "must say 'You should see'", "appears twice", "backticks", "a file name",
"only '- **Name:**", "only version headings"]
missing = [e for e in expected if not any(e in p for _, p in found)]
good = check(GOOD, BAD_CHANGELOG)
for _, p in found:
print(" caught: " + p)
if missing or good:
print("SELF-TEST FAILED: missed %s; good sample problems %s" % (missing, good))
return 1
print("Self-test passed: every rule caught its sample, and the good sample passed.")
return 0


def main(argv):
if argv[1:] == ["--self-test"]:
return self_test()
if len(argv) != 3:
print(__doc__)
return 2
with open(argv[1], encoding="utf-8") as handle:
checklist = handle.read()
with open(argv[2], encoding="utf-8") as handle:
changelog = handle.read()
problems = check(checklist, changelog)
for number, problem in problems:
if os.environ.get("GITHUB_ACTIONS"):
print("::error file=%s,line=%d::%s" % (argv[1], number, problem))
else:
print("%s:%d: %s" % (argv[1], number, problem))
if problems:
print("%d problem(s): see the QA checklist rule in docs/development.md#qa-checklist." % len(problems))
return 1
print("%s matches the changelog and follows the QA checklist rule." % argv[1])
return 0


if __name__ == "__main__":
sys.exit(main(sys.argv))
97 changes: 97 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Dependency updates (docs/development.md#dependency-updates). Everything goes to dev, the default branch, and moves up
# to qa, staging and main like any other change. Each kind of dependency gets at most three pull requests a week, every
# Monday: its patch and minor updates together, its major updates together, and its security fixes together (those
# arrive as soon as GitHub publishes the advisory, not on the schedule). Patch and minor merge on their own once build
# passes; major ones wait for review (.github/workflows/dependency-updates.yml). Group names ending in "-security" are
# how that workflow tells a security fix from an ordinary update; when Dependabot's commit message carries no sizes
# it can read, the workflow reads the "from A to B" lines itself.
version: 2

updates:
# Backend: the NuGet packages of every project in src/Requestarr.sln.
- package-ecosystem: nuget
directory: /src
schedule:
interval: weekly
day: monday
time: "06:00"
open-pull-requests-limit: 5
labels: [dependencies]
commit-message:
prefix: "Backend packages"
groups:
backend:
applies-to: version-updates
update-types: [minor, patch]
backend-major:
applies-to: version-updates
update-types: [major]
backend-security:
applies-to: security-updates
patterns: ["*"]

# Web app: package.json and yarn.lock.
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
open-pull-requests-limit: 5
labels: [dependencies]
commit-message:
prefix: "Web app packages"
groups:
frontend:
applies-to: version-updates
update-types: [minor, patch]
frontend-major:
applies-to: version-updates
update-types: [major]
frontend-security:
applies-to: security-updates
patterns: ["*"]

# The actions the workflows in .github/workflows use.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
open-pull-requests-limit: 5
labels: [dependencies]
commit-message:
prefix: "GitHub Actions"
groups:
actions:
applies-to: version-updates
update-types: [minor, patch]
actions-major:
applies-to: version-updates
update-types: [major]
actions-security:
applies-to: security-updates
patterns: ["*"]

# The base images in docker/Dockerfile (Node for the web build, the .NET SDK and runtime).
- package-ecosystem: docker
directory: /docker
schedule:
interval: weekly
day: monday
time: "06:00"
open-pull-requests-limit: 5
labels: [dependencies]
commit-message:
prefix: "Base images"
groups:
images:
applies-to: version-updates
update-types: [minor, patch]
images-major:
applies-to: version-updates
update-types: [major]
images-security:
applies-to: security-updates
patterns: ["*"]
Loading
Loading