action.yml 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. name: 'Save Cache'
  2. description: 'Archives and uploads cache to GitHub Releases with intelligent splitting and retry logic'
  3. inputs:
  4. cache_path:
  5. description: 'Path where cache is saved'
  6. required: true
  7. type: string
  8. cache_key:
  9. description: 'Unique key for the cache'
  10. required: true
  11. type: string
  12. cache_bucket:
  13. description: 'The tag name for the release (e.g., general-cache)'
  14. required: true
  15. default: 'general-cache'
  16. compression_level:
  17. description: 'Compression level (0-9). 0 = No compression, 1 = Fast, 19 = Best.'
  18. required: false
  19. type: number
  20. default: 6
  21. github_token:
  22. description: 'GitHub token for release upload authentication'
  23. required: true
  24. type: string
  25. runs:
  26. using: 'composite'
  27. steps:
  28. - name: Archive, Split, and Upload Cache
  29. shell: bash
  30. env:
  31. GITHUB_TOKEN: ${{ inputs.github_token }}
  32. TARGET_REPO: "${{ github.repository }}"
  33. run: |
  34. # Archive, Split, and Upload Cache
  35. git config user.name "github-actions[bot]"
  36. git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
  37. TAG_NAME="${{ inputs.cache_bucket }}"
  38. BASE_FILENAME="cache-${{ inputs.cache_key }}"
  39. if [ "${{ inputs.compression_level }}" -eq 0 ]; then
  40. FILENAME="$BASE_FILENAME.tar"
  41. else
  42. FILENAME="$BASE_FILENAME.tzst"
  43. fi
  44. echo "::group:: Checking Release State"
  45. git fetch --tags --force
  46. if ! git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
  47. echo "Tag '$TAG_NAME' not found. Creating backdated release..."
  48. GIT_COMMITTER_DATE="2015-01-01T12:00:00" git tag -a "$TAG_NAME" -m "General Cache Storage"
  49. if git push origin "$TAG_NAME" --force; then
  50. gh release create "$TAG_NAME" --title "General Cache" --notes "Automated storage for build assets" --repo "$TARGET_REPO" || true
  51. else
  52. echo "Push failed, tag might have been created by a parallel job. Continuing..."
  53. fi
  54. else
  55. echo "Release '$TAG_NAME' already exists. Ready for upload."
  56. fi
  57. echo "::endgroup::"
  58. echo "::group:: Archiving Path"
  59. echo "Target: ${{ inputs.cache_path }}"
  60. if [ ! -d "${{ inputs.cache_path }}" ] && [ ! -f "${{ inputs.cache_path }}" ]; then
  61. echo "⚠️ Target path not found. Skipping cache save."
  62. echo "::endgroup::"
  63. else
  64. DIR_NAME=$(dirname "${{ inputs.cache_path }}")
  65. BASE_NAME=$(basename "${{ inputs.cache_path }}")
  66. if [ "${{ inputs.compression_level }}" -eq 0 ]; then
  67. tar --posix -h -cvf "$FILENAME" -C "$DIR_NAME" "$BASE_NAME" > /dev/null 2>&1
  68. else
  69. tar --posix -h -I "zstd -T0 -${{ inputs.compression_level }}" -cvf "$FILENAME" -C "$DIR_NAME" "$BASE_NAME" > /dev/null 2>&1
  70. fi
  71. FILE_SIZE=$(stat -c%s "$FILENAME")
  72. echo "Archive created: $FILENAME ($FILE_SIZE bytes)"
  73. echo "::endgroup::"
  74. echo "::group:: Uploading Assets"
  75. MAX_SIZE=2000000000 # ~1.86GB
  76. upload_with_retry() {
  77. local file=$1
  78. local max_attempts=3
  79. for ((i=1; i<=max_attempts; i++)); do
  80. echo " Attempt $i for $file..."
  81. if timeout 10m gh release upload "$TAG_NAME" "$file" --clobber --repo "$TARGET_REPO" > /dev/null 2>&1; then
  82. echo " Successfully uploaded $file"
  83. return 0
  84. fi
  85. echo " ⚠ Attempt $i failed or timed out. Retrying..."
  86. sleep 5
  87. done
  88. return 1
  89. }
  90. if [ "$FILE_SIZE" -gt "$MAX_SIZE" ]; then
  91. echo "⚠ File > 2GB. Splitting..."
  92. split -b 1500M -a 2 "$FILENAME" "${FILENAME}.part"
  93. for part in "${FILENAME}".part*; do
  94. echo "Uploading $part..."
  95. if ! upload_with_retry "$part"; then
  96. echo "::error::Failed to upload part $part after multiple attempts."
  97. exit 1
  98. fi
  99. rm -f "$part"
  100. done
  101. rm -rf "$FILENAME"
  102. else
  103. echo "Uploading $FILENAME..."
  104. if ! upload_with_retry "$FILENAME"; then
  105. echo "::error::Failed to upload $FILENAME after multiple attempts."
  106. exit 1
  107. fi
  108. rm -f "$FILENAME"
  109. fi
  110. echo "::endgroup::"
  111. fi