diff --git a/.github/workflows/sync-large-assets.yml b/.github/workflows/sync-large-assets.yml index 02c3921c8..1a3566c43 100644 --- a/.github/workflows/sync-large-assets.yml +++ b/.github/workflows/sync-large-assets.yml @@ -1,9 +1,15 @@ -name: Sync Large Assets +name: "Sync Large Assets" on: push: branches: - docs-v2 + - docs-v2-dev + paths: + - "snippets/assets/**" + - "v2/assets/**" + schedule: + - cron: "0 0 * * 0" workflow_dispatch: inputs: target_branch: @@ -11,9 +17,14 @@ on: required: false default: "docs-v2-assets" threshold_mb: - description: "File size threshold in MB" + description: "File size threshold in MB (default 1)" required: false - default: "20" + default: "1" + dry_run: + description: "Dry run — report what would be synced without pushing" + type: boolean + required: false + default: false permissions: contents: write @@ -22,48 +33,61 @@ jobs: sync-large-assets: runs-on: ubuntu-latest env: - DEFAULT_TARGET_BRANCH: docs-v2-assets - DEFAULT_THRESHOLD_MB: "20" + TARGET_BRANCH: "docs-v2-assets" + THRESHOLD_MB: "1" steps: - name: Checkout source branch uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Resolve inputs + id: config + run: | + if [ -n "${{ inputs.target_branch }}" ]; then + echo "target=${{ inputs.target_branch }}" >> "$GITHUB_OUTPUT" + else + echo "target=${{ env.TARGET_BRANCH }}" >> "$GITHUB_OUTPUT" + fi + if [ -n "${{ inputs.threshold_mb }}" ]; then + echo "threshold=${{ inputs.threshold_mb }}" >> "$GITHUB_OUTPUT" + else + echo "threshold=${{ env.THRESHOLD_MB }}" >> "$GITHUB_OUTPUT" + fi + echo "dry_run=${{ inputs.dry_run || 'false' }}" >> "$GITHUB_OUTPUT" + - name: Sync large assets to target branch shell: bash + env: + RESOLVED_TARGET: ${{ steps.config.outputs.target }} + RESOLVED_THRESHOLD: ${{ steps.config.outputs.threshold }} + DRY_RUN: ${{ steps.config.outputs.dry_run }} run: | set -euo pipefail SOURCE_SHA="${GITHUB_SHA}" SOURCE_REF="${GITHUB_REF_NAME}" - - TARGET_BRANCH="${{ github.event.inputs.target_branch || '' }}" - if [ -z "$TARGET_BRANCH" ]; then - TARGET_BRANCH="$DEFAULT_TARGET_BRANCH" - fi - - THRESHOLD_MB="${{ github.event.inputs.threshold_mb || '' }}" - if [ -z "$THRESHOLD_MB" ]; then - THRESHOLD_MB="$DEFAULT_THRESHOLD_MB" - fi + TARGET_BRANCH="${RESOLVED_TARGET}" + THRESHOLD_MB="${RESOLVED_THRESHOLD}" if ! [[ "$THRESHOLD_MB" =~ ^[0-9]+$ ]]; then - echo "threshold_mb must be an integer" + echo "::error::threshold_mb must be an integer, got: $THRESHOLD_MB" exit 1 fi THRESHOLD_BYTES=$((THRESHOLD_MB * 1024 * 1024)) + echo "::group::Configuration" echo "Source branch: $SOURCE_REF" - echo "Source SHA: $SOURCE_SHA" + echo "Source SHA: $SOURCE_SHA" echo "Target branch: $TARGET_BRANCH" - echo "Threshold: ${THRESHOLD_MB}MB (${THRESHOLD_BYTES} bytes)" + echo "Threshold: ${THRESHOLD_MB} MB (${THRESHOLD_BYTES} bytes)" + echo "::endgroup::" git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git fetch origin "$TARGET_BRANCH" || true + git fetch origin "$TARGET_BRANCH" 2>/dev/null || true WORKTREE_DIR="../_assets-branch" rm -rf "$WORKTREE_DIR" @@ -71,73 +95,83 @@ jobs: if git show-ref --verify --quiet "refs/remotes/origin/$TARGET_BRANCH"; then git worktree add -B "$TARGET_BRANCH" "$WORKTREE_DIR" "origin/$TARGET_BRANCH" else + echo "Target branch $TARGET_BRANCH does not exist — creating it." git worktree add -b "$TARGET_BRANCH" "$WORKTREE_DIR" - ( - cd "$WORKTREE_DIR" - : > .nojekyll - mkdir -p .github - cat > .github/README.md <<'EOF' -This branch is auto-managed by .github/workflows/sync-large-assets.yml. -It stores large asset files mirrored from docs-v2 for static hosting. -EOF - git add .nojekyll .github/README.md - git commit -m "Initialize large-assets branch" - git push -u origin "$TARGET_BRANCH" - ) + pushd "$WORKTREE_DIR" > /dev/null + printf '' > .nojekyll + mkdir -p .github + echo "Auto-managed by sync-large-assets.yml. Stores large asset files for static hosting." > .github/README.md + git add .nojekyll .github/README.md + git commit -m "chore: initialise large-assets branch" + git push -u origin "$TARGET_BRANCH" + popd > /dev/null fi - LARGE_LIST_FILE="$(mktemp)" + # Build list of files exceeding threshold + LARGE_LIST="$(mktemp)" + file_count=0 while IFS= read -r file; do [ -z "$file" ] && continue size=$(wc -c < "$file") if [ "$size" -gt "$THRESHOLD_BYTES" ]; then - echo "$file" >> "$LARGE_LIST_FILE" + echo "$file" >> "$LARGE_LIST" + file_count=$((file_count + 1)) fi done < <(git ls-files 'snippets/assets/**' 'v2/assets/**') - sort -u "$LARGE_LIST_FILE" -o "$LARGE_LIST_FILE" + sort -u "$LARGE_LIST" -o "$LARGE_LIST" - echo "Large assets selected:" - if [ -s "$LARGE_LIST_FILE" ]; then - cat "$LARGE_LIST_FILE" + echo "::group::Large assets selected ($file_count files)" + if [ -s "$LARGE_LIST" ]; then + cat "$LARGE_LIST" else - echo "(none)" + echo "(none — no files exceed ${THRESHOLD_MB} MB)" fi + echo "::endgroup::" - ( - cd "$WORKTREE_DIR" + # Sync to target branch + pushd "$WORKTREE_DIR" > /dev/null - # Remove previously tracked mirrored assets not present in latest selection. - while IFS= read -r tracked; do - [ -z "$tracked" ] && continue - if ! grep -Fxq "$tracked" "$LARGE_LIST_FILE"; then - rm -f "$tracked" - fi - done < <(git ls-files 'snippets/assets/**' 'v2/assets/**') + # Remove previously tracked assets no longer in the selection + while IFS= read -r tracked; do + [ -z "$tracked" ] && continue + if ! grep -Fxq "$tracked" "$LARGE_LIST"; then + rm -f "$tracked" + fi + done < <(git ls-files 'snippets/assets/**' 'v2/assets/**') + + # Copy selected large assets from source checkout + while IFS= read -r file; do + [ -z "$file" ] && continue + mkdir -p "$(dirname "$file")" + cp -f "${GITHUB_WORKSPACE}/$file" "$file" + done < "$LARGE_LIST" + + # Write manifest + mkdir -p .github + printf 'source_branch=%s\nsource_sha=%s\nthreshold_mb=%s\nfile_count=%s\ngenerated_at=%s\n' \ + "$SOURCE_REF" "$SOURCE_SHA" "$THRESHOLD_MB" "$file_count" \ + "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \ + > .github/assets-manifest.txt + + git add -A snippets/assets v2/assets .nojekyll .github/assets-manifest.txt .github/README.md + + if git diff --cached --quiet; then + echo "No large-asset changes to commit." + exit 0 + fi - # Copy current large assets from source checkout. - while IFS= read -r file; do - [ -z "$file" ] && continue - mkdir -p "$(dirname "$file")" - cp -f "${GITHUB_WORKSPACE}/$file" "$file" - done < "$LARGE_LIST_FILE" + if [ "$DRY_RUN" = "true" ]; then + echo "::notice::DRY RUN — would sync $file_count assets to $TARGET_BRANCH" + echo "::group::Files that would be committed" + git diff --cached --stat + echo "::endgroup::" + exit 0 + fi - mkdir -p .github - cat > .github/assets-manifest.txt < /dev/null