|
| 1 | +name: 'CloudKit Sync Action' |
| 2 | +description: 'Reusable action for syncing data to CloudKit with export reporting' |
| 3 | + |
| 4 | +inputs: |
| 5 | + environment: |
| 6 | + description: 'CloudKit environment (development or production)' |
| 7 | + required: true |
| 8 | + container-id: |
| 9 | + description: 'CloudKit container ID' |
| 10 | + required: true |
| 11 | + cloudkit-key-id: |
| 12 | + description: 'CloudKit S2S key ID' |
| 13 | + required: true |
| 14 | + cloudkit-private-key: |
| 15 | + description: 'CloudKit S2S private key (PEM content)' |
| 16 | + required: true |
| 17 | + virtualbuddy-api-key: |
| 18 | + description: 'VirtualBuddy TSS API key' |
| 19 | + required: true |
| 20 | + enable-export: |
| 21 | + description: 'Run export after sync and generate reports' |
| 22 | + required: false |
| 23 | + default: 'true' |
| 24 | + |
| 25 | +runs: |
| 26 | + using: "composite" |
| 27 | + steps: |
| 28 | + - name: Download latest built binary |
| 29 | + uses: dawidd6/action-download-artifact@v3 |
| 30 | + with: |
| 31 | + workflow: bushel-cloud-build.yml |
| 32 | + workflow_conclusion: success |
| 33 | + name: bushel-cloud-binary |
| 34 | + path: ./binary |
| 35 | + |
| 36 | + - name: Make binary executable |
| 37 | + shell: bash |
| 38 | + run: chmod +x ./binary/bushel-cloud |
| 39 | + |
| 40 | + - name: Validate required secrets |
| 41 | + shell: bash |
| 42 | + env: |
| 43 | + VIRTUALBUDDY_API_KEY: ${{ inputs.virtualbuddy-api-key }} |
| 44 | + run: | |
| 45 | + if [ -z "$VIRTUALBUDDY_API_KEY" ]; then |
| 46 | + echo "❌ Error: VIRTUALBUDDY_API_KEY is not set" |
| 47 | + echo "Please add VIRTUALBUDDY_API_KEY to repository secrets" |
| 48 | + exit 1 |
| 49 | + fi |
| 50 | + echo "✅ All required secrets are present" |
| 51 | +
|
| 52 | + - name: Run CloudKit sync |
| 53 | + shell: bash |
| 54 | + env: |
| 55 | + CLOUDKIT_KEY_ID: ${{ inputs.cloudkit-key-id }} |
| 56 | + CLOUDKIT_PRIVATE_KEY: ${{ inputs.cloudkit-private-key }} |
| 57 | + CLOUDKIT_ENVIRONMENT: ${{ inputs.environment }} |
| 58 | + CLOUDKIT_CONTAINER_ID: ${{ inputs.container-id }} |
| 59 | + VIRTUALBUDDY_API_KEY: ${{ inputs.virtualbuddy-api-key }} |
| 60 | + run: | |
| 61 | + echo "Starting CloudKit sync..." |
| 62 | + echo "Container: $CLOUDKIT_CONTAINER_ID" |
| 63 | + echo "Environment: $CLOUDKIT_ENVIRONMENT" |
| 64 | +
|
| 65 | + ./binary/bushel-cloud sync \ |
| 66 | + --verbose \ |
| 67 | + --container-identifier "$CLOUDKIT_CONTAINER_ID" |
| 68 | +
|
| 69 | + - name: Run export and generate reports |
| 70 | + if: inputs.enable-export == 'true' |
| 71 | + shell: bash |
| 72 | + env: |
| 73 | + CLOUDKIT_KEY_ID: ${{ inputs.cloudkit-key-id }} |
| 74 | + CLOUDKIT_PRIVATE_KEY: ${{ inputs.cloudkit-private-key }} |
| 75 | + CLOUDKIT_ENVIRONMENT: ${{ inputs.environment }} |
| 76 | + CLOUDKIT_CONTAINER_ID: ${{ inputs.container-id }} |
| 77 | + run: | |
| 78 | + echo "Exporting CloudKit data..." |
| 79 | +
|
| 80 | + # Export to JSON |
| 81 | + ./binary/bushel-cloud export \ |
| 82 | + --output "cloudkit-export-${{ inputs.environment }}.json" \ |
| 83 | + --pretty \ |
| 84 | + --verbose \ |
| 85 | + --container-identifier "$CLOUDKIT_CONTAINER_ID" |
| 86 | +
|
| 87 | + # Parse JSON to extract counts |
| 88 | + RESTORE_COUNT=$(jq '.restoreImages | length' "cloudkit-export-${{ inputs.environment }}.json") |
| 89 | + XCODE_COUNT=$(jq '.xcodeVersions | length' "cloudkit-export-${{ inputs.environment }}.json") |
| 90 | + SWIFT_COUNT=$(jq '.swiftVersions | length' "cloudkit-export-${{ inputs.environment }}.json") |
| 91 | + TOTAL_COUNT=$((RESTORE_COUNT + XCODE_COUNT + SWIFT_COUNT)) |
| 92 | +
|
| 93 | + # Count signed restore images |
| 94 | + SIGNED_COUNT=$(jq '[.restoreImages[] | select(.fields.isSigned == "int64(1)")] | length' "cloudkit-export-${{ inputs.environment }}.json" || echo "0") |
| 95 | +
|
| 96 | + # Generate markdown summary |
| 97 | + cat > export-summary.md <<EOF |
| 98 | + # CloudKit Export Summary |
| 99 | +
|
| 100 | + **Environment**: \`${{ inputs.environment }}\` |
| 101 | + **Container**: \`${{ inputs.container-id }}\` |
| 102 | + **Export Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC") |
| 103 | +
|
| 104 | + ## Record Counts |
| 105 | +
|
| 106 | + | Record Type | Count | |
| 107 | + |-------------|-------| |
| 108 | + | Restore Images | ${RESTORE_COUNT} | |
| 109 | + | Xcode Versions | ${XCODE_COUNT} | |
| 110 | + | Swift Versions | ${SWIFT_COUNT} | |
| 111 | + | **Total** | **${TOTAL_COUNT}** | |
| 112 | +
|
| 113 | + ## Restore Image Status |
| 114 | +
|
| 115 | + - **Signed**: ${SIGNED_COUNT} images currently signed by Apple |
| 116 | + - **Unsigned**: $((RESTORE_COUNT - SIGNED_COUNT)) images no longer signed |
| 117 | +
|
| 118 | + ## Artifacts |
| 119 | +
|
| 120 | + - 📄 Full export data: \`cloudkit-export-${{ inputs.environment }}.json\` |
| 121 | + - 📊 This summary: \`export-summary.md\` |
| 122 | + EOF |
| 123 | +
|
| 124 | + # Append to GitHub Actions summary |
| 125 | + cat export-summary.md >> $GITHUB_STEP_SUMMARY |
| 126 | +
|
| 127 | + echo "✅ Export complete with ${TOTAL_COUNT} total records" |
| 128 | +
|
| 129 | + - name: Upload export artifacts |
| 130 | + if: inputs.enable-export == 'true' |
| 131 | + uses: actions/upload-artifact@v4 |
| 132 | + with: |
| 133 | + name: cloudkit-export-${{ inputs.environment }} |
| 134 | + path: | |
| 135 | + cloudkit-export-${{ inputs.environment }}.json |
| 136 | + export-summary.md |
| 137 | + retention-days: 30 |
0 commit comments