Overview
This issue adds a scheduled GitHub Actions workflow that automatically syncs macOS restore images, Xcode versions, and Swift versions to CloudKit every 12 hours.
Implementation Summary
Code Changes
-
BushelCloudKitService.swift - Added PEM string initializer + environment parameter
- New
init(containerIdentifier:keyID:pemString:environment:) for CI/CD environments
- Accepts PEM content directly from environment variables
- Eliminates need for file I/O in GitHub Actions
- Environment parameter (.development or .production) with default to .development
-
SyncEngine.swift - Support for both authentication methods + environment selection
- Updated initializer to accept both
privateKeyPath and pemString
- Added
environment parameter for dev/prod selection
- Automatically chooses appropriate BushelCloudKitService initializer
- Backward compatible with existing file-based approach
-
SyncCommand.swift - Environment variable support + environment selection
- New
--pem-content command-line option
- New
--environment flag (development/production)
- Reads from
CLOUDKIT_PRIVATE_KEY environment variable
- Reads from
CLOUDKIT_ENVIRONMENT environment variable
- Updated help text with CI/CD examples
New Files
-
.github/workflows/cloudkit-sync.yml - Scheduled workflow
- Runs every 12 hours (00:00 and 12:00 UTC)
- Uses ubuntu-latest with Swift 6.2
- Caches .build directory for faster runs (2-4 minutes after first run)
- Respects fetch intervals (no --force flag)
- Currently configured for development environment
-
.github/CLOUDKIT_SYNC_SETUP.md - Setup documentation
- Step-by-step GitHub Secrets configuration
- Troubleshooting guide
- Security best practices
- Performance and cost information
- Environment switching instructions
Configuration Required
To enable the workflow, add these GitHub Secrets (Settings → Secrets and variables → Actions):
CLOUDKIT_KEY_ID - 32-character Server-to-Server Key ID
CLOUDKIT_PRIVATE_KEY - Full PEM file content (including headers/footers)
Note: A single S2S key works for both development and production environments. The environment is selected via the CLOUDKIT_ENVIRONMENT variable in the workflow file.
See .github/CLOUDKIT_SYNC_SETUP.md for detailed setup instructions.
Features
- Cost-efficient: ~120-240 Linux minutes/month (within free tier)
- Secure: PEM content never written to disk
- Fast: Build caching reduces runtime to 2-4 minutes (after first run)
- Reliable: Respects fetch intervals to avoid API rate limits
- Flexible: Manual trigger available via workflow_dispatch
- Environment support: Same key works for both dev and production (just change CLOUDKIT_ENVIRONMENT variable)
Environment Support
The workflow supports both development and production CloudKit environments:
- Development (default): Safe for testing, free API calls
- Production: Real user data, same key but different environment setting
To switch to production, simply change CLOUDKIT_ENVIRONMENT: development to CLOUDKIT_ENVIRONMENT: production in the workflow file.
Testing
Test the workflow:
- Configure GitHub Secrets (see setup guide)
- Go to Actions → Scheduled CloudKit Sync
- Click "Run workflow" to trigger manually
- Monitor logs for success
Documentation
Overview
This issue adds a scheduled GitHub Actions workflow that automatically syncs macOS restore images, Xcode versions, and Swift versions to CloudKit every 12 hours.
Implementation Summary
Code Changes
BushelCloudKitService.swift - Added PEM string initializer + environment parameter
init(containerIdentifier:keyID:pemString:environment:)for CI/CD environmentsSyncEngine.swift - Support for both authentication methods + environment selection
privateKeyPathandpemStringenvironmentparameter for dev/prod selectionSyncCommand.swift - Environment variable support + environment selection
--pem-contentcommand-line option--environmentflag (development/production)CLOUDKIT_PRIVATE_KEYenvironment variableCLOUDKIT_ENVIRONMENTenvironment variableNew Files
.github/workflows/cloudkit-sync.yml - Scheduled workflow
.github/CLOUDKIT_SYNC_SETUP.md - Setup documentation
Configuration Required
To enable the workflow, add these GitHub Secrets (Settings → Secrets and variables → Actions):
CLOUDKIT_KEY_ID- 32-character Server-to-Server Key IDCLOUDKIT_PRIVATE_KEY- Full PEM file content (including headers/footers)Note: A single S2S key works for both development and production environments. The environment is selected via the
CLOUDKIT_ENVIRONMENTvariable in the workflow file.See .github/CLOUDKIT_SYNC_SETUP.md for detailed setup instructions.
Features
Environment Support
The workflow supports both development and production CloudKit environments:
To switch to production, simply change
CLOUDKIT_ENVIRONMENT: developmenttoCLOUDKIT_ENVIRONMENT: productionin the workflow file.Testing
Test the workflow:
Documentation