fix: group +/- temp buttons into one raised pill #32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Detect changed skins | |
| id: skins | |
| run: | | |
| # Detect added/modified skins (exclude deletions) | |
| SKIN_CHANGED=$(git diff --diff-filter=d --name-only HEAD~1 HEAD -- skins-pro/ 2>/dev/null \ | |
| | grep '^skins-pro/' | cut -d/ -f2 | sort -u | grep -v '^modern$' || true) | |
| SCREENSHOT_CHANGED=$(git diff --diff-filter=d --name-only HEAD~1 HEAD -- screenshots/ 2>/dev/null \ | |
| | grep '^screenshots/' | cut -d/ -f2 | sed 's/\.[^.]*$//' | sort -u \ | |
| | grep -v '^thumbnails$' | grep -v '^registry$' || true) | |
| CHANGED=$(printf '%s\n%s\n' "$SKIN_CHANGED" "$SCREENSHOT_CHANGED" | grep -v '^$' | sort -u | tr '\n' ' ' | sed 's/ $//' || true) | |
| if [ -z "$CHANGED" ]; then | |
| echo "target=" >> "$GITHUB_OUTPUT" | |
| echo "No specific skins changed" | |
| else | |
| echo "target=$CHANGED" >> "$GITHUB_OUTPUT" | |
| echo "Changed skins: $CHANGED" | |
| fi | |
| # Detect deleted skins | |
| SKIN_DELETED=$(git diff --diff-filter=D --name-only HEAD~1 HEAD -- skins-pro/ 2>/dev/null \ | |
| | grep '^skins-pro/' | cut -d/ -f2 | sort -u | grep -v '^modern$' || true) | |
| SCREENSHOT_DELETED=$(git diff --diff-filter=D --name-only HEAD~1 HEAD -- screenshots/ 2>/dev/null \ | |
| | grep '^screenshots/' | cut -d/ -f2 | sed 's/\.[^.]*$//' | sort -u \ | |
| | grep -v '^thumbnails$' | grep -v '^registry$' || true) | |
| DELETED=$(printf '%s\n%s\n' "$SKIN_DELETED" "$SCREENSHOT_DELETED" | grep -v '^$' | sort -u | tr '\n' ' ' | sed 's/ $//' || true) | |
| echo "deleted=$DELETED" >> "$GITHUB_OUTPUT" | |
| if [ -n "$DELETED" ]; then echo "Deleted skins: $DELETED"; fi | |
| - name: Fetch existing store assets | |
| run: | | |
| git fetch origin store --depth=1 2>/dev/null || true | |
| mkdir -p store screenshots/thumbnails | |
| for p in $(git ls-tree -r --name-only origin/store -- store/ 2>/dev/null | grep '\.zip$' || true); do | |
| git show "origin/store:$p" > "$p" 2>/dev/null && echo "Restored: $p" | |
| done | |
| for p in $(git ls-tree -r --name-only origin/store -- screenshots/thumbnails/ 2>/dev/null | grep '\.jpg$' || true); do | |
| git show "origin/store:$p" > "$p" 2>/dev/null && echo "Restored: $p" | |
| done | |
| - name: Remove deleted skin assets | |
| run: | | |
| DELETED="${{ steps.skins.outputs.deleted }}" | |
| if [ -z "$DELETED" ]; then | |
| echo "No skins to delete" | |
| exit 0 | |
| fi | |
| for skin in $DELETED; do | |
| rm -f "store/${skin}.zip" "screenshots/thumbnails/${skin}.jpg" | |
| echo "Removed store assets for deleted skin: $skin" | |
| done | |
| - name: Build skins | |
| run: | | |
| if [ -n "${{ steps.skins.outputs.target }}" ]; then | |
| npm run build -- ${{ steps.skins.outputs.target }} | |
| else | |
| 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 (no specific changes detected)" | |
| aws s3 sync store/ "s3://skinspro/store/" --endpoint-url "$ENDPOINT" --delete | |
| aws s3 sync screenshots/thumbnails/ "s3://skinspro/screenshots/thumbnails/" --endpoint-url "$ENDPOINT" --delete | |
| for f in screenshots/*.*; do | |
| [ -f "$f" ] && aws s3 cp "$f" "s3://skinspro/screenshots/$(basename "$f")" --endpoint-url "$ENDPOINT" | |
| done | |
| else | |
| for skin in $TARGET; do | |
| [ -f "store/${skin}.zip" ] && aws s3 cp "store/${skin}.zip" "s3://skinspro/store/${skin}.zip" --endpoint-url "$ENDPOINT" | |
| [ -f "screenshots/thumbnails/${skin}.jpg" ] && aws s3 cp "screenshots/thumbnails/${skin}.jpg" "s3://skinspro/screenshots/thumbnails/${skin}.jpg" --endpoint-url "$ENDPOINT" | |
| for f in screenshots/${skin}.*; do | |
| [ -f "$f" ] && aws s3 cp "$f" "s3://skinspro/screenshots/$(basename "$f")" --endpoint-url "$ENDPOINT" | |
| done | |
| done | |
| for skin in $DELETED; do | |
| aws s3 rm "s3://skinspro/store/${skin}.zip" --endpoint-url "$ENDPOINT" 2>/dev/null || true | |
| aws s3 rm "s3://skinspro/screenshots/thumbnails/${skin}.jpg" --endpoint-url "$ENDPOINT" 2>/dev/null || true | |
| for ext in png jpg jpeg webp bmp gif; do | |
| aws s3 rm "s3://skinspro/screenshots/${skin}.${ext}" --endpoint-url "$ENDPOINT" 2>/dev/null || true | |
| done | |
| done | |
| fi | |
| aws s3 cp screenshots/registry.json "s3://skinspro/screenshots/registry.json" --endpoint-url "$ENDPOINT" | |
| - name: Push store assets to store branch | |
| run: | | |
| STORE_DIR="$(mktemp -d)" | |
| mv store/*.zip "$STORE_DIR/" 2>/dev/null || true | |
| mv screenshots/thumbnails "$STORE_DIR/thumbnails" 2>/dev/null || true | |
| mv screenshots/registry.json "$STORE_DIR/registry.json" 2>/dev/null || true | |
| git checkout --orphan _store_push | |
| find . -maxdepth 1 -not -name '.git' -not -name '.' -exec rm -rf {} + | |
| mkdir -p store screenshots/thumbnails | |
| mv "$STORE_DIR"/*.zip store/ 2>/dev/null || true | |
| mv "$STORE_DIR"/thumbnails/* screenshots/thumbnails/ 2>/dev/null || true | |
| mv "$STORE_DIR"/registry.json screenshots/registry.json 2>/dev/null || true | |
| printf '%s\n' '# Skins Pro — Store Assets' '' 'This branch contains build artifacts for the skin store.' 'Pushed automatically by CI. Do not edit manually.' > README.md | |
| git add . | |
| git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" \ | |
| commit -m "Update store artifacts [skip ci]" --allow-empty | |
| git push origin _store_push:store --force | |
| git checkout "${{ github.ref_name }}" | |
| - name: Purge jsdelivr cache | |
| run: | | |
| BASE="https://purge.jsdelivr.net/gh/ha-china/Skins-Pro@store" | |
| TARGET="${{ steps.skins.outputs.target }}" | |
| DELETED="${{ steps.skins.outputs.deleted }}" | |
| purge() { echo "Purging: $1"; curl -s "$1" > /dev/null; sleep 0.5; } | |
| purge "$BASE/screenshots/registry.json" | |
| for skin in $TARGET $DELETED; do | |
| purge "$BASE/store/${skin}.zip" | |
| purge "$BASE/screenshots/thumbnails/${skin}.jpg" | |
| done |