From fc53d299059c52ca63b07f1cc2e199acbdac3175 Mon Sep 17 00:00:00 2001 From: Mateusz Daniluk <121170681+VeithMetro@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:37:57 +0100 Subject: [PATCH] [Actions] Add a workflow for reviewing LuaGenerator changes --- .github/workflows/LuaGenerator.yml | 392 +++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 .github/workflows/LuaGenerator.yml diff --git a/.github/workflows/LuaGenerator.yml b/.github/workflows/LuaGenerator.yml new file mode 100644 index 0000000..1c8dcd8 --- /dev/null +++ b/.github/workflows/LuaGenerator.yml @@ -0,0 +1,392 @@ +name: LuaGenerator Checks + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - "LuaGenerator/**" + - "ProxyStubGenerator/**" + - ".github/workflows/LuaGenerator.yml" + - ".github/workflows/ProxyStubGenerator.yml" + pull_request: + branches: [ master ] + paths: + - "LuaGenerator/**" + - "ProxyStubGenerator/**" + - ".github/workflows/LuaGenerator.yml" + - ".github/workflows/ProxyStubGenerator.yml" + +permissions: + contents: write + pull-requests: write + models: read + +concurrency: + group: luagenerator-previews-${{ github.head_ref || github.ref }} + cancel-in-progress: false + +jobs: + generate_lua: + runs-on: ubuntu-latest + steps: + - name: Checkout ThunderTools + uses: actions/checkout@v4 + with: + path: ThunderTools + + - name: Checkout Thunder + uses: actions/checkout@v4 + with: + repository: rdkcentral/Thunder + path: Thunder + + - name: Checkout ThunderInterfaces + uses: actions/checkout@v4 + with: + repository: rdkcentral/ThunderInterfaces + path: ThunderInterfaces + + - name: Run LuaGenerator + shell: bash + run: | + set -euo pipefail + + # The script expects to run relative to its location or with dependencies nearby + cd ThunderTools/LuaGenerator + + # Make sure script is executable + chmod +x GenerateLua.sh + + echo "Running GenerateLua.sh..." + ./GenerateLua.sh + + # Verify output exists + if [[ ! -f "protocol-thunder-comrpc.data" ]]; then + echo "::error::Output file 'protocol-thunder-comrpc.data' was not created!" + ls -la + exit 1 + fi + + echo "Generation successful." + + - name: Prepare Artifacts + shell: bash + run: | + mkdir -p generated_lua + mv ThunderTools/LuaGenerator/protocol-thunder-comrpc.data generated_lua/ + + - name: Upload Generated Lua Data + uses: actions/upload-artifact@v4 + with: + name: LuaGenerator-Output + path: generated_lua/ + retention-days: 1 + + publish_pages: + runs-on: ubuntu-latest + needs: generate_lua + + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + + steps: + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + name: LuaGenerator-Output + path: generated + + - name: Checkout gh-pages (baseline) + if: github.event_name == 'pull_request' + continue-on-error: true + uses: actions/checkout@v4 + with: + ref: gh-pages + path: ghpages_baseline + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Build static preview site + id: build_site + shell: bash + env: + TOOL_NAME: "LuaGenerator" + run: | + set -euo pipefail + + HAS_DIFF="false" + mkdir -p site + + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + BASE_DIR="previews/pr-${{ github.event.pull_request.number }}" + else + BASE_DIR="master" + fi + + RUN_DIR="${BASE_DIR}/run-${{ github.run_id }}" + + # ----- Save for future steps ----- + echo "RUN_DIR=$RUN_DIR" >> "$GITHUB_ENV" + + # ----- Export for current step ----- + export RUN_DIR + export HAS_DIFF + + mkdir -p "site/$RUN_DIR" + touch site/.nojekyll + + # ----- PR-only: diff vs gh-pages baseline ----- + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + BASELINE_ROOT="${PWD}/ghpages_baseline/${TOOL_NAME}/master/latest_raw" + mkdir -p diffs "site/$RUN_DIR/diff" + + if [[ -d "$BASELINE_ROOT" ]]; then + git diff --no-index \ + --src-prefix=baseline/ \ + --dst-prefix=generated/ \ + -- "$BASELINE_ROOT" "generated" \ + > "diffs/combined.diff" || true + else + mkdir empty_dir + git diff --no-index \ + --src-prefix=baseline/ \ + --dst-prefix=generated/ \ + -- "empty_dir" "generated" \ + > "diffs/combined.diff" || true + fi + + if [[ -s "diffs/combined.diff" ]]; then + HAS_DIFF="true" + export HAS_DIFF + + npx --yes diff2html-cli@5.2.15 -i file -F "site/$RUN_DIR/diff/index.html" -- "diffs/combined.diff" + head -c 50000 diffs/combined.diff > diffs/combined_trunc.diff + else + mkdir -p "site/$RUN_DIR/diff" + echo "

No changes detected

" > "site/$RUN_DIR/diff/index.html" + fi + fi + + echo "has_diff=$HAS_DIFF" >> "$GITHUB_OUTPUT" + + # ----- Copy files for browsing ----- + mkdir -p "site/$RUN_DIR/browse" + cp -r generated/* "site/$RUN_DIR/browse/" + + # ----- Generate Site with Python ----- + RUN_DIR="$RUN_DIR" HAS_DIFF="$HAS_DIFF" python - <<'PY' + import os + from pathlib import Path + import html + + run_dir = os.environ["RUN_DIR"] + has_diff = os.environ.get("HAS_DIFF") == "true" + + site_root = Path("site") / run_dir + browse_root = site_root / "browse" + + # ----- Generate Dark Theme CSS ----- + css_path = site_root / "assets" / "style.css" + css_path.parent.mkdir(parents=True, exist_ok=True) + css_path.write_text(""" + :root{color-scheme:dark;--bg:#0d1117;--fg:#c9d1d9;--muted:#8b949e;--link:#58a6ff;--border:#30363d;--card:#161b22;} + body{margin:0;font:18px/1.55 system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--fg)} + a{color:var(--link);text-decoration:none} a:hover{text-decoration:underline} + .container{max-width:1100px;margin:0 auto;padding:24px} + .nav{display:flex;gap:14px;padding:14px 24px;border-bottom:1px solid var(--border);background:rgba(13,17,23,.95);position:sticky;top:0} + .nav a{padding:6px 12px;border:1px solid var(--border);border-radius:6px;background:var(--card)} + ul{list-style:none;padding:0} li{padding:4px 0} + """, encoding="utf-8") + + def nav_html(rel_home): + links = [f"Home", f"Browse Files"] + if has_diff: + links.append(f"View Diff") + return "".join(links) + + def wrap_page(title, body, rel_path=""): + return f""" + {title} + + + +
{body}
+ """ + + def generate_index(directory): + items = sorted(directory.iterdir(), key=lambda p: (p.is_file(), p.name)) + links = [] + + if directory != browse_root: + links.append(f"
  • .. (Parent Directory)
  • ") + + for item in items: + if item.name == "index.html": continue + name = item.name + ("/" if item.is_dir() else "") + href = item.name + ("/index.html" if item.is_dir() else "") + links.append(f"
  • {name}
  • ") + + body = f"

    Index of {html.escape(directory.name)}

    " + + depth = len(directory.relative_to(site_root).parts) + rel_assets = "../" * depth + + (directory / "index.html").write_text(wrap_page(directory.name, body, rel_assets), encoding="utf-8") + + for item in items: + if item.is_dir(): + generate_index(item) + + if browse_root.exists(): + generate_index(browse_root) + + main_body = """ +

    LuaGenerator Results

    +

    Generated protocol data from GenerateLua.sh.

    + " + (site_root / "index.html").write_text(wrap_page("LuaGenerator Results", main_body, ""), encoding="utf-8") + PY + + # ----- Master Push: Update Baseline ----- + if [[ "${{ github.event_name }}" != "pull_request" ]]; then + echo "Updating master baseline..." + + # Update Browsable Site + rm -rf "site/master/latest" + mkdir -p "site/master/latest" + cp -a "site/$RUN_DIR"/* "site/master/latest/" + + # Update Raw Baseline + rm -rf "site/master/latest_raw" + mkdir -p "site/master/latest_raw" + cp -r generated/* "site/master/latest_raw/" + + echo "Baseline updated." + fi + + - name: Deploy to gh-pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./site + destination_dir: LuaGenerator + keep_files: true + + - name: AI Summary + if: github.event_name == 'pull_request' && steps.build_site.outputs.has_diff == 'true' + id: ai + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + set -euo pipefail + + python - <<'PY' + import json + import os + import urllib.request + import sys + + # ----- Read diff ----- + diff_path = "diffs/combined_trunc.diff" + try: + with open(diff_path, "r", encoding="utf-8", errors="ignore") as f: + diff_text = f.read() + except Exception as e: + print(f"::warning::Could not read diff file: {e}") + sys.exit(0) + + if not diff_text.strip(): + print("::warning::Diff text is empty.") + sys.exit(0) + + url = "https://models.github.ai/inference/chat/completions" + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {os.environ['GH_TOKEN']}", + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28" + } + + SAFE_LIMIT = 25000 + + payload = { + "model": "openai/gpt-4.1", + "messages": [ + {"role": "system", "content": "You are a Lua/Data serialization expert. Summarize the changes in this diff. Start with bullet points."}, + {"role": "user", "content": diff_text[:SAFE_LIMIT]} + ], + "temperature": 0.5 + } + + try: + req = urllib.request.Request(url, data=json.dumps(payload).encode("utf-8"), headers=headers) + with urllib.request.urlopen(req) as resp: + data = json.load(resp) + summary = data.get("choices", [{}])[0].get("message", {}).get("content", "") + + if summary: + with open(os.environ["GITHUB_OUTPUT"], "a") as gh_out: + gh_out.write("summary<