Skip to content

Deploy from GitHub Actions

View Markdown

Use this workflow to build 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.

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.

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

The --image override changes the selected Component image for this apply without editing the checked-out file. The resolved image is stored in the Environment revision, so deployment history, rollback, reconciliation, and deliberate pull all show the image that actually ran.

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.