This document describes the GitHub-based continuous integration, continuous deployment (CI/CD), and development infrastructure for the CraftSpace project.
CraftSpace leverages GitHub Actions for automated building, testing, and deployment of its multi-component architecture. This infrastructure enables developers to work efficiently on different parts of the system while maintaining integration across components. The CI/CD system handles everything from Unity WebGL compilation to collection processing and deployment to various environments.
.github/
├── workflows/ # GitHub Actions workflow definitions
│ ├── build-deploy.yml # Main build and deployment workflow
│ ├── update-collections.yml # Collection update workflow
│ ├── build-deploy-sveltekit.yml # SvelteKit-only workflow
│ ├── build-unity-webgl.yml # Unity WebGL-only workflow
│ └── build-push-docker.yml # Docker build and push workflow
├── scripts/ # Shared automation scripts
│ ├── process-collections.sh # Collection processing script
│ ├── deploy-collections.sh # Collection deployment script
│ └── unity-build.sh # Unity build helper script
├── actions/ # Custom GitHub Actions
│ └── unity-builder/ # Custom Unity builder action
└── templates/ # Workflow templates and documentation
└── issue_template.md # Issue template for workflow problems
The CraftSpace project is built on a philosophy of rapid iteration through specialized pipelines. Rather than treating the entire application as a monolith that must be rebuilt for every change, we've decomposed the system into independently deployable components that can be developed and iterated at different speeds.
┌─────────────────────────────────────────────────────────────────────┐
│ DEVELOPMENT PIPELINES │
├─────────────┬─────────────┬─────────────┬─────────────┬─────────────┤
│ SvelteKit │ Unity │ Collection │ Unity JS │ Full │
│ Changes │ WebGL │ Content │ Scripts │ Release │
│ │ Application │ Updates │ Hot-Patch │ Build │
├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
│ Minutes │ Hours │ Minutes │ Seconds │ Hours │
│ to deploy │ to deploy │ to deploy │ to deploy │ to deploy │
└─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
- Minimize Wait Times: Developers should never wait more than a few seconds to see changes during active development
- Component Independence: Changes to one component shouldn't require rebuilding others
- Flexible Deployment: Support partial updates for quick iteration and full builds for releases
- Environment Consistency: Development, staging, and production should use identical processes
- Build Acceleration: Use specialized hardware where needed (e.g., self-hosted runners for Unity)
- Hot-Patching: Update running applications without redeployment whenever possible
Workflow File: .github/workflows/build-deploy-sveltekit.yml
For changes to the web application interface, API endpoints, or server logic:
- Development: Use
npm run devfor instant hot-reloading during development - Staging/Production: Push changes and deploy SvelteKit without rebuilding Unity
- Integration Points:
- Serves Unity WebGL files
- Provides API endpoints for Unity
- Manages dynamic content loading
Workflow File: .github/workflows/build-unity-webgl.yml
For changes to C# code, Unity assets, prefabs, scenes, or shaders:
- Development: Work in Unity Editor for rapid visualization and testing
- Build Acceleration: Self-hosted runners with pre-configured Unity installations
- MacBook Pro (M1/M2) or high-performance Windows laptops
- Pre-cached Unity Editor with all dependencies
- Optimized build settings for development iterations
- Release Builds: Use full WebGL compression and optimization for production
- CI/CD Integration: Automated builds triggered by changes to Unity code paths
Workflow File: .github/workflows/update-content.yml
For changes to collection data, metadata, or texture atlases:
- Development: Update collection data with local processing
- Hot Deployment: Push updated content to all environments without app rebuilds
- Multi-Target: Update content in:
- SvelteKit static directory
- Unity Resources folder
- CDN edge locations
- Cache Management: Purge CDN caches and update version markers for client refreshes
Workflow File: .github/workflows/build-unity-scripts.yml
For changes to Unity behavior without modifying C# code:
- Development: Edit JavaScript and JSON files that control Unity at runtime
- Instant Refresh: Changes take effect on browser refresh without rebuilding
- Deployment Types:
- Local development (file system)
- Staging server (test environment)
- Production CDN (optimized, minified)
- Dynamic Loading: Unity loads these scripts at runtime through JavaScript interop
Workflow File: .github/workflows/build-deploy.yml
For comprehensive releases with changes across all components:
- Complete Process: Rebuilds everything from scratch in the correct order
- Asset Optimization: Full compression and optimization for production
- Consistency Checks: Ensures all components are compatible and synchronized
- Version Tagging: Creates release tags and versioning across all assets
- Documentation: Generates release notes and deployment records
┌──────────────────────┐ ┌────────────────────────┐
│ GitHub Actions │ │ Self-Hosted Runner │
│ Workflow Dispatcher ├──────►│ (MacBook Pro/Windows) │
└──────────────────────┘ └───────────┬────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ Pre-Configured Environment │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Unity Editor │ │ Cache Library │ │ Build Pipeline │ │
│ │ Pre-Installed │ │ Pre-Warmed │ │ Optimized │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────┐
│ Optimized WebGL Build │
└──────────────────────────┘
- Self-Hosted Runners: MacBook Pro or Windows laptops dedicated to Unity builds
- Pre-Installation: Unity Editor, packages, and dependencies pre-installed
- Library Caching: Pre-warmed Unity Library folder to skip import phase
- Parallel Processing: Multiple runners can handle different build tasks
- Hardware Acceleration: Dedicated GPUs improve shader compilation speed
- Build Variants: Development builds (faster, less compressed) vs Production builds
| Component | Change Type | Workflow | Typical Deployment Time | Hot-Patchable |
|---|---|---|---|---|
| SvelteKit | Web UI/API | build-deploy-sveltekit | 3-5 minutes | Yes (dev mode) |
| Unity WebGL | C#/Assets | build-unity-webgl | 30-60 minutes | No |
| Collections | Content | update-content | 2-10 minutes | Yes |
| Unity JS | Runtime Behavior | build-unity-scripts | 30-60 seconds | Yes |
| Full Release | Everything | build-deploy | 60-90 minutes | No |
-
Initial Setup: Full build of all components to establish baseline
gh workflow run build-deploy.yml
-
Daily Development: Focused iteration on specific components
- Working on SvelteKit: Use local dev server with hot reloading
- Working on Unity: Use Unity Editor, push only when ready for build
- Working on content: Use content pipeline for rapid updates
- Working on behavior: Use JavaScript hot-patching
-
Integration Testing: Periodic integration of all components
- Deploy to staging environment
- Verify cross-component interactions
- Test on multiple browsers and devices
-
Production Release: Complete rebuild with full optimization
- Trigger full build and deploy workflow
- Run comprehensive test suite
- Deploy to production with staged rollout
This project uses GitHub Actions to automate building and deployment:
- SvelteKit Build and Deploy: Builds the SvelteKit app and deploys to the hosting environment
- Unity WebGL Build: Uses a self-hosted runner to build the Unity WebGL application
- Collection Update: Processes Internet Archive collections and deploys them to the hosting environment
- Create a new GitHub repository
- Add required secrets:
UNITY_LICENSE: Unity license for building WebGLDIGITALOCEAN_ACCESS_TOKEN: API token for Digital OceanDIGITALOCEAN_APP_ID: App Platform application IDSSH_PRIVATE_KEY: SSH private key for deploymentDO_SPACES_KEY: Digital Ocean Spaces access keyDO_SPACES_SECRET: Digital Ocean Spaces secretDO_SPACES_ENDPOINT: Digital Ocean Spaces endpointDO_SPACES_BUCKET: Digital Ocean Spaces bucket name
- macOS 12 (Monterey) or later
- Administrator access on your MacBook Pro
- At least 16GB RAM recommended
- At least 40GB of free disk space
-
Install Xcode Command Line Tools:
xcode-select --install
-
Install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -
Install Node.js and npm:
brew install node
-
Install Docker Desktop: Download from docker.com
- Download Unity Hub from unity3d.com
- Install Unity Hub and sign in with your Unity account
- Install Unity version 2022.3.20f1 (or your preferred version)
- In Unity Hub, go to "Installs" → "Add" → select version 2022.3.20f1
- Include WebGL Build Support module
-
Go to your GitHub repository → Settings → Actions → Runners
-
Click "New self-hosted runner"
-
Select macOS
-
Follow the provided instructions to download and configure the runner
-
Add labels to your runner:
./config.sh --labels unity,configured
-
Start the runner as a service:
sudo ./svc.sh install sudo ./svc.sh start
-
Verify the runner is connected in your GitHub repository settings
- Create a build script in your Unity project:
// Assets/Editor/BuildScript.cs
using UnityEditor;
using System.IO;
public class BuildScript
{
[MenuItem("Build/WebGL Development")]
public static void BuildWebGLDevelopment()
{
BuildWebGL(BuildOptions.Development);
}
[MenuItem("Build/WebGL Production")]
public static void BuildWebGLProduction()
{
BuildWebGL(BuildOptions.None);
}
private static void BuildWebGL(BuildOptions options)
{
string outputDir = "Build/WebGL";
// Make sure the output directory exists
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
// Define build settings
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions
{
scenes = EditorBuildSettings.scenes,
targetGroup = BuildTargetGroup.WebGL,
target = BuildTarget.WebGL,
options = options,
locationPathName = outputDir
};
// Build the project
BuildPipeline.BuildPlayer(buildPlayerOptions);
}
}- Ensure your Unity path in the workflow file is correct:
- Edit
.github/workflows/build-unity-webgl.yml - Update the Unity path variable to match your Unity installation path
- Edit
-
Navigate to the SvelteKit project:
cd SvelteKit/BackSpace -
Install dependencies:
npm install
-
Start the development server:
npm run dev
-
For production builds:
npm run build
The Docker setup is configured in the Dockerfile. The GitHub workflow builds and pushes the Docker image automatically when changes are detected:
# Manual build and push
cd SvelteKit/BackSpace
docker build -t do-registry.digitalocean.com/craftspace/backend:latest .
docker push do-registry.digitalocean.com/craftspace/backend:latestThe application is deployed to Digital Ocean App Platform:
- Web Application: The SvelteKit application serves as the web frontend and API layer
- CDN Component: Static assets are served through Digital Ocean Spaces with CDN enabled
- Container Service: Docker containers handle backend processing
To configure deployment:
- Go to Digital Ocean App Platform
- Create a new app from GitHub repository
- Configure environment variables and resources
- Set up preview environments for staging/testing
The server components are deployed as Docker containers to Digital Ocean App Platform:
# Deploy manually (if needed)
doctl apps create --spec .do/app.yaml- Make changes to SvelteKit files
- Test locally with
npm run dev - Commit and push to trigger automatic deployment
- Make changes in the Unity project
- Test locally in Unity Editor
- Commit and push to trigger the Unity build workflow
- The build is automatically copied to the SvelteKit static directory and committed
-
Register a new collection:
cd SvelteKit/BackSpace npm run ia:register mycollection "My Collection" "subject:mycollection"
-
Process the collection:
npm run ia:process
-
Commit changes and push to trigger deployment
The integration between Unity and SvelteKit is handled through the CraftSpace.svelte component, which loads the Unity WebGL build at runtime.
The project includes scripts for downloading content from the Internet Archive:
# Build TypeScript scripts
npm run build:scripts
# Download and process a collection
npm run ia:process -- --collection=scifi- Check the Unity build log for errors:
Unity/CraftSpace/unity_build.log - Ensure the build method name matches in the workflow file and Unity script
- Verify Unity version compatibility
- Check runner status:
sudo ./svc.sh status - View runner logs:
tail -f ~/.runner/logs/Worker_* - Restart runner if needed:
sudo ./svc.sh restart
- Check for JS/TS errors in the console
- Ensure all dependencies are installed:
npm ci - Clear the SvelteKit build cache:
rm -rf .svelte-kit
File: .github/workflows/build-deploy.yml
This comprehensive workflow handles the complete build and deployment process:
- Builds the Unity WebGL application
- Processes collections data
- Builds the SvelteKit application
- Deploys everything to Digital Ocean
Trigger: Manual workflow dispatch
File: .github/workflows/update-collections.yml
This workflow updates the collection data without rebuilding the entire application:
- Incrementally processes collection data
- Deploys updated collections to CDN
Trigger:
- Weekly schedule (Monday at 1 AM)
- Manual workflow dispatch
File: .github/workflows/build-deploy-sveltekit.yml
For faster iterations on the web application without rebuilding Unity:
- Builds only the SvelteKit application
- Deploys to Digital Ocean App Platform
Trigger:
- Push to main branch affecting SvelteKit files
- Manual workflow dispatch
File: .github/workflows/build-unity-webgl.yml
For Unity-focused development:
- Builds only the Unity WebGL application
- Updates the SvelteKit static directory with the new build
- Commits the changes back to the repository
Trigger:
- Push to main branch affecting Unity files
- Manual workflow dispatch
Scripts in .github/scripts/ are shared across workflows:
process-collections.sh: Handles collection processing (full or incremental)deploy-collections.sh: Deploys collections to CDN
The following secrets need to be set in the GitHub repository:
UNITY_LICENSE: Unity license for building WebGL
DIGITALOCEAN_ACCESS_TOKEN: API tokenDIGITALOCEAN_APP_ID: App Platform application IDDIGITALOCEAN_HOST: Host for SSH connectionSSH_PRIVATE_KEY: SSH private key
DO_REGISTRY_TOKEN: Digital Ocean Container Registry token
DO_SPACES_KEY: Digital Ocean Spaces access keyDO_SPACES_SECRET: Digital Ocean Spaces secretDO_SPACES_ENDPOINT: Digital Ocean Spaces endpointDO_SPACES_BUCKET: Digital Ocean Spaces bucket name
- Go to "Actions" tab in the GitHub repository
- Select the workflow you want to run
- Click "Run workflow"
- Set any workflow input parameters
- Click "Run workflow" button
When adding new components to the monorepo:
- Create a new directory at the root level
- Add a specific workflow file in
.github/workflows/ - Share scripts when possible using
.github/scripts/ - Update this documentation
The workflows are designed to work together in a complementary way:
┌───────────────────┐
│ Manual Workflow │
│ Dispatch │
└─────────┬─────────┘
│
┌───────────────┴───────────────┐
│ │
┌────────────▼─────────────┐ ┌─────────────▼────────────┐
│ Component-Specific │ │ Comprehensive │
│ Workflows │ │ Build and Deploy │
└────────────┬─────────────┘ └─────────────┬────────────┘
│ │
┌────────────────┼───────────────────────────────┼────────────────┐
│ │
└─────────────────────────────────────────────────────────────────┘
This multi-tiered approach allows for:
- Fast iterative development on specific components
- Automated deployment of the full application
- Scheduled updates of collection data
- Flexible deployment options (container, direct, CDN)
File: .github/workflows/update-content.yml
This specialized workflow is designed for rapid content iteration without rebuilding application code. It enables developers to update collection data, metadata, and even client-side functionality with minimal deployment overhead.
The content development pipeline allows:
- Hot-patching content into production environments
- Updating collection data without rebuilding SvelteKit or Unity
- Modifying client-side behavior through JavaScript injection
- Minimizing developer wait times during content iteration
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ Multi-Target │
│ Content │───────►│ Processing │───────►│ Deployment │
│ Development │ │ Pipeline │ │ Injection │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
│
▼
┌─────────────────────────────────────────────────────┐
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ │ │ │
│ Static Content Cache │ │ Dynamic Code Cache │
│ (Collections Data) │ │ (JavaScript/JSON) │
│ │ │ │
└─────────────────┬───────┘ └───────────┬─────────────┘
│ │
▼ ▼
┌────────────────────────────────────┐ ┌─────────────────────────────────────────┐
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────┐
│ │ │ │ │ │ │ │ │ │ │ │
│ SvelteKit │ │ Unity Client │ │ CDN │ │ SvelteKit │ │ Unity Client │ │ CDN │
│ Static Directory │ │ Resources Dir │ │ │ │ Public JS │ │ Dynamic Scripts │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────┘ └──────────────────┘ └──────────────────┘ └──────┘
The Unity WebGL build is configured to load external JavaScript modules that implement functionality outside the Unity C# codebase:
- Core Communication Layer: Establishes messaging between Unity and JavaScript
- Extension Modules: Implement specific features that can be hot-patched
- Configuration Data: JSON files defining behavior that can be updated
This approach allows significant portions of application logic to be modified without Unity rebuilds.
Example directory structure:
SvelteKit/BackSpace/static/js/unity-extensions/
├── core/
│ ├── bridge.js # Core Unity-JS communication
│ ├── loader.js # Dynamically loads extension modules
│ └── messaging.js # Message formatting and routing
├── features/
│ ├── collections.js # Collection management (hot-patchable)
│ ├── search.js # Search functionality (hot-patchable)
│ ├── visualization.js # Visualization options (hot-patchable)
│ └── ui.js # UI customizations (hot-patchable)
└── config/
├── display.json # Visual configuration (hot-patchable)
├── collections.json # Collection settings (hot-patchable)
└── features.json # Feature flags (hot-patchable)
To maximize hardware utilization and provide scalability, we plan to containerize our GitHub runner environment. This approach will allow us to run multiple Unity build jobs in parallel on a single high-performance machine.
- Parallelism: Run multiple Unity builds simultaneously on one machine
- Isolation: Keep each build in its own container environment
- Resource Management: Allocate appropriate CPU/memory to each build job
- Versioning: Support multiple Unity versions in parallel
- Scaling: Add more containers as resource availability permits
- Base Docker Image: Create a Unity-ready Docker image with all dependencies
- Runner Configuration: Configure GitHub Actions runner in each container
- Persistent Caching: Mount shared caches for Library and Package dependencies
- Resource Limits: Configure container resource constraints
- Job Orchestration: Use labels to direct specific jobs to appropriate containers
Example of future deployment:
# Launch multiple containerized runners on a powerful machine
docker-compose up -d --scale unity-runner=4This containerization approach will reduce build times by better utilizing multi-core CPUs and providing parallel processing capabilities for the Unity build pipeline.