Deploy with GitHub Actions
This workflow builds one immutable image for each commit. A pull request into
main applies it to preview-pr-<number>; a push to main applies it to
production. Closing the pull request deletes its complete preview Environment.
The workflow does not create preview infrastructure procedurally. The first
apply to a name matching the Project Flow’s preview-* stage forks the
configured parent Environment, then reconciles the proposed image on top.
Prepare access
Section titled “Prepare access”Create a Team-scoped API token under API tokens in the console and add it to
the GitHub repository as the DELIBERATE_TOKEN Actions secret. Add the Team
slug as the DELIBERATE_TEAM repository variable.
The example assumes the directly-authored Component is named app and its
image belongs at registry.deliberate.cloud/<team>/app. Change both names to
match the Project.
Workflow
Section titled “Workflow”Create .github/workflows/deliberate.yaml:
name: deliberate
on: push: branches: [main] pull_request: branches: [main] types: [opened, synchronize, reopened, closed]
permissions: contents: read
env: DELIBERATE_TOKEN: ${{ secrets.DELIBERATE_TOKEN }} DELIBERATE_TEAM: ${{ vars.DELIBERATE_TEAM }}
jobs: deploy: if: >- github.event_name == 'push' || (github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository) runs-on: ubuntu-latest concurrency: group: deliberate-${{ github.event.pull_request.number || 'production' }} cancel-in-progress: true steps: - uses: actions/checkout@v4
- name: Install deliberate run: curl -fsSL https://get.deliberate.cloud | sh
- name: Log Docker into the deliberate registry run: >- deliberate registry login --runtime docker --team "$DELIBERATE_TEAM" --name "github-${GITHUB_RUN_ID}" --days 1
- name: Build and push the immutable image id: image run: | IMAGE="registry.deliberate.cloud/${DELIBERATE_TEAM}/app:git-${GITHUB_SHA}" docker build --tag "$IMAGE" . docker push "$IMAGE" echo "reference=$IMAGE" >> "$GITHUB_OUTPUT"
- name: Select Environment id: environment env: PR_NUMBER: ${{ github.event.pull_request.number }} run: | if [ "$GITHUB_EVENT_NAME" = "push" ]; then echo "name=production" >> "$GITHUB_OUTPUT" else echo "name=preview-pr-${PR_NUMBER}" >> "$GITHUB_OUTPUT" fi
- name: Apply run: >- deliberate apply --env "${{ steps.environment.outputs.name }}" --image "app=${{ steps.image.outputs.reference }}" --yes
- name: Wait for readiness run: >- deliberate envs status "${{ steps.environment.outputs.name }}" --wait --timeout 10m
- name: Report the application URL run: | URL="$(deliberate open --env "${{ steps.environment.outputs.name }}" --print)" echo "### deliberate. deployment" >> "$GITHUB_STEP_SUMMARY" echo "$URL" >> "$GITHUB_STEP_SUMMARY"
remove-preview: if: github.event_name == 'pull_request' && github.event.action == 'closed' runs-on: ubuntu-latest concurrency: group: deliberate-${{ github.event.pull_request.number }} cancel-in-progress: true steps: - uses: actions/checkout@v4
- name: Install deliberate run: curl -fsSL https://get.deliberate.cloud | sh
- name: Remove the complete preview Environment run: >- deliberate envs delete "preview-pr-${{ github.event.pull_request.number }}" --force--image is a typed deployment input, not mutable hidden state. Before apply,
the CLI merges the image into the in-memory authored tree and shows it in the
normal diff. The resolved tree is stored with the Environment revision, so
deployment history, rollback, reconciliation, and deliberate pull agree on
the image that actually ran. The checked-out files remain unchanged.
Pull requests from forks do not receive repository secrets and are excluded by the deploy condition above. Review and run untrusted contributions without granting them a Team deployment token.