Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
611573a
Add temporary GHA_PAT delete-scope test workflow
Geczy May 20, 2026
95fa5f3
Remove temporary GHA_PAT delete-scope test workflow
Geczy May 20, 2026
a1e459c
Unify builder.yml into a single service matrix
Geczy May 20, 2026
6880fe3
Disable unused minimap parse on the GSI hot path
Geczy May 20, 2026
b1dd733
Enable per-service GHA build cache; drop dead registry-cache config
Geczy May 20, 2026
36d61fc
Harden CI/CD: fix push-range detection, add concurrency, pin Bun
Geczy May 20, 2026
f708074
Fix eventsub/events connection flags getting stuck false on reconnect
Geczy May 20, 2026
ff66b37
build(deps): bump nick-fields/retry from 3 to 4 (#595)
dependabot[bot] May 20, 2026
0650557
build(deps): bump actions/cache from 4 to 5 (#594)
dependabot[bot] May 20, 2026
762024a
Drop Valve-disabled note from avg/gm/np/smurfs commands
Geczy May 20, 2026
074d3a2
test(clip-processor-py): expand suite to surface prod bugs
Geczy May 21, 2026
063ecd0
fix(clip-processor-py): stop silent cache loss and empty clip IDs
Geczy May 21, 2026
54b23ef
test: expand coverage across twitch-events, twitch-chat, shared-utils…
Geczy May 21, 2026
b83429d
refactor(clip-processor-py): dedupe facet-merge into one helper
Geczy May 21, 2026
5ca369c
test(dota): cover ranked and spectators via a mocked MongoDB layer
Geczy May 21, 2026
a7afabf
test(dota): cover opendota, profile, and friends commands
Geczy May 21, 2026
514d19e
test(dota): cover beta, toggle, and today (no-steam paths)
Geczy May 21, 2026
2650c77
test(dota): cover clearsharing and lgs (no-steam paths)
Geczy May 21, 2026
f01a5ac
test: harden assertions and test isolation from review
Geczy May 21, 2026
69d57a7
fix(clip-processor-py): repair draft alignment + queue dedup messaging
Geczy May 21, 2026
54985b0
test(dota): cover items and stats reachable paths
Geczy May 21, 2026
a832342
test(dota): cover geo plus the steam-guard branch of gm/np/smurfs/lg
Geczy May 21, 2026
63f64e5
build(deps): bump streamlink in /packages/clip-processor-py
dependabot[bot] May 21, 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
171 changes: 67 additions & 104 deletions .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,132 +5,97 @@ on:
push:
branches:
- "**"
paths:
- 'packages/dota/**' # Dota service and related changes
- 'packages/twitch-chat/**' # Twitch Chat service changes
- 'packages/steam/**' # Steam service changes
- 'packages/twitch-events/**' # Twitch Events service changes
- 'packages/shared-utils/**' # Shared utilities used by multiple services
- 'packages/profanity-filter/**'
- 'package.json'
- 'bun.lock'
- 'packages/Dockerfile.bun' # Shared Dockerfile for bun-based services
- 'docker-compose.yml' # Compose file changes might affect all services
- '.github/workflows/builder.yml' # The build workflow itself (affects all images)

concurrency:
group: builder-${{ github.ref }}
cancel-in-progress: true

jobs:
# Dota job remains separate because it has extra change checks
dota:
changes:
runs-on: ubuntu-latest
environment: prod
permissions:
packages: write
outputs:
services: ${{ steps.select.outputs.services }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2

- name: Check for changes in dota service
id: dota-changes
run: |
git diff --name-only HEAD^ HEAD | grep -q "^packages/profanity-filter/" && echo "profanity_filter_changed=true" >> $GITHUB_OUTPUT || echo "profanity_filter_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^package.json\|^bun.lock" && echo "deps_changed=true" >> $GITHUB_OUTPUT || echo "deps_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^packages/dota/" && echo "changed=true" >> $GITHUB_OUTPUT || echo "changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^packages/shared-utils/" && echo "shared_utils_changed=true" >> $GITHUB_OUTPUT || echo "shared_utils_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^packages/Dockerfile.bun" && echo "dockerfile_changed=true" >> $GITHUB_OUTPUT || echo "dockerfile_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^docker-compose.yml" && echo "compose_changed=true" >> $GITHUB_OUTPUT || echo "compose_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^.github/workflows/builder.yml" && echo "workflow_changed=true" >> $GITHUB_OUTPUT || echo "workflow_changed=false" >> $GITHUB_OUTPUT

- name: Extract branch name
if: ${{ github.event_name == 'workflow_dispatch' || steps.dota-changes.outputs.changed == 'true' || steps.dota-changes.outputs.dockerfile_changed == 'true' || steps.dota-changes.outputs.compose_changed == 'true' || steps.dota-changes.outputs.deps_changed == 'true' || steps.dota-changes.outputs.profanity_filter_changed == 'true' || steps.dota-changes.outputs.shared_utils_changed == 'true' || steps.dota-changes.outputs.workflow_changed == 'true' }}
shell: bash
run: |
echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
# Sanitize branch name for Docker tag (replace '/' with '-')
echo "DOCKER_TAG=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV
# Immutable per-commit tag + OCI label metadata
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
fetch-depth: 0

- name: Set up Docker Buildx
if: ${{ github.event_name == 'workflow_dispatch' || steps.dota-changes.outputs.changed == 'true' || steps.dota-changes.outputs.dockerfile_changed == 'true' || steps.dota-changes.outputs.compose_changed == 'true' || steps.dota-changes.outputs.deps_changed == 'true' || steps.dota-changes.outputs.profanity_filter_changed == 'true' || steps.dota-changes.outputs.shared_utils_changed == 'true' || steps.dota-changes.outputs.workflow_changed == 'true' }}
uses: docker/setup-buildx-action@v4
# Single source of truth for the build dependency graph. paths-filter
# diffs the full push range (github.event.before..after), so multi-commit
# pushes can't skip a rebuild. package.json/bun.lock are listed for every
# service since they all share the root lockfile + bun install.
- uses: dorny/paths-filter@v4.0.1
id: filter
with:
driver-opts: |
network=host
image=moby/buildkit:latest
buildkitd-flags: --debug
filters: |
dota:
- 'packages/dota/**'
- 'packages/profanity-filter/**'
- 'packages/shared-utils/**'
- 'packages/Dockerfile.bun'
- 'docker-compose.yml'
- 'package.json'
- 'bun.lock'
- '.github/workflows/builder.yml'
twitch-chat:
- 'packages/twitch-chat/**'
- 'packages/shared-utils/**'
- 'packages/Dockerfile.bun'
- 'docker-compose.yml'
- 'package.json'
- 'bun.lock'
- '.github/workflows/builder.yml'
steam:
- 'packages/steam/**'
- 'packages/shared-utils/**'
- 'packages/Dockerfile.bun'
- 'docker-compose.yml'
- 'package.json'
- 'bun.lock'
- '.github/workflows/builder.yml'
twitch-events:
- 'packages/twitch-events/**'
- 'packages/shared-utils/**'
- 'packages/Dockerfile.bun'
- 'docker-compose.yml'
- 'package.json'
- 'bun.lock'
- '.github/workflows/builder.yml'

- name: Login to ghcr
if: ${{ github.event_name == 'workflow_dispatch' || steps.dota-changes.outputs.changed == 'true' || steps.dota-changes.outputs.dockerfile_changed == 'true' || steps.dota-changes.outputs.compose_changed == 'true' || steps.dota-changes.outputs.deps_changed == 'true' || steps.dota-changes.outputs.profanity_filter_changed == 'true' || steps.dota-changes.outputs.shared_utils_changed == 'true' || steps.dota-changes.outputs.workflow_changed == 'true' }}
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GHA_PAT }}

- name: Build and push
if: ${{ github.event_name == 'workflow_dispatch' || steps.dota-changes.outputs.changed == 'true' || steps.dota-changes.outputs.dockerfile_changed == 'true' || steps.dota-changes.outputs.compose_changed == 'true' || steps.dota-changes.outputs.deps_changed == 'true' || steps.dota-changes.outputs.profanity_filter_changed == 'true' || steps.dota-changes.outputs.shared_utils_changed == 'true' || steps.dota-changes.outputs.workflow_changed == 'true' }}
uses: docker/bake-action@v7
with:
push: true
provenance: false
targets: dota
set: |
*.platform=linux/arm64
dota.tags=ghcr.io/${{ github.repository_owner }}/dota:${{ env.DOCKER_TAG }}
dota.tags+=ghcr.io/${{ github.repository_owner }}/dota:sha-${{ env.GIT_SHA }}
*.labels.org.opencontainers.image.revision=${{ github.sha }}
*.labels.org.opencontainers.image.created=${{ env.BUILD_DATE }}
*.labels.org.opencontainers.image.version=${{ env.DOCKER_TAG }}
*.cache-from=
*.cache-to=
- name: Select services to build
id: select
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo 'services=["dota","twitch-chat","steam","twitch-events"]' >> "$GITHUB_OUTPUT"
else
echo 'services=${{ steps.filter.outputs.changes }}' >> "$GITHUB_OUTPUT"
fi

# Combined job for twitch-chat, steam, and twitch-events using a matrix
services:
build:
needs: changes
if: needs.changes.outputs.services != '[]'
runs-on: ubuntu-latest
environment: prod
permissions:
packages: write
strategy:
fail-fast: false
matrix:
include:
- service: twitch-chat
changed_path: "^packages/twitch-chat/"
dockerfile: "packages/Dockerfile.bun"
- service: steam
changed_path: "^packages/steam/"
dockerfile: "packages/Dockerfile.bun"
- service: twitch-events
changed_path: "^packages/twitch-events/"
dockerfile: "packages/Dockerfile.bun"
service: ${{ fromJSON(needs.changes.outputs.services) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2

- name: Check for changes in ${{ matrix.service }} service
id: changes
run: |
git diff --name-only HEAD^ HEAD | grep -q "${{ matrix.changed_path }}" && echo "changed=true" >> $GITHUB_OUTPUT || echo "changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^packages/shared-utils/" && echo "shared_utils_changed=true" >> $GITHUB_OUTPUT || echo "shared_utils_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^${{ matrix.dockerfile }}" && echo "dockerfile_changed=true" >> $GITHUB_OUTPUT || echo "dockerfile_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^docker-compose.yml" && echo "compose_changed=true" >> $GITHUB_OUTPUT || echo "compose_changed=false" >> $GITHUB_OUTPUT
git diff --name-only HEAD^ HEAD | grep -q "^.github/workflows/builder.yml" && echo "workflow_changed=true" >> $GITHUB_OUTPUT || echo "workflow_changed=false" >> $GITHUB_OUTPUT

- name: Extract branch name
if: ${{ github.event_name == 'workflow_dispatch' || steps.changes.outputs.changed == 'true' || steps.changes.outputs.shared_utils_changed == 'true' || steps.changes.outputs.dockerfile_changed == 'true' || steps.changes.outputs.compose_changed == 'true' || steps.changes.outputs.workflow_changed == 'true' }}
shell: bash
run: |
echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> "$GITHUB_ENV"
# Sanitize branch name for Docker tag (replace '/' with '-')
echo "DOCKER_TAG=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV
echo "DOCKER_TAG=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> "$GITHUB_ENV"
# Immutable per-commit tag + OCI label metadata
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
echo "BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
if: ${{ github.event_name == 'workflow_dispatch' || steps.changes.outputs.changed == 'true' || steps.changes.outputs.shared_utils_changed == 'true' || steps.changes.outputs.dockerfile_changed == 'true' || steps.changes.outputs.compose_changed == 'true' || steps.changes.outputs.workflow_changed == 'true' }}
uses: docker/setup-buildx-action@v4
with:
driver-opts: |
Expand All @@ -139,15 +104,13 @@ jobs:
buildkitd-flags: --debug

- name: Login to ghcr
if: ${{ github.event_name == 'workflow_dispatch' || steps.changes.outputs.changed == 'true' || steps.changes.outputs.shared_utils_changed == 'true' || steps.changes.outputs.dockerfile_changed == 'true' || steps.changes.outputs.compose_changed == 'true' || steps.changes.outputs.workflow_changed == 'true' }}
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GHA_PAT }}

- name: Build and push
if: ${{ github.event_name == 'workflow_dispatch' || steps.changes.outputs.changed == 'true' || steps.changes.outputs.shared_utils_changed == 'true' || steps.changes.outputs.dockerfile_changed == 'true' || steps.changes.outputs.compose_changed == 'true' || steps.changes.outputs.workflow_changed == 'true' }}
uses: docker/bake-action@v7
with:
push: true
Expand All @@ -160,5 +123,5 @@ jobs:
*.labels.org.opencontainers.image.revision=${{ github.sha }}
*.labels.org.opencontainers.image.created=${{ env.BUILD_DATE }}
*.labels.org.opencontainers.image.version=${{ env.DOCKER_TAG }}
*.cache-from=
*.cache-to=
*.cache-from=type=gha,scope=${{ matrix.service }}
*.cache-to=type=gha,mode=max,scope=${{ matrix.service }}
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@ on:
permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
bun-version: 1.3.14
- name: Cache bun install
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
uses: nick-fields/retry@v3
uses: nick-fields/retry@v4
with:
timeout_minutes: 5
max_attempts: 3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/subscription-health-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
bun-version: 1.3.14

- name: Delete Steam package.json
run: rm -f packages/steam/package.json
Expand Down
20 changes: 0 additions & 20 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ services:
args:
- DOTABOD_ENV=${DOTABOD_ENV:-development}
- BUILD_CONTEXT=packages/twitch-chat
x-bake:
cache-from:
- "ghcr.io/dotabod/cache-twitch-chat:master"
cache-to:
- "ghcr.io/dotabod/cache-twitch-chat:master"
hostname: twitch-chat
environment:
- DATABASE_URL
Expand All @@ -42,11 +37,6 @@ services:
args:
- DOTABOD_ENV=${DOTABOD_ENV:-development}
- BUILD_CONTEXT=packages/steam
x-bake:
cache-from:
- "ghcr.io/dotabod/cache-steam:master"
cache-to:
- "ghcr.io/dotabod/cache-steam:master"
hostname: steam
environment:
- MONGO_URL
Expand All @@ -67,11 +57,6 @@ services:
args:
- DOTABOD_ENV=${DOTABOD_ENV:-development}
- BUILD_CONTEXT=packages/twitch-events
x-bake:
cache-from:
- "ghcr.io/dotabod/cache-twitch-events:master"
cache-to:
- "ghcr.io/dotabod/cache-twitch-events:master"
hostname: twitch-events
environment:
- DATABASE_URL
Expand Down Expand Up @@ -104,11 +89,6 @@ services:
args:
- DOTABOD_ENV=${DOTABOD_ENV:-development}
- BUILD_CONTEXT=packages/dota
x-bake:
cache-from:
- "ghcr.io/dotabod/cache-dota:master"
cache-to:
- "ghcr.io/dotabod/cache-dota:master"
hostname: dota
environment:
- D2PT_TOKEN
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"typecheck:all": "bun run --cwd packages/shared-utils typecheck && bun run --cwd packages/profanity-filter typecheck && bun run --cwd packages/dota typecheck && bun run --cwd packages/twitch-chat typecheck && bun run --cwd packages/twitch-events typecheck && bun run --cwd packages/steam typecheck",
"lint:all": "biome check .",
"test": "bun run --cwd packages/dota test",
"test:all": "bun run --cwd packages/shared-utils test && bun run --cwd packages/profanity-filter test && bun run --cwd packages/dota test"
"test:all": "bun run --cwd packages/shared-utils test && bun run --cwd packages/profanity-filter test && bun run --cwd packages/dota test && bun run --cwd packages/twitch-events test && bun run --cwd packages/twitch-chat test"
},
"trustedDependencies": [
"@biomejs/biome",
Expand Down
6 changes: 6 additions & 0 deletions packages/clip-processor-py/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ assets/reference.png

# Virtual environment
venv/
.venv/
.env/

# pytest / coverage
.pytest_cache/
.coverage
htmlcov/

# Editor files
.vscode/
.idea/
Expand Down
22 changes: 22 additions & 0 deletions packages/clip-processor-py/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[tool.pytest.ini_options]
minversion = "8.0"
addopts = "-ra -q --strict-markers --import-mode=importlib"
testpaths = ["tests"]
# api_server.py imports both `dota_hero_detection` (needs src on path) and
# `src.postgresql_client` (needs the package root on path), so expose both.
pythonpath = [".", "src"]

[dependency-groups]
dev = [
"pytest>=8",
"pytest-cov",
"pytest-mock",
# Light runtime deps the modules import at module load time. The heavy native
# deps (opencv/numpy/streamlink/etc.) are stubbed in tests/conftest.py.
"flask",
"requests",
"psutil",
"psycopg2-binary",
"beautifulsoup4",
"Pillow",
]
2 changes: 1 addition & 1 deletion packages/clip-processor-py/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ beautifulsoup4==4.12.2
tqdm==4.66.3
flask==3.1.3
gunicorn==23.0.0
streamlink==6.5.0
streamlink==8.4.0
psycopg2-binary==2.9.9
waitress==3.0.1
psutil==5.9.8
Expand Down
Loading
Loading