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
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,13 @@ LOG_LEVEL=info
# the app has no authentication, so every allowed origin can read your
# projects and push to your displays.
CORS_ORIGINS=

# Hostnames the editor answers to (DNS rebinding protection), comma separated.
# IP addresses, localhost, dot-less names and *.local / *.lan / *.home.arpa
# work out of the box. Add your reverse-proxy domain here, e.g.
# epaper.example.com or *.example.com. Use * to disable the check.
ALLOWED_HOSTS=

# Home Assistant service domains "Send to display" may call, comma separated.
# Defaults to open_epaper_link.
ALLOWED_SERVICE_DOMAINS=
99 changes: 99 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: CI

on:
push:
branches: ["**"]
pull_request:
workflow_dispatch:

permissions:
contents: read

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

jobs:
backend:
name: Backend (tests + lint)
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: backend/requirements-dev.txt

- name: Install dependencies
run: pip install -r requirements-dev.txt

- name: Lint
run: ruff check app

- name: Test
run: python -m pytest -q app

frontend:
name: Frontend (syntax)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"

# There is no build step: the browser loads the modules directly. Parsing
# every file still catches syntax errors and broken imports that a
# type-free module graph would otherwise surface only at runtime.
- name: Check module syntax
run: |
rc=0
for file in frontend/js/*.js; do
if ! node --check "$file"; then
echo "::error file=$file::Syntax error"
rc=1
fi
done
exit $rc

- name: Check imports resolve
run: |
rc=0
for file in frontend/js/*.js; do
# Every relative import must point at a file that exists.
while read -r target; do
[ -z "$target" ] && continue
resolved="$(dirname "$file")/$target"
if [ ! -f "$resolved" ]; then
echo "::error file=$file::Unresolved import '$target'"
rc=1
fi
done < <(grep -oE "from '\./[^']+'" "$file" | sed "s/from '//; s/'$//")
done
exit $rc

docker:
name: Docker image builds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: docker/setup-buildx-action@v3

# Build only; nothing is pushed. This catches a broken Dockerfile, a
# missing COPY source or a dependency that fails to install.
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: backend/Dockerfile
push: false
load: false
cache-from: type=gha
cache-to: type=gha,mode=max
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ data/
.env
.DS_Store
.vscode/
.mypy_cache/
.pytest_cache/
.ruff_cache/

# Fonts for the pixel-accurate preview. Downloaded by
# backend/scripts/fetch_assets.py (and at Docker build time) with size and
# SHA-1 verification, so they are not committed.
backend/app/assets/
Loading
Loading