Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 21 additions & 6 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
uses: actions/checkout@v5

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
Expand Down Expand Up @@ -85,15 +86,19 @@ jobs:
echo "EOF"
} >> "$GITHUB_OUTPUT"

- name: Prepare CPU build cache
run: mkdir -p /mnt/docker-cache/cpu

- name: Build and push CPU image
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
push: ${{ github.event_name == 'push' || inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=local,src=/mnt/docker-cache
cache-to: type=local,dest=/mnt/docker-cache,mode=max
cache-from: type=local,src=/mnt/docker-cache/cpu
cache-to: type=local,dest=/mnt/docker-cache/cpu,mode=max
platforms: linux/amd64
provenance: false

Expand All @@ -109,6 +114,7 @@ jobs:
uses: actions/checkout@v5

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
Expand Down Expand Up @@ -142,15 +148,19 @@ jobs:
echo "EOF"
} >> "$GITHUB_OUTPUT"

- name: Prepare GPU build cache
run: mkdir -p /mnt/docker-cache/gpu

- name: Build and push GPU image
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile.gpu
push: ${{ github.event_name == 'push' || inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=local,src=/mnt/docker-cache
cache-to: type=local,dest=/mnt/docker-cache,mode=max
cache-from: type=local,src=/mnt/docker-cache/gpu
cache-to: type=local,dest=/mnt/docker-cache/gpu,mode=max
platforms: linux/amd64
provenance: false

Expand All @@ -166,6 +176,7 @@ jobs:
uses: actions/checkout@v5

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
Expand Down Expand Up @@ -199,14 +210,18 @@ jobs:
echo "EOF"
} >> "$GITHUB_OUTPUT"

- name: Prepare Demo build cache
run: mkdir -p /mnt/docker-cache/demo

- name: Build and push Demo image
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile.demo
push: ${{ github.event_name == 'push' || inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=local,src=/mnt/docker-cache
cache-to: type=local,dest=/mnt/docker-cache,mode=max
cache-from: type=local,src=/mnt/docker-cache/demo
cache-to: type=local,dest=/mnt/docker-cache/demo,mode=max
platforms: linux/amd64
provenance: false
3 changes: 3 additions & 0 deletions .github/workflows/skit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ jobs:
steps:
- uses: actions/checkout@v5

- name: Check Docker workflow
run: python3 scripts/check_docker_workflow.py

- uses: ./.github/actions/setup-skit
with:
rust-cache-key: skit-lint
Expand Down
6 changes: 5 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ lint-ui: install-ui
@echo "Linting UI..."
@bun run lint

# Validate Docker workflow builder and cache isolation
check-docker-workflow:
@python3 scripts/check_docker_workflow.py

# Auto-fix UI code formatting and linting issues
[working-directory: 'ui']
fix-ui: install-ui
Expand Down Expand Up @@ -538,7 +542,7 @@ build: build-skit build-ui build-plugins
test: test-skit test-ui

# Lint all code
lint: lint-skit lint-ui lint-plugins check-license-headers
lint: lint-skit lint-ui lint-plugins check-license-headers check-docker-workflow

# Start full development environment (skit + frontend with hot reload)
dev: install-ui
Expand Down
59 changes: 59 additions & 0 deletions scripts/check_docker_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: 漏 2025 StreamKit Contributors
#
# SPDX-License-Identifier: MPL-2.0

from pathlib import Path
import re
import sys


WORKFLOW_PATH = Path(__file__).resolve().parents[1] / ".github/workflows/docker.yml"
EXPECTED_JOBS = {
"build-cpu": "/mnt/docker-cache/cpu",
"build-gpu": "/mnt/docker-cache/gpu",
"build-demo": "/mnt/docker-cache/demo",
}


def extract_job_blocks(workflow: str) -> dict[str, str]:
pattern = re.compile(
r"(?ms)^ (?P<job>build-cpu|build-gpu|build-demo):\n"
r"(?P<body>.*?)(?=^ [A-Za-z0-9_-]+:\n|\Z)"
)
return {match.group("job"): match.group("body") for match in pattern.finditer(workflow)}


def check_job(job: str, cache_path: str, block: str) -> list[str]:
checks = {
"setup-buildx step id": "id: buildx",
"explicit builder": "builder: ${{ steps.buildx.outputs.name }}",
"cache import": f"cache-from: type=local,src={cache_path}",
"cache export": f"cache-to: type=local,dest={cache_path},mode=max",
"cache directory preparation": f"mkdir -p {cache_path}",
}
return [f"{job}: missing {name}" for name, value in checks.items() if value not in block]


def main() -> int:
workflow = WORKFLOW_PATH.read_text()
blocks = extract_job_blocks(workflow)
errors = [
f"{job}: job block not found"
for job in EXPECTED_JOBS
if job not in blocks
]
for job, cache_path in EXPECTED_JOBS.items():
if job in blocks:
errors.extend(check_job(job, cache_path, blocks[job]))

if errors:
print("Docker workflow validation failed:", file=sys.stderr)
print("\n".join(f"- {error}" for error in errors), file=sys.stderr)
return 1

print("Docker workflow validation passed for build-cpu, build-gpu, and build-demo.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
Loading