Skip to content

Exam mode: Enable students to participate in the test exam multiple times #7928

Exam mode: Enable students to participate in the test exam multiple times

Exam mode: Enable students to participate in the test exam multiple times #7928

Workflow file for this run

name: Deploy to Testserver
on:
pull_request:
types: [labeled]
concurrency: test-servers
env:
RAW_URL: https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}
jobs:
# Get an up to date version of the label list. github.event.pull_request.labels seems to sometimes be outdated
# if the run was waiting for a while, which can cause duplicate deployments
get-labels:
runs-on: ubuntu-latest
outputs:
labels: ${{ steps.get-labels.outputs.result }}
steps:
- name: Get PR labels
id: get-labels
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const response = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
})
const labels = response.data
return labels.map(label => label.name)
# Check that the build job has run successfully before deploying
check-build-status:
needs: [ get-labels ]
runs-on: ubuntu-latest
# Only run workflow if the added label is a deploy label
if: contains(needs.get-labels.outputs.labels, 'deploy:artemis-test')
steps:
- name: Get latest successful build for branch
id: check_build
uses: octokit/request-action@v2.x
with:
route: GET /repos/${{ github.repository }}/actions/workflows/build.yml/runs?event=pull_request&status=success&head_sha=${{ github.event.pull_request.head.sha }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Remove deployment-error label if new run is started
- uses: actions-ecosystem/action-remove-labels@v1
if: fromJSON(steps.check_build.outputs.data).total_count > 0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: |
deployment-error
# In case of invalid build status, remove deploy labels
- uses: actions-ecosystem/action-remove-labels@v1
if: fromJSON(steps.check_build.outputs.data).total_count == 0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: |
deploy:artemis-test1
deploy:artemis-test2
deploy:artemis-test3
deploy:artemis-test4
deploy:artemis-test5
deploy:artemis-test6
deploy:artemis-test7
deploy:artemis-test8
deploy:artemis-test9
deploy:artemis-test10
- name: Check if latest push had successful build
if: fromJSON(steps.check_build.outputs.data).total_count == 0
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '### ⚠️ Unable to deploy to test servers ⚠️\nThe docker build needs to run through before deploying.'
})
core.setFailed('The build needs to run through first. Please wait for the build to finish and then try again.')
# Check which test server to deploy to based on the label
filter-matrix:
needs: [ get-labels, check-build-status ]
runs-on: ubuntu-latest
strategy:
matrix:
include:
# Commented out environments are not yet available and will be enabled in the future
- environment: artemis-test1.artemis.cit.tum.de
label-identifier: artemis-test1
url: https://artemis-test1.artemis.cit.tum.de
user: deployment
hosts: artemis-test1.artemis.cit.tum.de
folder: /opt/artemis
- environment: artemis-test2.artemis.cit.tum.de
label-identifier: artemis-test2
url: https://artemis-test2.artemis.cit.tum.de
user: deployment
hosts: artemis-test2.artemis.cit.tum.de
folder: /opt/artemis
- environment: artemis-test3.artemis.cit.tum.de
label-identifier: artemis-test3
url: https://artemis-test3.artemis.cit.tum.de
user: deployment
hosts: artemis-test3.artemis.cit.tum.de
folder: /opt/artemis
- environment: artemis-test4.artemis.cit.tum.de
label-identifier: artemis-test4
url: https://artemis-test4.artemis.cit.tum.de
user: deployment
hosts: artemis-test4.artemis.cit.tum.de
folder: /opt/artemis
- environment: artemis-test5.artemis.cit.tum.de
label-identifier: artemis-test5
url: https://artemis-test5.artemis.cit.tum.de
user: deployment
hosts: artemis-test5.artemis.cit.tum.de
folder: /opt/artemis
- environment: artemis-test6.artemis.cit.tum.de
label-identifier: artemis-test6
url: https://artemis-test6.artemis.cit.tum.de
user: deployment
hosts: artemis-test6.artemis.cit.tum.de
folder: /opt/artemis
host_keys: |
#- environment: artemis-test7.artemis.cit.tum.de
# label-identifier: artemis-test7
# url: https://artemis-test7.artemis.cit.tum.de
# user: deployment
# hosts: artemis-test7.artemis.cit.tum.de
# folder: /opt/artemis
#- environment: artemis-test8.artemis.cit.tum.de
# label-identifier: artemis-test8
# url: https://artemis-test8.artemis.cit.tum.de
# user: deployment
# hosts: artemis-test8.artemis.cit.tum.de
# folder: /opt/artemis
- environment: artemis-test9.artemis.cit.tum.de
label-identifier: artemis-test9
url: https://artemis-test9.artemis.cit.tum.de
user: deployment
hosts: artemis-test9.artemis.cit.tum.de
folder: /opt/artemis
host_keys: |
#- environment: artemis-test10.artemis.cit.tum.de
# label-identifier: artemis-test10
# url: https://artemis-test10.artemis.cit.tum.de
# user: deployment
# hosts: artemis-test10.artemis.cit.tum.de
# folder: /opt/artemis
outputs:
TS1: ${{ steps.filter.outputs.artemis-test1 || '' }}
TS2: ${{ steps.filter.outputs.artemis-test2 || '' }}
TS3: ${{ steps.filter.outputs.artemis-test3 || '' }}
TS4: ${{ steps.filter.outputs.artemis-test4 || '' }}
TS5: ${{ steps.filter.outputs.artemis-test5 || '' }}
TS6: ${{ steps.filter.outputs.artemis-test6 || '' }}
#TS7: ${{ steps.filter.outputs.artemis-test7 || '' }}
#TS8: ${{ steps.filter.outputs.artemis-test8 || '' }}
TS9: ${{ steps.filter.outputs.artemis-test9 || '' }}
#TS10: ${{ steps.filter.outputs.artemis-test10 || '' }}
steps:
- run: |
echo "$DEPLOY_LABEL"
echo '${{ contains(fromJSON(needs.get-labels.outputs.labels), format('deploy:{0}', matrix.label-identifier)) }}'
- id: filter
env:
MATRIX_JSON: ${{ toJSON(matrix) }}
if: ${{ contains(fromJSON(needs.get-labels.outputs.labels), format('deploy:{0}', matrix.label-identifier)) }}
run: |
MATRIX_JSON=${MATRIX_JSON//$'\n'/}
echo "${{ matrix.label-identifier }}=$MATRIX_JSON" >> $GITHUB_OUTPUT
# Process the output of the filter step to create a valid matrix for the deploy step
process-matrix:
needs: [ filter-matrix ]
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.process.outputs.matrix }}
steps:
- id: process
env:
MATRIX_JSON: ${{ toJSON(needs.filter-matrix.outputs.*) }}
run: |
MATRIX_JSON=${MATRIX_JSON//$'\n'/}
MATRIX_JSON=${MATRIX_JSON//$'"{'/'{'}
MATRIX_JSON=${MATRIX_JSON//$'}"'/'}'}
MATRIX_JSON=${MATRIX_JSON//$'\\"'/'"'}
echo "$MATRIX_JSON"
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
# Deploy to the test servers
deploy:
needs: [ process-matrix ]
runs-on: ubuntu-latest
concurrency: test-servers-deploy
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.process-matrix.outputs.matrix) }}
environment:
name: ${{ matrix.environment }}
url: ${{ matrix.url }}
env:
DEPLOYMENT_USER: ${{ matrix.user }}
DEPLOYMENT_HOSTS: ${{ matrix.hosts }}
DEPLOYMENT_FOLDER: ${{ matrix.folder }}
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:
- uses: actions-ecosystem/action-remove-labels@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: |
deploy:${{ matrix.label-identifier }}
- name: Check "lock:${{ matrix.environment }}" label
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const opts = github.rest.issues.listForRepo.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['lock:${{ matrix.label-identifier }}']
})
const issues = await github.paginate(opts)
if (issues.length == 1 && (!context.issue || issues[0].number != context.issue.number)) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `#### ⚠️ Unable to deploy to test servers ⚠️\nTestserver "${{ matrix.environment }}" is already in use by PR #${issues[0].number}.`
})
core.setFailed(`Testserver "${{ matrix.environment }}" is already in use by PR #${issues[0].number}.`);
} else if (issues.length > 1) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '#### ⚠️ Unable to deploy to test servers ⚠️\nTestserver "${{ matrix.environment }}" is already in use by multiple PRs. Check PRs with label "lock:${{ matrix.label-identifier }}"!'
})
core.setFailed('Testserver "${{ matrix.environment }}" is already in use by multiple PRs. Check PRs with label "lock:${{ matrix.label-identifier }}"!');
}
- name: Compute Tag
uses: actions/github-script@v7
id: compute-tag
with:
result-encoding: string
script: |
if (context.eventName === "pull_request") {
return "pr-" + context.issue.number;
}
if (context.eventName === "release") {
return "latest";
}
if (context.eventName === "push") {
if (context.ref.startsWith("refs/tags/")) {
return context.ref.slice(10);
}
if (context.ref === "refs/heads/develop") {
return "develop";
}
}
return "FALSE";
# 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
TAG: ${{ steps.compute-tag.outputs.result }}
run: |
for host in $DEPLOYMENT_HOSTS; do
./artemis-server-cli docker-deploy "$DEPLOYMENT_USER@$host" -g "$GATEWAY_USER@$GATEWAY_HOST" -t $TAG -b $GITHUB_HEAD_REF -d $DEPLOYMENT_FOLDER -y
done
- name: Add "lock:${{ matrix.environment }}" label
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
if (context.issue && context.issue.number) {
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['lock:${{ matrix.label-identifier }}']
})
}
- name: Update badge
uses: RubbaBoy/BYOB@v1.3.0
with:
NAME: ${{ matrix.label-identifier }}
LABEL: ${{ matrix.environment }}
STATUS: ${{ github.event.pull_request.head.ref }}
COLOR: red
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Check that the build job has run successfully before deploying
add-error-label:
needs: [ get-labels, check-build-status, filter-matrix, process-matrix, deploy ]
runs-on: ubuntu-latest
if: ${{ failure() }}
steps:
- name: Add error label
uses: actions-ecosystem/action-add-labels@v1
with:
labels: deployment-error