name: 🚀 Deploy on: # Allow contributors to schedule manual deployments. # Permission to deploy can be restricted by requiring approval in environment configuration. workflow_dispatch: inputs: target_domain: description: "Deployment Domain" required: true default: "openfront.dev" type: choice options: - openfront.io - openfront.dev target_host: description: "Deployment Host" required: true default: "staging" type: choice options: - masters - staging - falk2 target_subdomain: description: "Deployment Subdomain" required: false default: "" type: string # Automatic deployment on push # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore push: branches: - "*" permissions: {} concurrency: group: ${{ github.event_name == 'workflow_dispatch' && inputs.target_host || 'staging' }} cancel-in-progress: false jobs: deploy: # Don't deploy on push if this is a fork if: ${{ github.event_name == 'workflow_dispatch' || github.repository == 'openfrontio/OpenFrontIO' }} # Use different logic based on event type name: Deploy to ${{ inputs.target_domain || 'openfront.dev' }} runs-on: ubuntu-latest timeout-minutes: 30 environment: ${{ inputs.target_domain == 'openfront.io' && 'prod' || '' }} env: DOMAIN: ${{ inputs.target_domain || 'openfront.dev' }} SUBDOMAIN: ${{ github.event_name == 'push' && github.ref_name || inputs.target_subdomain || 'main' }} steps: - uses: actions/checkout@v5 - name: 📝 Update job summary env: FQDN: ${{ env.SUBDOMAIN && format('{0}.{1}', env.SUBDOMAIN, env.DOMAIN) || env.DOMAIN || 'openfront.dev' }} run: | echo "FQDN=$FQDN" >> $GITHUB_ENV cat <> $GITHUB_STEP_SUMMARY ### In progress :ship: Deploying from $GITHUB_REF to $FQDN EOF - uses: actions/create-github-app-token@v3 id: generate-token if: ${{ github.repository == 'openfrontio/OpenFrontIO' }} with: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - name: Export the token if: ${{ github.repository == 'openfrontio/OpenFrontIO' }} env: GH_TOKEN: ${{ steps.generate-token.outputs.token }} run: | echo "GH_TOKEN=$GH_TOKEN" >> $GITHUB_ENV gh api octocat - name: 📝 Create deployment if: ${{ github.repository == 'openfrontio/OpenFrontIO' && steps.generate-token.outputs.token != '' }} uses: actions/github-script@v8 id: deployment env: ENVIRONMENT: ${{ inputs.target_domain == 'openfront.io' && 'prod' || 'staging' }} FQDN: ${{ env.FQDN }} with: github-token: ${{ steps.generate-token.outputs.token }} script: | const response = await github.rest.repos.createDeployment({ owner: context.repo.owner, repo: context.repo.repo, ref: process.env.GITHUB_SHA, environment: process.env.ENVIRONMENT, description: 'Deployment to ' + process.env.FQDN, auto_merge: false, required_contexts: [], transient_environment: process.env.ENVIRONMENT === 'staging' && context.ref !== 'refs/heads/main', production_environment: process.env.ENVIRONMENT === 'prod' }); const deployment = response.data; if (!deployment || !deployment.id) { core.setFailed('Failed to create deployment'); return; } core.setOutput('deployment_id', deployment.id); - name: 🔗 Log in to GHCR uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ vars.GHCR_USERNAME }} password: ${{ secrets.GHCR_TOKEN }} - name: 🔑 Create SSH private key env: SERVER_HOST_MASTERS: ${{ secrets.SERVER_HOST_MASTERS }} SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | set -euxo pipefail mkdir -p ~/.ssh echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa test -n "$SERVER_HOST_MASTERS" && ssh-keyscan -H "$SERVER_HOST_MASTERS" >> ~/.ssh/known_hosts test -n "$SERVER_HOST_FALK2" && ssh-keyscan -H "$SERVER_HOST_FALK2" >> ~/.ssh/known_hosts test -n "$SERVER_HOST_STAGING" && ssh-keyscan -H "$SERVER_HOST_STAGING" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/id_rsa - name: 🚢 Deploy env: GHCR_REPO: ${{ vars.GHCR_REPO }} GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} ENV: ${{ inputs.target_domain == 'openfront.io' && 'prod' || 'staging' }} HOST: ${{ github.event_name == 'workflow_dispatch' && inputs.target_host || 'staging' }} OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }} OTEL_AUTH_HEADER: ${{ secrets.OTEL_AUTH_HEADER }} TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }} API_KEY: ${{ secrets.API_KEY }} SERVER_HOST_MASTERS: ${{ secrets.SERVER_HOST_MASTERS }} SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }} SSH_KEY: ~/.ssh/id_rsa VERSION_TAG: latest run: | echo "::group::deploy.sh" ./build-deploy.sh "$ENV" "$HOST" "$SUBDOMAIN" echo "Deployment created in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::" - name: ⏳ Wait for deployment to start env: API_KEY: ${{ secrets.API_KEY }} run: | echo "::group::Wait for deployment to start" set -euxo pipefail while [ "$(curl -s -H "X-API-Key: ${API_KEY}" https://${FQDN}/commit.txt)" != "${GITHUB_SHA}" ]; do if [ "$SECONDS" -ge 300 ]; then echo "Timeout: deployment did not start within 5 minutes" exit 1 fi sleep 10 done echo "Deployment started in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::" - name: 🔄 Update deployment status if: ${{ always() && github.repository == 'openfrontio/OpenFrontIO' && steps.generate-token.outputs.token != '' && steps.deployment.outcome == 'success' && steps.deployment.outputs.deployment_id != '' }} uses: actions/github-script@v8 env: FQDN: ${{ env.FQDN }} DEPLOYMENT_ID: ${{ steps.deployment.outputs.deployment_id }} STATUS: ${{ job.status }} with: github-token: ${{ steps.generate-token.outputs.token }} script: | await github.rest.repos.createDeploymentStatus({ owner: context.repo.owner, repo: context.repo.repo, deployment_id: process.env.DEPLOYMENT_ID, state: process.env.STATUS === 'success' ? 'success' : 'failure', environment_url: 'https://' + process.env.FQDN }); - name: ✅ Update job summary if: success() run: | cat <> $GITHUB_STEP_SUMMARY ### Success! :rocket: Deployed from $GITHUB_REF to $FQDN EOF - name: ❌ Update job summary if: failure() run: | cat <> $GITHUB_STEP_SUMMARY ### Failure! :fire: Unable to deploy from $GITHUB_REF to $FQDN EOF