diff --git a/.github/workflows/main-branch.yml b/.github/workflows/main-branch.yml index ff5d50a..570338f 100644 --- a/.github/workflows/main-branch.yml +++ b/.github/workflows/main-branch.yml @@ -30,37 +30,7 @@ jobs: pip install -r requirements.txt - name: Build static site bundle - run: | - python - <<'PY' - import json - import shutil - import time - from pathlib import Path - - start = time.perf_counter() - root = Path('.') - dist = Path('dist') - if dist.exists(): - shutil.rmtree(dist) - dist.mkdir(parents=True, exist_ok=True) - - for asset in ['index.html', 'style.css', 'app.js', 'ai-instruct.txt']: - shutil.copy2(root / asset, dist / asset) - - duration = time.perf_counter() - start - report_dir = Path('ci_reports') - report_dir.mkdir(parents=True, exist_ok=True) - (report_dir / 'build_status.json').write_text( - json.dumps( - { - 'status': 'succeeded', - 'artifact': 'github-pages', - 'duration': duration, - }, - indent=2, - ) - ) - PY + run: python scripts/build_static.py - name: Upload static artifact uses: actions/upload-pages-artifact@v3 diff --git a/README.md b/README.md index 33970bd..f644f42 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,10 @@ Two separate GitHub Actions workflows keep deployments fast and informative: - **Main Branch Delivery** (`.github/workflows/main-branch.yml`) - Triggers on pushes to `main` and manual dispatches. - - Builds the static bundle, uploads the GitHub Pages artifact, and records a - machine-readable build summary. + - Runs `scripts/build_static.py`, which inlines the CSS and JavaScript so the + GitHub Pages artifact is a self-contained `index.html` (eliminating missing + asset issues on the published site). + - Uploads the bundle artifact and records a machine-readable build summary. - Executes the same test suite and reports results without blocking deploys. - Deploys successful builds to GitHub Pages. diff --git a/index.html b/index.html index d7fa67b..fb25e4d 100644 --- a/index.html +++ b/index.html @@ -4,8 +4,12 @@ Unity Voice Chat + + + + diff --git a/scripts/build_static.py b/scripts/build_static.py new file mode 100644 index 0000000..c9275f8 --- /dev/null +++ b/scripts/build_static.py @@ -0,0 +1,88 @@ +"""Build the GitHub Pages bundle with inlined assets.""" +from __future__ import annotations + +import json +import shutil +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +DIST = ROOT / "dist" +CI_REPORTS = ROOT / "ci_reports" + +CSS_START = "" +CSS_END = "" +JS_START = "" +JS_END = "" + + +def replace_block(source: str, start_marker: str, end_marker: str, replacement: str) -> str: + """Replace the block delimited by the provided markers. + + Raises a ValueError when the markers are missing so the workflow fails fast + instead of silently producing a broken bundle. + """ + + try: + start_index = source.index(start_marker) + len(start_marker) + end_index = source.index(end_marker) + except ValueError as exc: # pragma: no cover - defensive guard + raise ValueError( + "Build markers missing in index.html. Ensure the start and end " + f"markers {start_marker!r} and {end_marker!r} exist." + ) from exc + + before = source[:start_index] + after = source[end_index:] + return f"{before}\n{replacement}\n{after}" + + +def build() -> None: + start = time.perf_counter() + + if DIST.exists(): + shutil.rmtree(DIST) + DIST.mkdir(parents=True, exist_ok=True) + + index_html = (ROOT / "index.html").read_text(encoding="utf-8") + css = (ROOT / "style.css").read_text(encoding="utf-8") + javascript = (ROOT / "app.js").read_text(encoding="utf-8") + + inlined_index = replace_block( + index_html, + CSS_START, + CSS_END, + f"", + ) + inlined_index = replace_block( + inlined_index, + JS_START, + JS_END, + f"", + ) + + (DIST / "index.html").write_text(inlined_index, encoding="utf-8") + + # Keep the original assets alongside the inlined bundle for local debugging + # and to avoid breaking any bookmarked resources. + shutil.copy2(ROOT / "style.css", DIST / "style.css") + shutil.copy2(ROOT / "app.js", DIST / "app.js") + shutil.copy2(ROOT / "ai-instruct.txt", DIST / "ai-instruct.txt") + + duration = time.perf_counter() - start + CI_REPORTS.mkdir(parents=True, exist_ok=True) + (CI_REPORTS / "build_status.json").write_text( + json.dumps( + { + "status": "succeeded", + "artifact": "github-pages", + "duration": duration, + }, + indent=2, + ), + encoding="utf-8", + ) + + +if __name__ == "__main__": + build()