action.yml 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. name: 'Restore Cache'
  2. description: ""
  3. inputs:
  4. cache_path:
  5. description: 'Path where cache should be restored'
  6. required: true
  7. type: string
  8. cache_key:
  9. description: 'Primary key to restore cache'
  10. required: true
  11. type: string
  12. restore_keys:
  13. description: 'Multiline list of keys (fallback prefixes)'
  14. required: false
  15. type: string
  16. default: ""
  17. cache_bucket:
  18. description: 'The tag name for the release (e.g., general-cache)'
  19. required: true
  20. default: 'general-cache'
  21. runs:
  22. using: 'composite'
  23. steps:
  24. - name: Detect and Download Cache
  25. shell: bash
  26. env:
  27. TARGET_REPO: "${{ github.repository }}"
  28. run: |
  29. # Detect and Download Cache
  30. if [ "${{ inputs.debug }}" = "true" ]; then set -x; fi
  31. cd "$GITHUB_WORKSPACE"
  32. TAG_NAME="${{ inputs.cache_bucket }}"
  33. BASE_URL="https://github.com/${TARGET_REPO}/releases/download/$TAG_NAME"
  34. ASSETS_URL="https://github.com/${TARGET_REPO}/releases/expanded_assets/$TAG_NAME"
  35. ARIA2_OPTS=(
  36. "-x16" "-s16" "-k1M" "-j5" "--file-allocation=none"
  37. "--header=User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
  38. "--header=Accept: */*"
  39. "--header=Connection: keep-alive"
  40. )
  41. if [ "${{ inputs.debug }}" != "true" ]; then
  42. ARIA2_OPTS+=("--quiet" "--summary-interval=0" "--console-log-level=error")
  43. fi
  44. echo "::group:: Fetching Asset List"
  45. HTTP_RESPONSE=$(curl -sL -A "Mozilla/5.0" -w "%{http_code}" "$ASSETS_URL" -o assets.html || echo "404")
  46. if [ "$HTTP_RESPONSE" -eq 200 ]; then
  47. ALL_ASSETS=$(grep -oP "download/$TAG_NAME/\K[^\"' ]+" assets.html | sort -u || echo "")
  48. else
  49. echo "Status $HTTP_RESPONSE: Failed to fetch assets from scraper endpoint."
  50. ALL_ASSETS=""
  51. fi
  52. rm -f assets.html
  53. if [ -z "$ALL_ASSETS" ]; then
  54. echo "No assets found in bucket '$TAG_NAME'. Skipping search."
  55. echo "::endgroup::"
  56. else
  57. echo "Successfully fetched asset list. Has $(echo "$ALL_ASSETS" | wc -l) assets."
  58. echo "::endgroup::"
  59. SEARCH_LIST=$(printf "%s\n%s" "${{ inputs.cache_key }}" "${{ inputs.restore_keys }}" | sed '/^$/d')
  60. FOUND=false
  61. while read -r KEY; do
  62. [ -z "$KEY" ] && continue
  63. echo "::group:: Searching Prefix: $KEY"
  64. MATCH=$(echo "$ALL_ASSETS" | grep "^cache-$KEY" | sort -r | head -n 1 || true)
  65. if [ -z "$MATCH" ]; then
  66. echo "Not found."
  67. echo "::endgroup::"
  68. continue
  69. fi
  70. BASE_FILENAME=$(echo "$MATCH" | sed -E 's/\.(tzst|tar)(\.part[a-z]{2})?$//')
  71. EXT=$(echo "$MATCH" | grep -oP '\.(tzst|tar)' | head -n 1)
  72. [[ "$MATCH" == *".part"* ]] && IS_SPLIT=true || IS_SPLIT=false
  73. [ "$EXT" = ".tzst" ] && COMPRESSED=true || COMPRESSED=false
  74. FOUND=true
  75. echo "✅ Hit! Restoring $BASE_FILENAME$EXT"
  76. echo "::endgroup::"
  77. echo "::group:: Downloading Cache"
  78. download_asset() {
  79. local filename="$1"
  80. local url="$2"
  81. local max_retries=3
  82. local attempt=1
  83. while [ $attempt -le $max_retries ]; do
  84. echo " Attempt $attempt: Downloading $filename..."
  85. if timeout 10m aria2c "${ARIA2_OPTS[@]}" --retry-wait=10 --max-tries=10 -o "$filename" "$url"; then
  86. return 0
  87. fi
  88. echo " ⚠️ Download failed or timed out. Retrying in 5s..."
  89. sleep 5
  90. attempt=$((attempt + 1))
  91. done
  92. return 1
  93. }
  94. if [ "$IS_SPLIT" = "true" ]; then
  95. for part in {a..z}{a..z}; do
  96. PART_NAME="$BASE_FILENAME$EXT.part$part"
  97. if echo "$ALL_ASSETS" | grep -q "^$PART_NAME$"; then
  98. if ! download_asset "$PART_NAME" "$BASE_URL/$PART_NAME"; then
  99. echo "::error::Failed to download $PART_NAME after multiple retries."
  100. exit 1
  101. fi
  102. else break; fi
  103. done
  104. else
  105. if ! download_asset "$BASE_FILENAME$EXT" "$BASE_URL/$BASE_FILENAME$EXT"; then
  106. echo "::error::Failed to download $BASE_FILENAME$EXT after multiple retries."
  107. exit 1
  108. fi
  109. fi
  110. echo "::endgroup::"
  111. echo "::group:: Extracting Cache"
  112. mkdir -p "${{ inputs.cache_path }}"
  113. FINAL_ARCHIVE="$BASE_FILENAME$EXT"
  114. EXTRACT_DIR="$(dirname "${{ inputs.cache_path }}")"
  115. extract_cache() {
  116. local cmd="$1"
  117. if [ "${{ inputs.debug }}" = "true" ]; then
  118. sh -c "$cmd"
  119. else
  120. sh -c "$cmd" > /dev/null 2>&1
  121. fi
  122. }
  123. if [ "$IS_SPLIT" = "true" ]; then
  124. PARTS=$(ls "$FINAL_ARCHIVE.part"* | sort)
  125. if [ "$COMPRESSED" = "true" ]; then
  126. extract_cache "cat $PARTS | tar -I 'zstd -d -T0' -xvf - -C '$EXTRACT_DIR'"
  127. else
  128. extract_cache "cat $PARTS | tar -xvf - -C '$EXTRACT_DIR'"
  129. fi
  130. rm -f $PARTS
  131. else
  132. if [ "$COMPRESSED" = "true" ]; then
  133. extract_cache "tar -I 'zstd -d -T0' -xvf '$FINAL_ARCHIVE' -C '$EXTRACT_DIR'"
  134. else
  135. extract_cache "tar -xvf '$FINAL_ARCHIVE' -C '$EXTRACT_DIR'"
  136. fi
  137. rm -f "$FINAL_ARCHIVE"
  138. fi
  139. echo "✅ Restore complete."
  140. echo "::endgroup::"
  141. break
  142. done <<< "$SEARCH_LIST"
  143. if [ "$FOUND" = "false" ]; then
  144. echo "⚠️ No cache matches found. Proceeding with fresh run."
  145. fi
  146. fi