feat: Add WebUI auto-build workflow

This commit is contained in:
Aleksander Grygier 2025-11-12 19:34:33 +01:00
parent 8e878f0cb4
commit 2782953d79
1 changed files with 231 additions and 0 deletions

231
.github/workflows/webui-auto-build.yml vendored Normal file
View File

@ -0,0 +1,231 @@
name: WebUI Auto-Build
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- ".github/workflows/webui-auto-build.yml"
- "tools/server/webui/**"
- "!tools/server/webui/README.md"
- "!tools/server/public/index.html.gz"
push:
branches:
- master
paths:
- ".github/workflows/webui-auto-build.yml"
- "tools/server/webui/**"
- "!tools/server/webui/README.md"
- "!tools/server/public/index.html.gz"
workflow_dispatch:
inputs:
pr_number:
description: "PR number to rebuild (leave empty for all open PRs)"
required: false
type: string
permissions:
contents: write
pull-requests: write
concurrency:
group: webui-auto-build-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
identify-prs:
name: Identify PRs to Rebuild
runs-on: ubuntu-latest
outputs:
pr_numbers: ${{ steps.get-prs.outputs.pr_numbers }}
steps:
- name: Get PR numbers
id: get-prs
uses: actions/github-script@v7
with:
script: |
let prNumbers = [];
// If triggered by a PR event, only rebuild that PR
if (context.eventName === 'pull_request') {
prNumbers = [context.payload.pull_request.number];
}
// If manually triggered with a specific PR number
else if (context.eventName === 'workflow_dispatch' && context.payload.inputs.pr_number) {
prNumbers = [parseInt(context.payload.inputs.pr_number)];
}
// If triggered by master push or manual without PR number, rebuild all open PRs
else {
const { data: pullRequests } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
per_page: 100
});
// Filter PRs that have webui changes
for (const pr of pullRequests) {
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
const hasWebuiChanges = files.some(file =>
file.filename.startsWith('tools/server/webui/') &&
!file.filename.endsWith('README.md') &&
file.filename !== 'tools/server/public/index.html.gz'
);
if (hasWebuiChanges) {
prNumbers.push(pr.number);
}
}
}
console.log(`PRs to rebuild: ${prNumbers.join(', ')}`);
core.setOutput('pr_numbers', JSON.stringify(prNumbers));
rebuild-webui:
name: Rebuild WebUI for PR #${{ matrix.pr_number }}
needs: identify-prs
if: needs.identify-prs.outputs.pr_numbers != '[]'
runs-on: ubuntu-latest
strategy:
matrix:
pr_number: ${{ fromJson(needs.identify-prs.outputs.pr_numbers) }}
fail-fast: false
max-parallel: 3
steps:
- name: Get PR details
id: pr-details
uses: actions/github-script@v7
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ matrix.pr_number }}
});
core.setOutput('head_ref', pr.head.ref);
core.setOutput('head_sha', pr.head.sha);
core.setOutput('head_repo', pr.head.repo.full_name);
core.setOutput('base_ref', pr.base.ref);
- name: Checkout PR branch
uses: actions/checkout@v4
with:
repository: ${{ steps.pr-details.outputs.head_repo }}
ref: ${{ steps.pr-details.outputs.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
cache-dependency-path: "tools/server/webui/package-lock.json"
- name: Install dependencies
run: npm ci
working-directory: tools/server/webui
- name: Build WebUI
run: npm run build
working-directory: tools/server/webui
- name: Check for changes
id: check-changes
run: |
# Decompress the newly built file and compute its hash
NEW_HASH=$(gunzip -c tools/server/public/index.html.gz | sha256sum | cut -d' ' -f1)
echo "New build hash: $NEW_HASH"
# Get the original file from git, decompress it, and compute its hash
if git show HEAD:tools/server/public/index.html.gz 2>/dev/null | gunzip -c | sha256sum > /tmp/old-hash.txt 2>&1; then
OLD_HASH=$(cut -d' ' -f1 /tmp/old-hash.txt)
echo "Original hash: $OLD_HASH"
# Compare hashes
if [ "$NEW_HASH" = "$OLD_HASH" ]; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "✓ No changes detected in static output (HTML content is identical)"
else
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "✓ Changes detected in static output"
fi
else
# File doesn't exist in repo yet (new file)
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "✓ New static output file detected"
fi
# Cleanup
rm -f /tmp/old-hash.txt
- name: Commit and push changes
if: steps.check-changes.outputs.has_changes == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add tools/server/public/index.html.gz
git commit -m "chore(webui): auto-rebuild static output [skip ci]"
git push origin ${{ steps.pr-details.outputs.head_ref }}
- name: Add comment to PR
if: steps.check-changes.outputs.has_changes == 'true'
uses: actions/github-script@v7
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ matrix.pr_number }}
});
// Check if we already commented about auto-rebuild
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🤖 WebUI static output auto-rebuilt')
);
const message = `🤖 **WebUI static output auto-rebuilt**
The static build has been automatically updated to reflect the latest changes.
<details>
<summary>Build details</summary>
- **Workflow run**: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
- **Commit**: ${{ steps.pr-details.outputs.head_sha }}
- **Triggered by**: ${context.eventName === 'pull_request' ? 'PR update' : 'master branch update'}
</details>`;
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: message
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ matrix.pr_number }},
body: message
});
}
- name: Report no changes
if: steps.check-changes.outputs.has_changes == 'false'
run: |
echo "✓ Static output is already up to date"