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
Binary file not shown.
136 changes: 136 additions & 0 deletions .github/scripts/build_locale_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env python3
from __future__ import annotations

import argparse
import re
import shutil
import subprocess
import sys
from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile


ROOT = Path(__file__).resolve().parents[2]
SOURCE_APP_DIR = ROOT / "src" / "dashx"
I18N_BUILDER = ROOT / "bin" / "i18n" / "build-single-json.py"
I18N_RESOLVER = ROOT / ".vscode" / "scripts" / "resolve_i18n_tags.py"
SOUNDPACK_ROOT = ROOT / "bin" / "sound-generator" / "soundpack"


def update_version_suffix(main_lua_path: Path, version: str) -> None:
text = main_lua_path.read_text(encoding="utf-8")
updated_text, replacements = re.subn(
r'(version\s*=\s*\{[^}]*?suffix\s*=\s*")[^"]*(")',
lambda match: f'{match.group(1)}{version}{match.group(2)}',
text,
count=1,
flags=re.DOTALL,
)
if replacements != 1:
raise RuntimeError(f"Could not update version suffix in {main_lua_path}")
main_lua_path.write_text(updated_text, encoding="utf-8")


def copy_soundpack(lang: str, stage_app_dir: Path) -> None:
source_dir = SOUNDPACK_ROOT / lang
if not source_dir.is_dir():
fallback_dir = SOUNDPACK_ROOT / "en"
print(f"[AUDIO] {source_dir} not found; falling back to {fallback_dir}")
source_dir = fallback_dir

if not source_dir.is_dir():
print(f"[AUDIO] No sound pack found for {lang} or fallback locale en. Skipping.")
return

dest_dir = stage_app_dir / "audio" / lang
shutil.copytree(source_dir, dest_dir, dirs_exist_ok=True)
print(f"[AUDIO] Copied {source_dir} -> {dest_dir}")


def build_locale_json(lang: str, stage_i18n_dir: Path) -> Path:
generated_locale = ROOT / "scripts" / "dashx" / "i18n" / f"{lang}.json"

subprocess.run(
[
sys.executable,
str(I18N_BUILDER),
"--only",
lang,
],
check=True,
cwd=ROOT,
)

if not generated_locale.is_file():
raise FileNotFoundError(f"expected locale bundle was not created: {generated_locale}")

stage_i18n_dir.mkdir(parents=True, exist_ok=True)
staged_locale = stage_i18n_dir / f"{lang}.json"
shutil.copy2(generated_locale, staged_locale)
return staged_locale


def create_zip(zip_path: Path, lang_root: Path) -> None:
if zip_path.exists():
zip_path.unlink()

with ZipFile(zip_path, "w", compression=ZIP_DEFLATED, compresslevel=9) as archive:
for path in sorted(lang_root.rglob("*")):
if path.is_file():
archive.write(path, path.relative_to(lang_root))


def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Build a per-locale DashX package from src/dashx")
parser.add_argument("--lang", required=True, help="Locale code to package, e.g. en or de")
parser.add_argument("--version", required=True, help="Version suffix to inject into main.lua")
parser.add_argument("--artifact", required=True, help="Output zip path, relative to repo root or absolute")
parser.add_argument("--build-root", default="build", help="Directory used for staging package contents")
args = parser.parse_args(argv)

if not SOURCE_APP_DIR.is_dir():
print(f"ERROR: source app directory not found: {SOURCE_APP_DIR}", file=sys.stderr)
return 1

lang_root = (ROOT / args.build_root / args.lang).resolve()
stage_root = lang_root / "scripts"
stage_app_dir = stage_root / "dashx"
artifact_path = Path(args.artifact)
if not artifact_path.is_absolute():
artifact_path = (ROOT / artifact_path).resolve()

if lang_root.exists():
shutil.rmtree(lang_root)

shutil.copytree(SOURCE_APP_DIR, stage_app_dir)
print(f"[BUILD] Staged {SOURCE_APP_DIR} -> {stage_app_dir}")

i18n_dir = stage_app_dir / "i18n"
try:
locale_json = build_locale_json(args.lang, i18n_dir)
except Exception as exc:
print(f"ERROR: {exc}", file=sys.stderr)
return 1

subprocess.run(
[
sys.executable,
str(I18N_RESOLVER),
"--json",
str(locale_json),
"--root",
str(stage_root),
],
check=True,
cwd=ROOT,
)

copy_soundpack(args.lang, stage_app_dir)
update_version_suffix(stage_app_dir / "main.lua", args.version)
create_zip(artifact_path, lang_root)
print(f"[BUILD] Created {artifact_path}")
return 0


if __name__ == "__main__":
raise SystemExit(main())
66 changes: 10 additions & 56 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@ on:
types: [opened, synchronize, reopened]

jobs:
# Per-language PR builds (mirrors push.yml behavior)
create-zip:
name: Build PR ZIP (${{ matrix.lang }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# 👇 keep this in sync with push.yml (add/remove locales as needed)
lang: [en, de , es, fr, it, nl]

env:
STAGE: build/${{ matrix.lang }}/scripts
lang: [en, de, es, fr, it, nl]

steps:
- name: Checkout code
Expand All @@ -30,61 +25,20 @@ jobs:
- name: Set build variables (PR version)
run: |
PR_NUMBER='${{ github.event.pull_request.number }}'
echo "GIT_VER=PR-${PR_NUMBER}" >> $GITHUB_ENV

# Build merged i18n JSON only for this locale (into src/dashx/i18n/<lang>.json)
- name: Build merged i18n JSON (${{ matrix.lang }})
run: |
python bin/i18n/build-single-json.py --only '${{ matrix.lang }}'
test -f "src/dashx/i18n/${{ matrix.lang }}.json"

# Stage scripts/ into build/<lang>/scripts
- name: Stage scripts tree
run: |
rm -rf "${{ env.STAGE }}"
mkdir -p "${{ env.STAGE }}"
cp -a src/. "${{ env.STAGE }}/"

# Resolve @i18n(...)@ tags in the staged tree using the staged locale file
- name: Resolve i18n tags (locale=${{ matrix.lang }})
run: |
python .vscode/scripts/resolve_i18n_tags.py \
--json "${{ env.STAGE }}/dashx/i18n/${{ matrix.lang }}.json" \
--root "${{ env.STAGE }}"

# Copy sound pack for this locale into the staged tree (fallback to en)
- name: Copy sound pack (locale=${{ matrix.lang }})
run: |
SRC="bin/sound-generator/soundpack/${{ matrix.lang }}"
if [ ! -d "$SRC" ]; then
echo "[AUDIO] $SRC not found; falling back to bin/sound-generator/soundpack/en"
SRC="bin/sound-generator/soundpack/en"
fi
if [ -d "$SRC" ]; then
DEST="${{ env.STAGE }}/dashx/audio/${{ matrix.lang }}"
rm -rf "$DEST"
mkdir -p "$DEST"
cp -a "$SRC/." "$DEST/"
echo "[AUDIO] Copied $SRC -> $DEST"
else
echo "[AUDIO] No sound pack found (lang='${{ matrix.lang }}' or 'en'). Skipping."
fi

# Write PR version suffix into the *staged* main.lua
- name: Update version and config in staged main.lua
run: |
sed -E -i "s/(version[[:space:]]*=[[:space:]]*\{[^}]*suffix[[:space:]]*=[[:space:]]*\")[^\"]*(\")/\1${{ env.GIT_VER }}\2/" "${{ env.STAGE }}/dashx/main.lua"
grep 'config\.' "${{ env.STAGE }}/dashx/main.lua" || true
echo "GIT_VER=PR-${PR_NUMBER}" >> "$GITHUB_ENV"

# Zip the staged scripts (includes i18n + audio for this locale)
- name: Create dashx-${{ env.GIT_VER }}-${{ matrix.lang }}.zip
- name: Build package for locale ${{ matrix.lang }}
run: |
( cd "build/${{ matrix.lang }}" && zip -q -r -9 "dashx-${{ env.GIT_VER }}-${{ matrix.lang }}.zip" scripts )
mv "build/${{ matrix.lang }}/dashx-${{ env.GIT_VER }}-${{ matrix.lang }}.zip" .
ART="dashx-${{ env.GIT_VER }}-${{ matrix.lang }}.zip"
python .github/scripts/build_locale_package.py \
--lang "${{ matrix.lang }}" \
--version "${{ env.GIT_VER }}" \
--artifact "$ART"
echo "ARTIFACT=$ART" >> "$GITHUB_ENV"

- name: Upload per-locale ZIP
uses: actions/upload-artifact@v4
with:
name: dashx-${{ env.GIT_VER }}-${{ matrix.lang }}
path: dashx-${{ env.GIT_VER }}-${{ matrix.lang }}.zip
path: ${{ env.ARTIFACT }}
if-no-files-found: error
64 changes: 11 additions & 53 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ name: Create dashx-lua-ethos ZIP on Push
on:
push:
branches:
- 'master'
- 'RF-*'
- "master"
- "RF-*"

jobs:
create-zip:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# ←—— add/remove locales here
lang: [en, de , es, fr, it, nl]
lang: [en, de, es, fr, it, nl]

steps:
- name: Checkout code
Expand All @@ -29,63 +28,22 @@ jobs:
shell: bash
run: |
SHORT_SHA="${GITHUB_SHA::7}"
echo "GIT_VER=commit-${SHORT_SHA}" >> $GITHUB_ENV
echo "sha7=${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "GIT_VER=commit-${SHORT_SHA}" >> "$GITHUB_ENV"
echo "sha7=${SHORT_SHA}" >> "$GITHUB_OUTPUT"

# Build merged JSON for the specific locale (writes to src/dashx/i18n/<locale>.json)
- name: Build i18n for this locale
run: python bin/i18n/build-single-json.py --only ${{ matrix.lang }}

# Stage a per-locale copy to avoid mutating the repo
- name: Stage files for this locale
shell: bash
run: |
STAGE="build/${{ matrix.lang }}/scripts"
mkdir -p "$STAGE"
rsync -a src/ "$STAGE"/
echo "STAGE=$STAGE" >> $GITHUB_ENV

# Update version in the staged copy
- name: Update version and config in main.lua (staged)
run: |
sed -E -i "s/(version[[:space:]]*=[[:space:]]*\{[^}]*suffix[[:space:]]*=[[:space:]]*\")[^\"]*(\")/\1${{ env.GIT_VER }}\2/" "${{ env.STAGE }}/dashx/main.lua"
grep 'config\.' "${{ env.STAGE }}/dashx/main.lua" || true

# Resolve @i18n(...)@ tags in the staged tree using the chosen locale
- name: Resolve i18n tags (locale=${{ matrix.lang }})
run: |
python .vscode/scripts/resolve_i18n_tags.py \
--json "${{ env.STAGE }}/dashx/i18n/${{ matrix.lang }}.json" \
--root "${{ env.STAGE }}"

# Copy sound pack for this locale into the staged tree
- name: Copy sound pack (locale=${{ matrix.lang }})
shell: bash
run: |
SRC="bin/sound-generator/soundpack/${{ matrix.lang }}"
if [ ! -d "$SRC" ]; then
echo "[AUDIO] $SRC not found; falling back to bin/sound-generator/soundpack/en"
SRC="bin/sound-generator/soundpack/en"
fi
DEST="${{ env.STAGE }}/dashx/audio/${{ matrix.lang }}"
rm -rf "$DEST"
mkdir -p "$DEST"
cp -a "$SRC/." "$DEST/"
echo "[AUDIO] Copied $SRC -> $DEST"

# Zip only the staged scripts folder for this locale
- name: Create dashx-<lang>-commit-<sha7>.zip
- name: Build package for locale ${{ matrix.lang }}
shell: bash
run: |
ART="dashx-${{ matrix.lang }}-${{ env.GIT_VER }}.zip"
(cd build/${{ matrix.lang }} && zip -q -r -9 "../$ART" scripts)
mv "build/${{ matrix.lang }}/../$ART" .
echo "ARTIFACT=$ART" >> $GITHUB_ENV
python .github/scripts/build_locale_package.py \
--lang "${{ matrix.lang }}" \
--version "${{ env.GIT_VER }}" \
--artifact "$ART"
echo "ARTIFACT=$ART" >> "$GITHUB_ENV"

- name: Upload per-locale artifact
uses: actions/upload-artifact@v4
with:
name: dashx-${{ matrix.lang }}-${{ env.GIT_VER }}
path: ${{ env.ARTIFACT }}
if-no-files-found: error

Loading
Loading