Skip to content

Environment Action

The Environment Action creates, updates and deletes Quant Cloud environments.

Repository: quantcdn/quant-cloud-environment-action (latest release v4.0.0)

The action works on environments only. Create the application first, in the dashboard or with the API.

Input Required Default Description
api_key Yes Quant API key
organization Yes Organisation machine name
app_name Yes Application name
environment_name Yes Environment name
base_url No https://dashboard.quantcdn.io QuantGov: https://dash.quantgov.cloud (a trailing /api/v3 is also accepted)
from_environment No Clone the configuration of this environment. Used only when the environment is created
compose_spec No The translated_compose output of the Compose Action. Required for update; create needs it or from_environment
image_suffix No Image tag suffix that the platform applies
operation No create create, update or delete

Output: environment_name.

  • create - Creates the environment. If it already exists, the action updates it instead.
  • update - Updates an existing environment. Fails if the environment does not exist.
  • delete - Deletes the environment. Passes if the environment does not exist.
- uses: quantcdn/quant-cloud-compose-action@v4
id: compose
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
compose_file: docker-compose.yml
- uses: quantcdn/quant-cloud-environment-action@v4
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
app_name: my-app
environment_name: production
compose_spec: ${{ steps.compose.outputs.translated_compose }}

Let the Init Action detect the environment, and choose the operation from its output:

- uses: quantcdn/quant-cloud-environment-action@v4
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
app_name: ${{ steps.init.outputs.quant_application }}
environment_name: ${{ steps.init.outputs.environment_name }}
operation: ${{ steps.init.outputs.environment_exists == 'true' && 'update' || 'create' }}
compose_spec: ${{ steps.compose.outputs.translated_compose }}

After an update, redeploy with the State Action.

This workflow gives each pull request its own environment, pr-<number>. The Init Action picks the name from the pull request. The first run creates the environment as a copy of production’s configuration, waits until creation completes, and copies production’s database into it. Later pushes update and redeploy it. When the pull request is closed or merged, the environment is deleted.

  • The new environment gets production’s configuration and variables, an empty database (the sync fills it) and no secrets. Set any secrets the app needs on the new environment.
  • Environment creation is asynchronous. GET /api/v3/organizations/{org}/applications/{app}/environments/{env} returns creationStatus: creating, then completed or failed. The workflow waits for completed before the sync.
  • The Sync Action passes with a warning if the platform refuses the sync, so the workflow checks its skipped output.
  • Pull requests from forks get no secrets, so both jobs skip them.
  • Each preview environment runs until it is deleted. Look for pr-* environments whose pull request is closed (for example after a failed cleanup run), and delete them.

On QuantGov, set the QUANT_BASE_URL variable to https://dash.quantgov.cloud/api/v3. The image tag starts with the compose service name (app here).

name: PR environment
on:
pull_request:
types: [opened, synchronize, reopened, closed]
permissions:
contents: read
concurrency:
group: quant-pr-${{ github.event.pull_request.number }}
cancel-in-progress: false # never cancel a run that may be deleting
env:
QUANT_BASE_URL: ${{ vars.QUANT_BASE_URL || 'https://dashboard.quantcdn.io/api/v3' }}
QUANT_APP: ${{ vars.QUANT_APPLICATION || github.event.repository.name }}
jobs:
deploy:
# Forks get no secrets: skip them. Closed PRs go to the cleanup job.
if: github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ${{ vars.RUNNER_TYPE || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- name: Initialize Quant Cloud # PR -> environment pr-<n>, image suffix pr-<n>
id: init
uses: quantcdn/quant-cloud-init-action@1bc52dca113ea1cb2f3d7dcb0edbc7859d76afaf # v4.0.1
with:
quant_organization: ${{ secrets.QUANT_ORGANIZATION }}
quant_api_key: ${{ secrets.QUANT_API_KEY }}
quant_application: ${{ env.QUANT_APP }}
base_url: ${{ env.QUANT_BASE_URL }}
- name: Build and push
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: .
platforms: ${{ vars.BUILD_PLATFORM || 'linux/arm64' }}
push: true
tags: ${{ steps.init.outputs.stripped_endpoint }}/${{ secrets.QUANT_ORGANIZATION }}/${{ steps.init.outputs.quant_application }}:app-${{ steps.init.outputs.image_suffix_clean }}
- name: Translate docker-compose.yml
id: compose
uses: quantcdn/quant-cloud-compose-action@3a06db471e3364db3e4691fd522b9c37346d0a19 # v4.0.0
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
compose_file: docker-compose.yml
image_suffix: ${{ steps.init.outputs.image_suffix_clean }}
base_url: ${{ env.QUANT_BASE_URL }}
- name: Create (cloned from production) or update
uses: quantcdn/quant-cloud-environment-action@936fe16373f3169fa15b61a9117ffa87b3996855 # v4.0.0
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
app_name: ${{ steps.init.outputs.quant_application }}
environment_name: ${{ steps.init.outputs.environment_name }}
operation: ${{ steps.init.outputs.environment_exists == 'true' && 'update' || 'create' }}
from_environment: production # used only when the environment is created
compose_spec: ${{ steps.compose.outputs.translated_compose }}
base_url: ${{ env.QUANT_BASE_URL }}
- name: Wait until the new environment is created
if: steps.init.outputs.environment_exists != 'true'
env:
QUANT_API_KEY: ${{ secrets.QUANT_API_KEY }}
ORG: ${{ secrets.QUANT_ORGANIZATION }}
APP: ${{ steps.init.outputs.quant_application }}
ENV_NAME: ${{ steps.init.outputs.environment_name }}
run: |
API="${QUANT_BASE_URL%/api/v3}/api/v3"
URL="$API/organizations/$ORG/applications/$APP/environments/$ENV_NAME"
for i in $(seq 1 40); do
STATUS=$(curl -fsS -H "Authorization: Bearer $QUANT_API_KEY" "$URL" | jq -r '.creationStatus // empty')
if [ "$STATUS" = "completed" ]; then exit 0; fi
if [ "$STATUS" = "failed" ]; then echo "::error::Environment creation failed"; exit 1; fi
echo "Waiting ($i/40): creationStatus=${STATUS:-unknown}"
sleep 15
done
echo "::error::Environment not created after 10 minutes"
exit 1
- name: Copy the production database (first run only)
id: sync
if: steps.init.outputs.environment_exists != 'true'
uses: quantcdn/quant-cloud-environment-sync-action@aeb054d52e2067ac7eb6694c07df2c4cde262c5f # v4.0.0
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
app_name: ${{ steps.init.outputs.quant_application }}
environment_name: ${{ steps.init.outputs.environment_name }} # the target
source: production
type: database
wait: true
base_url: ${{ env.QUANT_BASE_URL }}
- name: Fail if the sync was skipped
if: steps.sync.outputs.skipped == 'true'
run: |
echo "::error::Database sync skipped (see the warning above)"
exit 1
- name: Redeploy
if: steps.init.outputs.environment_exists == 'true'
uses: quantcdn/quant-cloud-environment-state-action@b1b75af5d772bb295bc067f225a7bb3a952bd7a1 # v4.0.1
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
application: ${{ steps.init.outputs.quant_application }}
environment: ${{ steps.init.outputs.environment_name }}
action: redeploy
base_url: ${{ env.QUANT_BASE_URL }}
cleanup:
if: github.event.action == 'closed' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- name: Delete the PR environment
uses: quantcdn/quant-cloud-environment-action@936fe16373f3169fa15b61a9117ffa87b3996855 # v4.0.0
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: ${{ secrets.QUANT_ORGANIZATION }}
app_name: ${{ env.QUANT_APP }}
environment_name: pr-${{ github.event.pull_request.number }}
operation: delete # succeeds if the environment is already gone
base_url: ${{ env.QUANT_BASE_URL }}