Integrated code lifecycle
: Improve reinitialization when pausing build agents
#12947
Workflow file for this run
This file contains 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 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 | |
host_keys: | | |
#- 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 |