|
| 1 | +on: |
| 2 | + workflow_dispatch: |
| 3 | + inputs: |
| 4 | + cache_entries: |
| 5 | + description: 'JSON array of cache entries, e.g., [{"key":"abc","version":"123"},{"key":"def","version":"456"}]' |
| 6 | + required: true |
| 7 | + type: string |
| 8 | + default: '[{"key":"runner_venv-Linux-/opt/hostedtoolcache/Python/3.12.12/x64-dbe133b0a76747625e6c8139943b9dc2dbf5814e9ccf9f4a8ed5b7fa66dd2976","version":"f488f6875b536eb746450004e6f18bf74d514ad2cad78c86d6d5147ddbf9f9b0"},{"key":"PFxRDTsQC2CBRTRk3TMxWNYXnd0=","version":"4793076103aa823b0a4c97942d7385d4346f77a3c30a0bad6e0f1d748becbab5"},{"key":"playwright-browsers-oldest-dd6","version":"4f7514040e3a28a321a9658d8e3a51fd52c29410f6844d0d51bcb9b20ca5e3a6"},{"key":"PFxRDTsQC2CBRTRk3TMxWNYXnd0=","version":"c95311a28e589c62f14651d2e6001da3e2afe6e855380a412a583dabc576b960"},{"key":"yarn-cache-AI Guard-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"Aktlxw4hnyBVd/vZJbkdxGmq8Tw=","version":"3dbcc4f8dfd5fbbab9759602b7adb19c466cf9edfc277687f97ba9efbdc86d90"},{"key":"yarn-cache-APM Capabilities-tracing-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"yarn-cache-AppSec-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"yarn-cache-OpenFeature-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"cypress-binary-14.5.4","version":"09038f5f1eb279f921ac07849ccf00ea0cadd76685c868eab628a2e3f47ef0b7"},{"key":"n71Gg/JormzoitmBpVjBCZCcL6Y=","version":"0c867ee6264758fbca938e6c6d38a3160cb478f2770da2f831e22e4c9e3720d8"},{"key":"playwright-browsers-Linux-1.57.0","version":"b11b119dfd10565044882f81f06d3a75b1602bec6f8658ac905dd63583b2a885"},{"key":"cypress-binary-10.2.0","version":"09038f5f1eb279f921ac07849ccf00ea0cadd76685c868eab628a2e3f47ef0b7"},{"key":"yarn-cache-Profiling-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"actionlint-1.7.9-Linux-X64","version":"2c5831b0ad32de99a644bc2cdd9a58421edce007c9b47f4c1c7d25220f9d6578"},{"key":"yarn-cache-AppSec-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"PFxRDTsQC2CBRTRk3TMxWNYXnd0=","version":"c95311a28e589c62f14651d2e6001da3e2afe6e855380a412a583dabc576b960"},{"key":"playwright-browsers-oldest-dd6","version":"4f7514040e3a28a321a9658d8e3a51fd52c29410f6844d0d51bcb9b20ca5e3a6"},{"key":"yarn-cache-Profiling-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"cypress-binary-14.5.4","version":"09038f5f1eb279f921ac07849ccf00ea0cadd76685c868eab628a2e3f47ef0b7"},{"key":"yarn-cache-APM Capabilities-tracing-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"cypress-binary-10.2.0","version":"09038f5f1eb279f921ac07849ccf00ea0cadd76685c868eab628a2e3f47ef0b7"},{"key":"yarn-cache-AI Guard-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"Aktlxw4hnyBVd/vZJbkdxGmq8Tw=","version":"3dbcc4f8dfd5fbbab9759602b7adb19c466cf9edfc277687f97ba9efbdc86d90"},{"key":"yarn-cache-OpenFeature-windows-b4e1dc4e46ec063c714cab2e6a48b2f1c42c37b4546d1f2592a517159bbd52d8-v2","version":"dfeaf94a5df020ad999e6dd827afacf94f5a2ddf5418288305ef5b91f639b181"},{"key":"playwright-browsers-Linux-1.57.0","version":"b11b119dfd10565044882f81f06d3a75b1602bec6f8658ac905dd63583b2a885"},{"key":"n71Gg/JormzoitmBpVjBCZCcL6Y=","version":"0c867ee6264758fbca938e6c6d38a3160cb478f2770da2f831e22e4c9e3720d8"},{"key":"actionlint-1.7.9-Linux-X64","version":"2c5831b0ad32de99a644bc2cdd9a58421edce007c9b47f4c1c7d25220f9d6578"},{"key":"PFxRDTsQC2CBRTRk3TMxWNYXnd0=","version":"c95311a28e589c62f14651d2e6001da3e2afe6e855380a412a583dabc576b960"},{"key":"playwright-browsers-oldest-dd6","version":"4f7514040e3a28a321a9658d8e3a51fd52c29410f6844d0d51bcb9b20ca5e3a6"}]' |
| 9 | + |
| 10 | +jobs: |
| 11 | + extract-cache: |
| 12 | + runs-on: ubuntu-latest |
| 13 | + |
| 14 | + steps: |
| 15 | + - name: Checkout (minimal) |
| 16 | + uses: actions/checkout@v4 |
| 17 | + with: |
| 18 | + sparse-checkout: | |
| 19 | + .github |
| 20 | + sparse-checkout-cone-mode: false |
| 21 | + |
| 22 | + - name: Extract caches |
| 23 | + run: | |
| 24 | + mkdir -p cache-artifacts |
| 25 | +
|
| 26 | + echo '${{ inputs.cache_entries }}' | jq -c '.[]' | while read -r entry; do |
| 27 | + key=$(echo "$entry" | jq -r '.key') |
| 28 | + version=$(echo "$entry" | jq -r '.version') |
| 29 | +
|
| 30 | + echo "================================================" |
| 31 | + echo "Attempting to restore: $key (version: $version)" |
| 32 | + echo "================================================" |
| 33 | +
|
| 34 | + safe_name=$(echo "$key-$version" | tr '/' '_' | tr ':' '_') |
| 35 | + cache_dir="cache-artifacts/$safe_name" |
| 36 | + mkdir -p "$cache_dir" |
| 37 | +
|
| 38 | + echo "Restoring to: $cache_dir" |
| 39 | +
|
| 40 | + cat > "$cache_dir/metadata.json" <<EOF |
| 41 | + { |
| 42 | + "key": "$key", |
| 43 | + "version": "$version", |
| 44 | + "requested_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", |
| 45 | + "runner_os": "$RUNNER_OS", |
| 46 | + "runner_arch": "$RUNNER_ARCH" |
| 47 | + } |
| 48 | + EOF |
| 49 | + done |
| 50 | +
|
| 51 | + - name: Restore cache entries |
| 52 | + id: restore |
| 53 | + continue-on-error: true |
| 54 | + run: | |
| 55 | + echo '${{ inputs.cache_entries }}' | jq -c '.[]' | while read -r entry; do |
| 56 | + key=$(echo "$entry" | jq -r '.key') |
| 57 | + version=$(echo "$entry" | jq -r '.version') |
| 58 | + safe_name=$(echo "$key-$version" | tr '/' '_' | tr ':' '_') |
| 59 | + cache_dir="cache-artifacts/$safe_name" |
| 60 | +
|
| 61 | + echo "::group::Restoring $key" |
| 62 | +
|
| 63 | + restored="false" |
| 64 | + if gh cache restore "$cache_dir" --key "$key" 2>/dev/null; then |
| 65 | + echo "✓ Successfully restored $key" |
| 66 | + restored="true" |
| 67 | + else |
| 68 | + echo "✗ Failed to restore $key" |
| 69 | + fi |
| 70 | +
|
| 71 | + echo "$restored" > "$cache_dir/restore_status.txt" |
| 72 | + echo "::endgroup::" |
| 73 | + done |
| 74 | + env: |
| 75 | + GH_TOKEN: ${{ github.token }} |
| 76 | + |
| 77 | + - name: Create file hashes |
| 78 | + run: | |
| 79 | + echo "# File Hashes (SHA256)" > cache-artifacts/HASHES.txt |
| 80 | + find cache-artifacts -type f -not -name "HASHES.txt" -exec sha256sum {} \; >> cache-artifacts/HASHES.txt |
| 81 | +
|
| 82 | + - name: Prepare artifacts for upload |
| 83 | + run: | |
| 84 | + echo '${{ inputs.cache_entries }}' | jq -c '.[]' | while read -r entry; do |
| 85 | + key=$(echo "$entry" | jq -r '.key') |
| 86 | + version=$(echo "$entry" | jq -r '.version') |
| 87 | + safe_name=$(echo "$key-$version" | tr '/' '_' | tr ':' '_') |
| 88 | + cache_dir="cache-artifacts/$safe_name" |
| 89 | +
|
| 90 | + if [ -d "$cache_dir" ]; then |
| 91 | + tar -czf "${safe_name}.tar.gz" -C "cache-artifacts" "$(basename "$cache_dir")" |
| 92 | + artifact_name="${key}:${version}" |
| 93 | + safe_artifact_name=$(echo "$artifact_name" | sed 's/[^a-zA-Z0-9:_-]/_/g') |
| 94 | + echo "$safe_artifact_name|${safe_name}.tar.gz" >> artifact_list.txt |
| 95 | + fi |
| 96 | + done |
| 97 | +
|
| 98 | + - name: Upload artifacts |
| 99 | + uses: actions/upload-artifact@v4 |
| 100 | + if: always() |
| 101 | + with: |
| 102 | + name: cache-forensics-batch-${{ github.run_number }} |
| 103 | + path: | |
| 104 | + *.tar.gz |
| 105 | + cache-artifacts/HASHES.txt |
| 106 | + retention-days: 30 |
| 107 | + if-no-files-found: warn |
| 108 | + |
| 109 | + - name: Display summary |
| 110 | + if: always() |
| 111 | + run: | |
| 112 | + echo "## Cache Extraction Complete 🔍" >> $GITHUB_STEP_SUMMARY |
| 113 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 114 | +
|
| 115 | + if [ -f artifact_list.txt ]; then |
| 116 | + echo "### Extracted Artifacts" >> $GITHUB_STEP_SUMMARY |
| 117 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 118 | + echo "| Cache Key:Version | Archive File |" >> $GITHUB_STEP_SUMMARY |
| 119 | + echo "|-------------------|--------------|" >> $GITHUB_STEP_SUMMARY |
| 120 | + while IFS='|' read -r artifact_name archive_file; do |
| 121 | + echo "| \`$artifact_name\` | \`$archive_file\` |" >> $GITHUB_STEP_SUMMARY |
| 122 | + done < artifact_list.txt |
| 123 | + fi |
0 commit comments