This document explains how Codespaces pre-builds are configured for the pg_durable repository and how to maintain them.
GitHub Codespaces pre-builds reduce startup time by pre-building the development environment. Without a prebuild, first-time setup is noticeably slower because PostgreSQL, pgrx, and the extension toolchain all need to be prepared. With a healthy prebuild, opening a new Codespace is much faster because the expensive setup has already been done.
Pre-builds must be enabled by a repository administrator:
- Go to repository Settings → Codespaces
- Click Set up prebuild
- Configure the prebuild:
- Configuration: Select
.devcontainer/devcontainer.json - Region: Select your preferred region(s)
- Trigger: Choose "Automatically" for changes to main branch
- Reduce prebuild available to specific regions: Optional
- Configuration: Select
- Click Create
duroxide and duroxide-pg are crates.io dependencies. No provider checkout, provider PAT, or extra Codespaces repository permission is required.
Codespaces has two distinct phases:
- Pre-build Phase (runs in GitHub Actions, cached for all users)
- Triggered by:
.github/workflows/prebuild.yml - Executes:
onCreateCommandindevcontainer.json
- Triggered by:
- Duration: depends on cache state and network conditions; it is the slow phase and runs only when the prebuild needs to be refreshed
- Installs:
- System dependencies (libssl, clang, bison, etc.)
- cargo-pgrx 0.16.1
- PostgreSQL 17 (downloaded and compiled via pgrx)
- Rust dependencies from crates.io
- Builds and installs pg_durable
- Recreates the local
~/.pgrx/data-17cluster withinitdb -U postgres- Pre-creates thepg_durableextension and verifies it - Result: a prebuilt environment with dependencies, build artifacts, and a ready-to-start local PostgreSQL cluster
- Post-Create Phase — no
postCreateCommandis configured. When the Codespace opens the prebuild environment is ready; run./scripts/pg-start.shto start PostgreSQL and begin working.
.devcontainer/
├── devcontainer.json # Main configuration with onCreateCommand
└── onCreateCommand.sh # Heavy setup (runs during prebuild)
.github/workflows/
└── prebuild.yml # Validates devcontainer configuration
Note: The workflow doesn't trigger prebuilds directly. GitHub automatically triggers prebuilds when enabled in repository settings.
Once prebuilds are enabled in Settings, they are automatically triggered when:
- Changes are pushed to the
mainbranch - The devcontainer configuration is updated
- Dependencies change (Cargo.toml, Cargo.lock)
You can manually trigger a prebuild:
- Go to repository Settings → Codespaces
- Find your prebuild configuration
- Click the "..." menu → "Trigger prebuild"
- Go to repository Settings → Codespaces → Prebuild configuration
- View prebuild status for each configuration
- See which branches have active prebuilds
- Check prebuild success/failure history
- View logs for failed prebuilds
The prebuild logs will show the execution of onCreateCommand.sh and any errors that occurred.
When you need to update system dependencies or pgrx version:
- Update
onCreateCommand.shwith the new dependencies - Commit and push to main (or create a PR)
- Wait for the prebuild to complete
- Test in a new Codespace to verify the changes work
Example: Updating pgrx version
# In .devcontainer/onCreateCommand.sh
cargo install cargo-pgrx --version 0.16.1 --locked # Updated from 0.15.0- Check the prebuild logs in Settings → Codespaces → Prebuild configuration
- Common issues:
- System dependency installation failures (apt-get)
- Network timeouts during PostgreSQL download
- Cargo compilation errors
- Fix the issue in the relevant script and push
- The prebuild will automatically retry on next push or trigger manually
Possible causes:
- Prebuilds not enabled yet (check Settings → Codespaces)
- Prebuild hasn't completed yet (check prebuild status)
- Prebuild is for a different branch than you're using
- Recent changes weren't included in the last prebuild
- Cache was invalidated (check if base image changed)
Solution: Enable prebuilds if not done, wait for completion, or manually trigger
This means the prebuild did not run or failed. There is no automatic fallback — open a terminal and run ./scripts/pg-start.sh to trigger a full build and install.
Solution: Investigate why the prebuild isn't working and fix it for future users
No longer applicable — provider dependencies come from crates.io and GH_PAT is not used by the prebuild. If you see a GH_PAT secret configured at the repo level, you can safely remove it.
Pre-builds use GitHub Actions compute time. However:
- They save users from repeating the expensive environment setup on every fresh Codespace
- Break-even after 1-2 Codespace opens
- Well worth it for active repositories
- Storage costs apply for prebuild images (typically negligible)
To manage costs:
- Configure prebuilds only for active branches (typically just
main) - Set appropriate retention policies in prebuild settings
- Monitor usage in Settings → Codespaces
- Keep
onCreateCommand.shdeterministic - Don't use dynamic versions - Test changes locally first - Use Dev Containers in VS Code
- Monitor prebuild success rate - Set up notifications for failures
- Update documentation - Keep this doc in sync with changes
- Pin dependency versions - Avoid surprises from version changes
onCreateCommandruns during prebuild and does all the heavy setup once.- When the Codespace opens the environment is already ready; there is nothing useful a
postCreateCommandcan do that the user cannot trigger themselves with./scripts/pg-start.sh. - Omitting
postCreateCommandavoids running a script whose output is not visible to most users.
- Better maintainability and readability
- Easier to test locally
- Can share logic between scripts
- Better error handling with
set -e
You can test the devcontainer configuration locally using VS Code:
- Install the Dev Containers extension in VS Code
- Open the repository in VS Code
- Press
F1and select "Dev Containers: Rebuild Container" - This simulates the Codespace environment locally
Note: Local testing doesn't simulate the prebuild workflow exactly, but it validates the scripts work.