Skip to content

JP assets sync

JP assets sync #23

Workflow file for this run

name: JP assets sync
# 统一 workflow:手动触发,自动判断冷启动/增量
# - 首次运行(无 cache):冷启动,全量下载
# - 后续运行(有 cache):增量,只下载 diff
# - 可强制冷启动:workflow_dispatch.cold_start = true
on:
workflow_dispatch:
inputs:
cold_start:
description: 'Force cold start (full re-download)'
required: false
default: false
type: boolean
permissions:
contents: write
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 480
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install azlassets
run: |
python -m pip install --upgrade pip
pip install azlassets
azl --help
# Restore cache: state + last snapshots
- name: Restore cache
id: cache
uses: actions/cache@v5
with:
path: |
jp-client-state.tar
last_loadingbg
last_gallerypic
key: jp-assets-v2-${{ runner.os }}-${{ github.run_id }}
restore-keys: |
jp-assets-v2-${{ runner.os }}-
# Determine mode: cold start if cache miss or forced
# Note: cache-hit is only "true" for exact key match. restore-keys fallback = "false".
# So we check if jp-client-state.tar actually exists (restored via restore-keys).
- name: Determine run mode
id: mode
run: |
HAS_CACHE=false
if [ -f "jp-client-state.tar" ] && [ -s "jp-client-state.tar" ]; then
HAS_CACHE=true
fi
if [ "$HAS_CACHE" != "true" ] || [ "${{ inputs.cold_start }}" == "true" ]; then
echo "mode=cold" >> $GITHUB_OUTPUT
echo "Mode: COLD START (full download)"
else
echo "mode=incremental" >> $GITHUB_OUTPUT
echo "Mode: INCREMENTAL (diff sync)"
tar -xf jp-client-state.tar
fi
# Download JP assets
- name: Download JP assets
run: |
python - <<'PY'
import sys
import azl
import azlassets.classes as cls
import azlassets.updater as updater
# Patch: VersionType __hash__
VT = getattr(cls, "VersionType", None)
if VT and getattr(VT, "__hash__", None) is None:
VT.__hash__ = lambda self: hash(str(self))
print("[patch] Patched VersionType.__hash__")
# Patch: remove_asset / delete_asset_safe for directories
import pathlib, shutil
for attr in ('remove_asset', 'delete_asset_safe'):
if hasattr(updater, attr):
orig = getattr(updater, attr)
def patched(f, orig):
def wrapper(assetpath):
p = pathlib.Path(assetpath.full) if hasattr(assetpath, 'full') else pathlib.Path(assetpath)
if p.is_dir():
shutil.rmtree(p)
print(f"[patch] Removed dir: {p}")
else:
f(assetpath)
return wrapper
setattr(updater, attr, patched(orig, orig))
print(f"[patch] Patched updater.{attr} for directory deletion")
break
# Download
if "${{ steps.mode.outputs.mode }}" == "cold":
sys.argv = ["azl", "download", "JP", "--force-refresh"]
else:
sys.argv = ["azl", "download", "JP"]
azl.main()
print("[done] Download complete.")
# Extract
sys.argv = ["azl", "extract", "JP"]
azl.main()
print("[done] Extract complete.")
PY
# Collect current files
- name: Collect loadingbg
run: python scripts/collect_loadingbg.py
- name: Collect gallerypic
run: python scripts/collect_gallerypic.py
# Show collected
- name: Show collected files
run: |
echo "=== loadingbg ==="
if [ -d "current_loadingbg" ] && [ -n "$(ls -A current_loadingbg 2>/dev/null)" ]; then
echo "$(ls current_loadingbg/ | wc -l) files, $(du -sh current_loadingbg/ | cut -f1)"
else
echo "(empty)"
fi
echo "=== gallerypic ==="
if [ -d "current_gallerypic" ] && [ -n "$(ls -A current_gallerypic 2>/dev/null)" ]; then
echo "$(ls current_gallerypic/ | wc -l) files, $(du -sh current_gallerypic/ | cut -f1)"
else
echo "(empty)"
fi
# Pack: cold start → only full zips
- name: Pack full zips (cold start)
if: steps.mode.outputs.mode == 'cold'
run: |
if [ -d "current_loadingbg" ] && [ -n "$(ls -A current_loadingbg 2>/dev/null)" ]; then
zip -r loadingbg_full.zip current_loadingbg
fi
if [ -d "current_gallerypic" ] && [ -n "$(ls -A current_gallerypic 2>/dev/null)" ]; then
zip -r gallerypic_full.zip current_gallerypic
fi
# Diff: incremental → diff + full zips
- name: Diff and pack (incremental)
if: steps.mode.outputs.mode == 'incremental'
run: |
bash scripts/diff_and_zip.sh
bash scripts/diff_and_zip_gallerypic.sh
- name: Read diff status
if: steps.mode.outputs.mode == 'incremental'
id: diffcheck
run: |
echo "has_diff=$(cat has_diff.flag 2>/dev/null || echo false)" >> $GITHUB_OUTPUT
echo "has_diff_gallerypic=$(cat has_diff_gallerypic.flag 2>/dev/null || echo false)" >> $GITHUB_OUTPUT
# Update cache: merge current into last to keep full snapshot
- name: Update cache
run: |
# ⚠️ 关键:current_* 是 azl 增量提取的(仅 diff),
# 必须**合并**到 last_* 才能保持 last 是「远端当前全量」。
# 漏写 merge 会导致 last_* 被替换成 current_* 的少量文件,丢失历史。
if [ -d "current_loadingbg" ] && [ -n "$(ls -A current_loadingbg 2>/dev/null)" ]; then
mkdir -p last_loadingbg
# 用 cp -r 覆盖同名,保留 last 中独有文件
# (不能用 cp -n no-clobber,否则 current 中的新版无法覆盖 last 中的旧版)
cp -r current_loadingbg/. last_loadingbg/
echo "[cache] last_loadingbg merged: $(ls last_loadingbg | wc -l) files"
else
echo "[cache] current_loadingbg empty, keeping last_loadingbg ($(ls last_loadingbg 2>/dev/null | wc -l) files)"
fi
if [ -d "current_gallerypic" ] && [ -n "$(ls -A current_gallerypic 2>/dev/null)" ]; then
mkdir -p last_gallerypic
cp -r current_gallerypic/. last_gallerypic/
echo "[cache] last_gallerypic merged: $(ls last_gallerypic | wc -l) files"
else
echo "[cache] current_gallerypic empty, keeping last_gallerypic ($(ls last_gallerypic 2>/dev/null | wc -l) files)"
fi
# Pack state
rm -rf state_tmp && mkdir -p state_tmp/ClientAssets
if [ -d "ClientAssets/JP" ]; then
cp -r ClientAssets/JP state_tmp/ClientAssets/
rm -rf state_tmp/ClientAssets/JP/AssetBundles
fi
tar -cf jp-client-state.tar -C state_tmp ClientAssets
echo "Cache updated."
# Generate meta
- name: Generate meta info
run: |
echo "client=JP" > meta.txt
echo "mode=${{ steps.mode.outputs.mode }}" >> meta.txt
echo "generated_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> meta.txt
if [ "${{ steps.mode.outputs.mode }}" == "incremental" ]; then
echo "has_diff=${{ steps.diffcheck.outputs.has_diff }}" >> meta.txt
echo "has_diff_gallerypic=${{ steps.diffcheck.outputs.has_diff_gallerypic }}" >> meta.txt
fi
# Publish Release
- name: Publish to Release
uses: softprops/action-gh-release@v2
with:
tag_name: jp-loadingbg-latest
name: JP assets (${{ steps.mode.outputs.mode }})
body: |
JP assets sync (${{ steps.mode.outputs.mode }}).
- jp-client-state.tar: azlassets logical state
- loadingbg_full.zip / gallerypic_full.zip: full snapshots
- loadingbg_diff.zip / gallerypic_diff.zip: incremental diffs (if any)
files: |
jp-client-state.tar
loadingbg_full.zip
gallerypic_full.zip
meta.txt
# Upload diff zips conditionally
- name: Upload loadingbg diff
if: steps.mode.outputs.mode == 'incremental' && steps.diffcheck.outputs.has_diff == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: jp-loadingbg-latest
files: loadingbg_diff.zip
- name: Upload gallerypic diff
if: steps.mode.outputs.mode == 'incremental' && steps.diffcheck.outputs.has_diff_gallerypic == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: jp-loadingbg-latest
files: gallerypic_diff.zip