Files
OpenFrontIO/.github/workflows/deploy.yml
T
VariableVince 8e6c0c1132 Chore:Deprecation of Node 20: migrate actions in workflows to Node 24 versions (#3460)
## Description:

Node 20 will reach EOL in April 2026. Node.js 20 actions are deprecated
and will be forced to run on Node.js 24 starting June 2, 2026:
https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Update our workflows in this PR.

- For _deployment-action_ and _deployment-status_: stop using these and
. They seem quite unmaintained which could pose risks and there is no
Node 24 version yet:
https://github.com/chrnorm/deployment-action/issues/93 and
https://github.com/chrnorm/deployment-status/issues/53. It will probably
be updated to Node 24, but why wait if we don't actually need to be
dependent on them per se.

- Instead of the above, use actions/github-script@v8 with default API.
Maybe a bit more maintainance work, if any, but better than to be
dependent on unmaintained outside actions. For reference see
https://docs.github.com/en/rest/deployments/deployments?apiVersion=2026-03-10#create-a-deployment

- For _auto-author-assign_, use v3.0.1
(4d585cc37690897bd9015942ed6e766aa7cdb97f). From v3.0.0 it uses Node 24:
https://github.com/toshimaru/auto-author-assign/releases

- For _stale_, use v10.2.0 (b5d41d4e1d5dceea10e7104786b73624c18a190f).
From v10.0.0 it uses Node 24: https://github.com/actions/stale/releases

- For other actions, use their appropriate version for Node 24.

- Tested all with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

tryout33
2026-03-19 21:32:32 -07:00

199 lines
7.9 KiB
YAML

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
- falk1
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 <<EOF >> $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_FALK1: ${{ secrets.SERVER_HOST_FALK1 }}
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_FALK1" && ssh-keyscan -H "$SERVER_HOST_FALK1" >> ~/.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:
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
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_FALK1: ${{ secrets.SERVER_HOST_FALK1 }}
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
run: |
echo "::group::Wait for deployment to start"
set -euxo pipefail
while [ "$(curl -s 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 <<EOF >> $GITHUB_STEP_SUMMARY
### Success! :rocket:
Deployed from $GITHUB_REF to $FQDN
EOF
- name: ❌ Update job summary
if: failure()
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
### Failure! :fire:
Unable to deploy from $GITHUB_REF to $FQDN
EOF