Files
Goldebek/.gitea/workflows/deploy.yml
T
Per Hoener 0d45331f5c
Deploy / validate-dispatch (push) Successful in 43s
Deploy / scheduled-rebuild-dev (push) Skipped
Deploy / scheduled-rebuild-master (push) Skipped
Deploy / rollback-dev (push) Skipped
Deploy / rollback-master (push) Skipped
Deploy / changes (push) Successful in 13s
Deploy / secret-scan (push) Successful in 9s
Deploy / app-quality (push) Successful in 11m21s
Deploy / security-deps (push) Successful in 14s
Deploy / context (push) Failing after 1s
Deploy / app-image (push) Skipped
Deploy / deploy-dev (push) Skipped
Deploy / deploy-master (push) Skipped
Initial commit
2026-09-18 23:37:19 +02:00

628 lines
23 KiB
YAML

name: Deploy
permissions:
contents: read
concurrency:
group: website-starter-deploy-${{ github.event_name == 'schedule' && 'scheduled' || github.event.inputs.rollback_target || github.ref_name }}
cancel-in-progress: false
on:
push:
branches:
- dev
- master
workflow_dispatch:
inputs:
rollback_target:
description: "Rollback target: dev or master. Leave empty for a normal manual deploy."
required: false
app_image_tag:
description: "Next app image tag for rollback."
required: false
schedule:
- cron: "17 3 * * 1"
env:
DOCKER_BUILDKIT: 1
NODE_VERSION_FILE: .node-version
TRIVY_IMAGE: aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969
REGISTRY: ${{ vars.CONTAINER_REGISTRY }}
APP_IMAGE_REPOSITORY: ${{ vars.APP_IMAGE_REPOSITORY }}
APP_NAME: ${{ vars.APP_NAME }}
COMPANY_NAME: ${{ vars.COMPANY_NAME }}
CONTACT_EMAIL: ${{ vars.CONTACT_EMAIL }}
CONTACT_PHONE: ${{ vars.CONTACT_PHONE }}
CONTACT_ADDRESS: ${{ vars.CONTACT_ADDRESS }}
jobs:
validate-dispatch:
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 5
steps:
- name: Validate workflow dispatch inputs
env:
EVENT_NAME: ${{ github.event_name }}
REF_NAME: ${{ github.ref_name }}
ROLLBACK_TARGET: ${{ github.event.inputs.rollback_target }}
APP_IMAGE_TAG: ${{ github.event.inputs.app_image_tag }}
run: |
set -eu
if [ "$EVENT_NAME" != "workflow_dispatch" ]; then
exit 0
fi
fail() {
echo "$1" >&2
exit 1
}
validate_tag() {
key="$1"
value="$2"
case "$value" in
[A-Za-z0-9_]* ) ;;
*) fail "Invalid Docker image tag for $key." ;;
esac
case "$value" in
*[!A-Za-z0-9_.-]* ) fail "Invalid Docker image tag for $key." ;;
esac
if [ "${#value}" -gt 128 ]; then
fail "Docker image tag for $key exceeds 128 characters."
fi
}
case "$REF_NAME" in
dev|master) ;;
*) fail "Manual deployments must be dispatched from dev or master." ;;
esac
if [ -z "$ROLLBACK_TARGET" ]; then
if [ -n "$APP_IMAGE_TAG" ]; then
fail "Image tags require rollback_target."
fi
exit 0
fi
case "$ROLLBACK_TARGET" in
dev|master) ;;
*) fail "rollback_target must be dev or master." ;;
esac
if [ "$ROLLBACK_TARGET" != "$REF_NAME" ]; then
fail "rollback_target must match the dispatched branch."
fi
validate_tag APP_IMAGE_TAG "$APP_IMAGE_TAG"
changes:
if: github.event_name != 'schedule' && (github.event_name != 'workflow_dispatch' || github.event.inputs.rollback_target == '')
needs: [validate-dispatch]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 5
outputs:
deploy: ${{ steps.detect.outputs.deploy }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
fetch-depth: 0
- name: Detect changed areas
id: detect
env:
CHANGESET_BEFORE: ${{ github.event.before }}
run: sh scripts/detect-ci-changes.sh
app-quality:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true'
needs: [changes]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
APP_URL: https://example.com
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version-file: ${{ env.NODE_VERSION_FILE }}
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Restore and update image cache
env:
IMAGE_CACHE_NAMESPACE: ${{ github.ref_name }}
run: sh scripts/prepare-image-cache.sh
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Type check
run: npm run typecheck
- name: Build
env:
SKIP_IMAGE_OPTIMIZATION: true
run: npm run build
- name: E2E smoke test
env:
SKIP_IMAGE_OPTIMIZATION: true
run: npm run test:e2e
secret-scan:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true'
needs: [changes]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Scan repository for committed secrets
run: sh scripts/trivy-scan.sh secret-fs .
security-deps:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true'
needs: [changes]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Report app dependency vulnerabilities
run: sh scripts/trivy-scan.sh vuln-fs .
- name: Block high and critical app dependency vulnerabilities
env:
TRIVY_SEVERITY: HIGH,CRITICAL
TRIVY_EXIT_CODE: 1
run: sh scripts/trivy-scan.sh vuln-fs .
context:
if: >
needs.changes.outputs.deploy == 'true' &&
(
(github.event_name == 'push' &&
github.event.pull_request == null &&
(github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/master')) ||
(github.event_name == 'workflow_dispatch' &&
github.event.pull_request == null &&
(github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/master'))
)
needs: [changes]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 5
outputs:
environment_name: ${{ steps.resolve.outputs.environment_name }}
primary_domain: ${{ steps.resolve.outputs.primary_domain }}
app_url: ${{ steps.resolve.outputs.app_url }}
cors_origin: ${{ steps.resolve.outputs.cors_origin }}
deploy_stack_name: ${{ steps.resolve.outputs.deploy_stack_name }}
traefik_certresolver: ${{ steps.resolve.outputs.traefik_certresolver }}
traefik_network_name: ${{ steps.resolve.outputs.traefik_network_name }}
steps:
- name: Resolve deployment target
id: resolve
env:
REF_NAME: ${{ github.ref_name }}
DEV_PRIMARY_DOMAIN: ${{ vars.DEV_PRIMARY_DOMAIN }}
DEV_APP_URL: ${{ vars.DEV_APP_URL }}
DEV_CORS_ORIGIN: ${{ vars.DEV_CORS_ORIGIN }}
DEV_DEPLOY_STACK_NAME: ${{ vars.DEV_DEPLOY_STACK_NAME }}
DEV_TRAEFIK_CERTRESOLVER: ${{ secrets.DEV_TRAEFIK_CERTRESOLVER }}
DEV_TRAEFIK_NETWORK_NAME: ${{ vars.DEV_TRAEFIK_NETWORK_NAME }}
PROD_PRIMARY_DOMAIN: ${{ vars.PROD_PRIMARY_DOMAIN }}
PROD_APP_URL: ${{ vars.PROD_APP_URL }}
PROD_CORS_ORIGIN: ${{ vars.PROD_CORS_ORIGIN }}
PROD_DEPLOY_STACK_NAME: ${{ vars.PROD_DEPLOY_STACK_NAME }}
PROD_TRAEFIK_CERTRESOLVER: ${{ secrets.PROD_TRAEFIK_CERTRESOLVER }}
PROD_TRAEFIK_NETWORK_NAME: ${{ vars.PROD_TRAEFIK_NETWORK_NAME }}
run: |
set -eu
set_output() {
printf '%s=%s\n' "$1" "$2" >> "$GITHUB_OUTPUT"
}
require_value() {
key="$1"
value="$2"
if [ -z "$value" ]; then
echo "Missing required workflow configuration: $key" >&2
exit 1
fi
}
case "$REF_NAME" in
dev)
config_prefix="DEV"
environment_name="dev"
primary_domain="$DEV_PRIMARY_DOMAIN"
app_url="${DEV_APP_URL:-}"
cors_origin="${DEV_CORS_ORIGIN:-}"
deploy_stack_name="${DEV_DEPLOY_STACK_NAME:-website-starter-dev}"
traefik_certresolver="$DEV_TRAEFIK_CERTRESOLVER"
traefik_network_name="${DEV_TRAEFIK_NETWORK_NAME:-traefik-external}"
;;
master)
config_prefix="PROD"
environment_name="production"
primary_domain="$PROD_PRIMARY_DOMAIN"
app_url="${PROD_APP_URL:-}"
cors_origin="${PROD_CORS_ORIGIN:-}"
deploy_stack_name="${PROD_DEPLOY_STACK_NAME:-website-starter-prod}"
traefik_certresolver="$PROD_TRAEFIK_CERTRESOLVER"
traefik_network_name="${PROD_TRAEFIK_NETWORK_NAME:-traefik}"
;;
*)
echo "Branch $REF_NAME is not configured for deployment." >&2
exit 1
;;
esac
require_value "${config_prefix}_PRIMARY_DOMAIN" "$primary_domain"
require_value "${config_prefix}_TRAEFIK_CERTRESOLVER" "$traefik_certresolver"
if [ -z "$app_url" ]; then
app_url="https://$primary_domain"
fi
if [ -z "$cors_origin" ]; then
cors_origin="$app_url"
fi
set_output "environment_name" "$environment_name"
set_output "primary_domain" "$primary_domain"
set_output "app_url" "$app_url"
set_output "cors_origin" "$cors_origin"
set_output "deploy_stack_name" "$deploy_stack_name"
set_output "traefik_certresolver" "$traefik_certresolver"
set_output "traefik_network_name" "$traefik_network_name"
app-image:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true'
needs: [changes, context, app-quality, secret-scan, security-deps]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
APP_URL: ${{ needs.context.outputs.app_url }}
APP_IMAGE_NAME: ${{ env.APP_IMAGE_REPOSITORY }}:${{ github.ref_name }}-${{ github.sha }}-${{ github.run_id }}
APP_BRANCH_IMAGE_NAME: ${{ env.APP_IMAGE_REPOSITORY }}:${{ github.ref_name }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version-file: ${{ env.NODE_VERSION_FILE }}
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Restore and update image cache
env:
IMAGE_CACHE_NAMESPACE: ${{ github.ref_name }}
run: sh scripts/prepare-image-cache.sh
- name: Build app runtime image
run: |
docker build --pull \
--build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--build-arg VCS_REF="${{ github.sha }}" \
--build-arg APP_URL="$APP_URL" \
--build-arg APP_NAME="${APP_NAME:-Example Website}" \
--build-arg COMPANY_NAME="${COMPANY_NAME:-Example Company}" \
--build-arg CONTACT_EMAIL="${CONTACT_EMAIL:-info@example.com}" \
--build-arg CONTACT_PHONE="${CONTACT_PHONE:-+49 000 000000}" \
--build-arg CONTACT_ADDRESS="${CONTACT_ADDRESS:-Example Street 1, 12345 Example City}" \
--build-arg SOURCE_URL="${{ github.server_url }}/${{ github.repository }}" \
--build-arg SKIP_IMAGE_OPTIMIZATION=true \
--build-arg IMAGE_CACHE_NAMESPACE="${{ github.ref_name }}" \
-f Dockerfile \
-t "$APP_IMAGE_NAME" \
-t "$APP_BRANCH_IMAGE_NAME" \
.
- name: Report app runtime image vulnerabilities
run: sh scripts/trivy-scan.sh vuln-image "$APP_IMAGE_NAME"
- name: Block high and critical app runtime vulnerabilities
env:
TRIVY_SEVERITY: HIGH,CRITICAL
TRIVY_EXIT_CODE: 1
run: sh scripts/trivy-scan.sh vuln-image "$APP_IMAGE_NAME"
- name: Push app runtime image
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: |
set -eu
if [ -z "${REGISTRY_USERNAME:-}" ] || [ -z "${REGISTRY_TOKEN:-}" ]; then
echo "Missing required secrets: PACKAGES_USERNAME and PACKAGES_TOKEN" >&2
exit 1
fi
docker_config="$(mktemp -d)"
cleanup() {
DOCKER_CONFIG="$docker_config" docker logout "$REGISTRY" >/dev/null 2>&1 || true
rm -rf "$docker_config"
}
trap cleanup EXIT
trap 'exit 1' HUP INT TERM
export DOCKER_CONFIG="$docker_config"
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin
docker push "$APP_IMAGE_NAME"
docker push "$APP_BRANCH_IMAGE_NAME"
deploy-dev:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true' && github.ref == 'refs/heads/dev'
needs: [changes, context, app-quality, app-image, secret-scan, security-deps]
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ needs.context.outputs.primary_domain }}
APP_URL: ${{ needs.context.outputs.app_url }}
CORS_ORIGIN: ${{ needs.context.outputs.cors_origin }}
COMPOSE_PROJECT_NAME: ${{ needs.context.outputs.deploy_stack_name }}
TRAEFIK_STACK_NAME: ${{ needs.context.outputs.deploy_stack_name }}
TRAEFIK_CERTRESOLVER: ${{ needs.context.outputs.traefik_certresolver }}
TRAEFIK_NETWORK_NAME: ${{ needs.context.outputs.traefik_network_name }}
DEPLOY_TARGET: dev
APP_IMAGE_NAME: ${{ env.APP_IMAGE_REPOSITORY }}:dev-${{ github.sha }}-${{ github.run_id }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Pull app runtime image
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: |
set -eu
if [ -z "${REGISTRY_USERNAME:-}" ] || [ -z "${REGISTRY_TOKEN:-}" ]; then
echo "Missing required secrets: PACKAGES_USERNAME and PACKAGES_TOKEN" >&2
exit 1
fi
docker_config="$(mktemp -d)"
cleanup() {
DOCKER_CONFIG="$docker_config" docker logout "$REGISTRY" >/dev/null 2>&1 || true
rm -rf "$docker_config"
}
trap cleanup EXIT
trap 'exit 1' HUP INT TERM
export DOCKER_CONFIG="$docker_config"
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin
docker pull "$APP_IMAGE_NAME"
- name: Validate runtime configuration
run: |
if [ -z "${CALENDAR_URL:-}" ]; then
echo "Missing required secret: CALENDAR_URL" >&2
exit 1
fi
- name: Print deployment target
run: |
echo "Environment: ${{ needs.context.outputs.environment_name }}"
echo "Site host: $PRIMARY_DOMAIN"
echo "Compose project: $COMPOSE_PROJECT_NAME"
- name: Deploy and verify app
run: sh scripts/deploy-and-verify.sh
deploy-master:
if: github.event_name != 'schedule' && needs.changes.outputs.deploy == 'true' && github.ref == 'refs/heads/master'
needs: [changes, context, app-quality, app-image, secret-scan, security-deps]
runs-on: ${{ vars.PROD_RUNNER || vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ needs.context.outputs.primary_domain }}
APP_URL: ${{ needs.context.outputs.app_url }}
CORS_ORIGIN: ${{ needs.context.outputs.cors_origin }}
COMPOSE_PROJECT_NAME: ${{ needs.context.outputs.deploy_stack_name }}
TRAEFIK_STACK_NAME: ${{ needs.context.outputs.deploy_stack_name }}
TRAEFIK_CERTRESOLVER: ${{ needs.context.outputs.traefik_certresolver }}
TRAEFIK_NETWORK_NAME: ${{ needs.context.outputs.traefik_network_name }}
DEPLOY_TARGET: master
APP_IMAGE_NAME: ${{ env.APP_IMAGE_REPOSITORY }}:master-${{ github.sha }}-${{ github.run_id }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Pull app runtime image
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: |
set -eu
if [ -z "${REGISTRY_USERNAME:-}" ] || [ -z "${REGISTRY_TOKEN:-}" ]; then
echo "Missing required secrets: PACKAGES_USERNAME and PACKAGES_TOKEN" >&2
exit 1
fi
docker_config="$(mktemp -d)"
cleanup() {
DOCKER_CONFIG="$docker_config" docker logout "$REGISTRY" >/dev/null 2>&1 || true
rm -rf "$docker_config"
}
trap cleanup EXIT
trap 'exit 1' HUP INT TERM
export DOCKER_CONFIG="$docker_config"
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin
docker pull "$APP_IMAGE_NAME"
- name: Validate runtime configuration
run: |
if [ -z "${CALENDAR_URL:-}" ]; then
echo "Missing required secret: CALENDAR_URL" >&2
exit 1
fi
- name: Print deployment target
run: |
echo "Environment: ${{ needs.context.outputs.environment_name }}"
echo "Site host: $PRIMARY_DOMAIN"
echo "Compose project: $COMPOSE_PROJECT_NAME"
- name: Deploy and verify app
run: sh scripts/deploy-and-verify.sh
scheduled-rebuild-dev:
if: github.event_name == 'schedule'
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 45
env:
DEPLOY_TARGET: dev
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ vars.DEV_PRIMARY_DOMAIN }}
APP_URL: ${{ vars.DEV_APP_URL }}
CORS_ORIGIN: ${{ vars.DEV_CORS_ORIGIN }}
COMPOSE_PROJECT_NAME: ${{ vars.DEV_DEPLOY_STACK_NAME }}
TRAEFIK_STACK_NAME: ${{ vars.DEV_DEPLOY_STACK_NAME }}
TRAEFIK_CERTRESOLVER: ${{ secrets.DEV_TRAEFIK_CERTRESOLVER }}
TRAEFIK_NETWORK_NAME: ${{ vars.DEV_TRAEFIK_NETWORK_NAME }}
steps:
- name: Checkout dev branch
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
ref: dev
lfs: true
- name: Scan repository for committed secrets
run: sh scripts/trivy-scan.sh secret-fs .
- name: Report app dependency vulnerabilities
run: sh scripts/trivy-scan.sh vuln-fs .
- name: Block high and critical app dependency vulnerabilities
env:
TRIVY_SEVERITY: HIGH,CRITICAL
TRIVY_EXIT_CODE: 1
run: sh scripts/trivy-scan.sh vuln-fs .
- name: Rebuild latest base image and deploy dev
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: sh scripts/scheduled-rebuild-deploy.sh
scheduled-rebuild-master:
if: github.event_name == 'schedule'
runs-on: ${{ vars.PROD_RUNNER || vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 45
env:
DEPLOY_TARGET: master
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ vars.PROD_PRIMARY_DOMAIN }}
APP_URL: ${{ vars.PROD_APP_URL }}
CORS_ORIGIN: ${{ vars.PROD_CORS_ORIGIN }}
COMPOSE_PROJECT_NAME: ${{ vars.PROD_DEPLOY_STACK_NAME }}
TRAEFIK_STACK_NAME: ${{ vars.PROD_DEPLOY_STACK_NAME }}
TRAEFIK_CERTRESOLVER: ${{ secrets.PROD_TRAEFIK_CERTRESOLVER }}
TRAEFIK_NETWORK_NAME: ${{ vars.PROD_TRAEFIK_NETWORK_NAME }}
steps:
- name: Checkout master branch
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
ref: master
lfs: true
- name: Scan repository for committed secrets
run: sh scripts/trivy-scan.sh secret-fs .
- name: Report app dependency vulnerabilities
run: sh scripts/trivy-scan.sh vuln-fs .
- name: Block high and critical app dependency vulnerabilities
env:
TRIVY_SEVERITY: HIGH,CRITICAL
TRIVY_EXIT_CODE: 1
run: sh scripts/trivy-scan.sh vuln-fs .
- name: Rebuild latest base image and deploy master
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: sh scripts/scheduled-rebuild-deploy.sh
rollback-dev:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.rollback_target == 'dev' && github.ref == 'refs/heads/dev'
runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
DEPLOY_TARGET: dev
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ vars.DEV_PRIMARY_DOMAIN }}
APP_URL: ${{ vars.DEV_APP_URL }}
CORS_ORIGIN: ${{ vars.DEV_CORS_ORIGIN }}
COMPOSE_PROJECT_NAME: ${{ vars.DEV_DEPLOY_STACK_NAME }}
TRAEFIK_STACK_NAME: ${{ vars.DEV_DEPLOY_STACK_NAME }}
TRAEFIK_CERTRESOLVER: ${{ secrets.DEV_TRAEFIK_CERTRESOLVER }}
TRAEFIK_NETWORK_NAME: ${{ vars.DEV_TRAEFIK_NETWORK_NAME }}
APP_IMAGE_TAG: ${{ github.event.inputs.app_image_tag }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Deploy rollback and verify app
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: sh scripts/manual-rollback-deploy.sh
rollback-master:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.rollback_target == 'master' && github.ref == 'refs/heads/master'
runs-on: ${{ vars.PROD_RUNNER || vars.CI_RUNNER || 'ubuntu-latest' }}
timeout-minutes: 30
env:
DEPLOY_TARGET: master
CALENDAR_URL: ${{ secrets.CALENDAR_URL }}
PRIMARY_DOMAIN: ${{ vars.PROD_PRIMARY_DOMAIN }}
APP_URL: ${{ vars.PROD_APP_URL }}
CORS_ORIGIN: ${{ vars.PROD_CORS_ORIGIN }}
COMPOSE_PROJECT_NAME: ${{ vars.PROD_DEPLOY_STACK_NAME }}
TRAEFIK_STACK_NAME: ${{ vars.PROD_DEPLOY_STACK_NAME }}
TRAEFIK_CERTRESOLVER: ${{ secrets.PROD_TRAEFIK_CERTRESOLVER }}
TRAEFIK_NETWORK_NAME: ${{ vars.PROD_TRAEFIK_NETWORK_NAME }}
APP_IMAGE_TAG: ${{ github.event.inputs.app_image_tag }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
lfs: true
- name: Deploy rollback and verify app
env:
REGISTRY_USERNAME: ${{ secrets.PACKAGES_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
run: sh scripts/manual-rollback-deploy.sh