Created
January 9, 2026 07:58
-
-
Save marckohlbrugge/6d4aadf5a56474e3cc39881c3971b7ca to your computer and use it in GitHub Desktop.
Optimistic Builds™ with Kamal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Optimistic Builds for Kamal | |
| # | |
| # This workflow speeds up deploys by building the Docker image in parallel with CI. | |
| # Instead of: CI → Build → Deploy (sequential) | |
| # We do: CI ↘ | |
| # → Deploy | |
| # Build ↗ | |
| # | |
| # The "optimistic" part: we start building before knowing if tests pass. | |
| # Since CI usually passes, this saves ~2 minutes per deploy. | |
| name: Deploy | |
| on: | |
| push: | |
| branches: [main] | |
| concurrency: | |
| group: deploy-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| # Your normal CI setup here | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # ... your test steps | |
| # Build Docker image in parallel with tests (optimistic build) | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Set up SSH for Kamal | |
| uses: webfactory/[email protected] | |
| with: | |
| ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| bundler-cache: true | |
| # Build and push image to your registry | |
| - name: Build and push image | |
| env: | |
| KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }} | |
| VERSION: ${{ github.sha }} | |
| run: bundle exec kamal build push --version=$VERSION | |
| # Pre-pull image on the server so deploy is instant | |
| - name: Pre-pull image on server | |
| env: | |
| KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }} | |
| VERSION: ${{ github.sha }} | |
| run: bundle exec kamal build pull --version=$VERSION | |
| # Deploy only runs after BOTH test and build succeed | |
| deploy: | |
| needs: [test, build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up SSH for Kamal | |
| uses: webfactory/[email protected] | |
| with: | |
| ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| bundler-cache: true | |
| # Deploy the pre-built, pre-pulled image | |
| # --skip-push: Don't build/push, image already exists | |
| # --version: Use the specific image we built earlier | |
| - name: Deploy | |
| env: | |
| KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }} | |
| VERSION: ${{ github.sha }} | |
| run: bundle exec kamal deploy --skip-push --version=$VERSION |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment