Skip to content

chore: bump strings.json version #142

chore: bump strings.json version

chore: bump strings.json version #142

Workflow file for this run

name: Build Skins
on:
push:
branches: [main, master]
paths:
- 'skins-pro/**'
- 'screenshots/**'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: skins-build
cancel-in-progress: false
jobs:
build-skins:
name: Build and publish skins
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 2
token: ${{ secrets.GITHUB_TOKEN }}
- name: Detect changed skins
id: skins
run: |
HAS_PARENT=$(git rev-parse --verify HEAD~1 2>/dev/null && echo 1 || echo 0)
# Changes from diff (for new pushes)
SKIN_TOUCHED=""
SCREENSHOT_TOUCHED=""
if [ "$HAS_PARENT" = 1 ]; then
SKIN_TOUCHED=$(git diff --name-only HEAD~1 HEAD -- skins-pro/ 2>/dev/null \
| grep '^skins-pro/' | cut -d/ -f2 | sort -u \
| grep -v '^\.gitkeep$' || true)
SCREENSHOT_TOUCHED=$(git diff --name-only HEAD~1 HEAD -- screenshots/ 2>/dev/null \
| grep '^screenshots/' | cut -d/ -f2 | sed 's/\.[^.]*$//' | sort -u \
| grep -v '^thumbnails$' | grep -v '^registry$' | grep -v '^\.gitkeep$' || true)
fi
# Scan for residual assets on master (cleanup leftover from failed prior runs)
SKIN_PRESENT=$(find skins-pro/ -maxdepth 1 -mindepth 1 -type d 2>/dev/null | cut -d/ -f2 | sort -u || true)
SCREENSHOT_PRESENT=$(find screenshots/ -maxdepth 1 -type f ! -name '.gitkeep' 2>/dev/null \
| xargs -n1 basename 2>/dev/null | sed 's/\.[^.]*$//' | sort -u \
| grep -v '^thumbnails$' | grep -v '^registry$' || true)
CHANGED=""
DELETED=""
for skin in $(printf '%s\n%s\n%s\n%s\n' "$SKIN_TOUCHED" "$SCREENSHOT_TOUCHED" "$SKIN_PRESENT" "$SCREENSHOT_PRESENT" | grep -v '^$' | sort -u); do
if [ -d "skins-pro/$skin" ]; then
CHANGED="$CHANGED $skin"
else
DELETED="$DELETED $skin"
fi
done
CHANGED=$(echo "$CHANGED" | xargs || true)
DELETED=$(echo "$DELETED" | xargs || true)
echo "target=$CHANGED" >> "$GITHUB_OUTPUT"
echo "deleted=$DELETED" >> "$GITHUB_OUTPUT"
echo "Changed skins: ${CHANGED:-<none>}"
echo "Deleted themes: ${DELETED:-<none>}"
- name: Prepare asset worktrees
run: |
for branch in skin-assets screenshot-assets; do
if git fetch origin "$branch" --depth=1 2>/dev/null; then
git worktree add "$branch" "origin/$branch"
else
git worktree add --detach "$branch"
git -C "$branch" checkout --orphan "$branch"
git -C "$branch" rm -rf . 2>/dev/null || true
fi
done
- name: Move source files into full asset worktrees
run: |
TARGET="${{ steps.skins.outputs.target }}"
if [ -z "$TARGET" ]; then
exit 0
fi
for skin in $TARGET; do
if [ -d "skins-pro/$skin" ]; then
mkdir -p "skin-assets/$skin"
cp -r "skins-pro/$skin/." "skin-assets/$skin/"
rm -rf "skins-pro/$skin"
fi
for ext in png jpg jpeg webp bmp gif mp4; do
if [ -f "screenshots/$skin.$ext" ]; then
cp "screenshots/$skin.$ext" "screenshot-assets/$skin.$ext"
rm "screenshots/$skin.$ext"
fi
done
done
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci
- name: Build skins
run: |
TARGET="${{ steps.skins.outputs.target }}"
if [ -n "$TARGET" ]; then
echo "Incremental build for: $TARGET"
npm run build -- $TARGET
else
echo "Full build"
npm run build
fi
- name: Sync to Cloudflare R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
run: |
ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"
TARGET="${{ steps.skins.outputs.target }}"
DELETED="${{ steps.skins.outputs.deleted }}"
if [ -z "$TARGET" ] && [ -z "$DELETED" ]; then
echo "Full sync"
aws s3 sync store/ "s3://skinspro/store/" --endpoint-url "$ENDPOINT"
aws s3 sync screenshot-assets/ "s3://skinspro/screenshots/" --endpoint-url "$ENDPOINT" --exclude "thumbnails/*"
aws s3 sync screenshot-assets/thumbnails/ "s3://skinspro/screenshots/thumbnails/" --endpoint-url "$ENDPOINT"
aws s3 cp screenshot-assets/registry.json "s3://skinspro/screenshots/registry.json" --endpoint-url "$ENDPOINT"
else
echo "Incremental sync for: target=$TARGET deleted=$DELETED"
for skin in $TARGET; do
[ -f "store/${skin}.zip" ] && aws s3 cp "store/${skin}.zip" "s3://skinspro/store/${skin}.zip" --endpoint-url "$ENDPOINT"
[ -f "screenshot-assets/thumbnails/${skin}.jpg" ] && aws s3 cp "screenshot-assets/thumbnails/${skin}.jpg" "s3://skinspro/screenshots/thumbnails/${skin}.jpg" --endpoint-url "$ENDPOINT"
for ext in png jpg jpeg webp bmp gif mp4; do
[ -f "screenshot-assets/${skin}.${ext}" ] && aws s3 cp "screenshot-assets/${skin}.${ext}" "s3://skinspro/screenshots/${skin}.${ext}" --endpoint-url "$ENDPOINT"
done
done
[ -f "screenshot-assets/registry.json" ] && aws s3 cp "screenshot-assets/registry.json" "s3://skinspro/screenshots/registry.json" --endpoint-url "$ENDPOINT"
fi
- name: Push new skin sources to skin-assets branch
run: |
TARGET="${{ steps.skins.outputs.target }}"
if [ -z "$TARGET" ]; then
echo "No new skins to publish"
exit 0
fi
cd skin-assets
for skin in $TARGET; do
if [ -d "${{ github.workspace }}/skins-pro/$skin" ]; then
rm -rf "$skin"
cp -r "${{ github.workspace }}/skins-pro/$skin" "$skin"
echo "Copied skin source: $skin"
fi
done
git add .
if git diff --cached --quiet; then
echo "No changes to skin-assets"
else
git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" \
commit -m "Add skin sources: $TARGET [skip ci]"
git push origin HEAD:skin-assets
fi
- name: Push new screenshots to screenshot-assets branch
run: |
TARGET="${{ steps.skins.outputs.target }}"
if [ -z "$TARGET" ]; then
echo "No new screenshots to publish"
exit 0
fi
cd screenshot-assets
# Copy new screenshots from master workspace (build already wrote
# thumbnails/registry.json directly here since this is the worktree)
for skin in $TARGET; do
for ext in png jpg jpeg webp bmp gif mp4; do
if [ -f "${{ github.workspace }}/screenshots/$skin.$ext" ]; then
cp "${{ github.workspace }}/screenshots/$skin.$ext" "$skin.$ext"
echo "Copied screenshot: $skin.$ext"
fi
done
done
git add .
if git diff --cached --quiet; then
echo "No changes to screenshot-assets"
else
git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" \
commit -m "Add screenshots: $TARGET [skip ci]"
git push origin HEAD:screenshot-assets
fi
- name: Clean moved assets from master
run: |
TARGET="${{ steps.skins.outputs.target }}"
if [ -z "$TARGET" ]; then
echo "No cleanup needed"
exit 0
fi
cd "${{ github.workspace }}"
for skin in $TARGET; do
if git rm -r --ignore-unmatch "skins-pro/$skin" >/dev/null 2>&1; then
echo "Removed skins-pro/$skin from master"
fi
for ext in png jpg jpeg webp bmp gif mp4; do
if git rm --ignore-unmatch "screenshots/$skin.$ext" >/dev/null 2>&1; then
echo "Removed screenshots/$skin.$ext from master"
fi
done
done
mkdir -p skins-pro screenshots
[ -f "skins-pro/.gitkeep" ] || touch skins-pro/.gitkeep
[ -f "screenshots/.gitkeep" ] || touch screenshots/.gitkeep
git add skins-pro/.gitkeep screenshots/.gitkeep 2>/dev/null || true
if git diff --cached --quiet; then
echo "Nothing to clean"
else
git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" \
commit -m "chore: move $TARGET assets to asset branches [skip ci]"
git push origin HEAD:master
fi
- name: Clean up worktrees
if: always()
run: |
git worktree remove --force skin-assets 2>/dev/null || true
git worktree remove --force screenshot-assets 2>/dev/null || true