Files
testprojekt/build/workflows/deploy.yml

168 lines
4.9 KiB
YAML
Raw Normal View History

2026-04-06 16:49:17 -04:00
name: Deploy (yggdrasil)
on:
push:
branches: ["main"]
jobs:
deploy:
runs-on: [ mainhost ]
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
SSH_KEY_PATH: /home/gitea-runner/.ssh/id_ed25519
SSH_OPTS: >-
-F /dev/null
-o IdentitiesOnly=yes
-o IdentityAgent=none
-o PreferredAuthentications=publickey
-o PubkeyAuthentication=yes
-o PasswordAuthentication=no
-o NumberOfPasswordPrompts=0
-o BatchMode=yes
-o ServerAliveInterval=15
-o ServerAliveCountMax=3
-o ConnectTimeout=20
-o StrictHostKeyChecking=no
APP_ROOT: /var/www/yggdrasil
KEEP_N: "5"
SHARED_DIRS: "uploads:cache"
HEALTH_URL: "https://yggdrasil.corpintech.net/"
SERVICE_NAME: "apache2"
steps:
- name: Checkout (pure git, private repo)
env:
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
run: |
set -euo pipefail
export GIT_TERMINAL_PROMPT=0
git init -b main
git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
git -c http.extraHeader="Authorization: token ${GIT_TOKEN}" \
fetch --no-tags --depth=1 origin "${GITHUB_SHA}"
git checkout -q "${GITHUB_SHA}"
- name: SSH smoke test
run: |
set -euo pipefail
ssh $SSH_OPTS -i "$SSH_KEY_PATH" "${SSH_USER}@${SSH_HOST}" true
- name: Deploy atomically
run: |
set -euo pipefail
REL="$(date -u +%Y%m%d-%H%M%SZ)-${GITHUB_SHA}"
TAR_LOCAL="release/${REL}.tar.gz"
mkdir -p release
IFS=':' read -r -a SHARED_DIR_ARR <<< "${SHARED_DIRS}"
EXCLUDES=(--exclude-vcs --exclude='./node_modules' --exclude='./release')
for d in "${SHARED_DIR_ARR[@]}"; do
EXCLUDES+=( "--exclude=./${d}" )
done
tar -czf "${TAR_LOCAL}" "${EXCLUDES[@]}" .
ssh $SSH_OPTS -i "$SSH_KEY_PATH" "${SSH_USER}@${SSH_HOST}" \
"set -e;
install -d -m 2755 '${APP_ROOT}' '${APP_ROOT}/releases' '${APP_ROOT}/shared' '${APP_ROOT}/logs';"
for d in "${SHARED_DIR_ARR[@]}"; do
ssh $SSH_OPTS -i "$SSH_KEY_PATH" "${SSH_USER}@${SSH_HOST}" \
"install -d -m 2755 '${APP_ROOT}/shared/${d}'"
done
scp -O $SSH_OPTS -i "$SSH_KEY_PATH" "${TAR_LOCAL}" "${SSH_USER}@${SSH_HOST}:/tmp/${REL}.tar.gz"
ssh $SSH_OPTS -i "$SSH_KEY_PATH" "${SSH_USER}@${SSH_HOST}" bash -s -- \
"${APP_ROOT}" \
"${REL}" \
"${KEEP_N}" \
"${SHARED_DIRS}" \
"${HEALTH_URL}" \
"${SERVICE_NAME}" \
"${GITHUB_SHA}" <<'REMOTE'
set -euo pipefail
APP_ROOT="$1"
REL="$2"
KEEP_N="$3"
SHARED_DIRS="$4"
HEALTH_URL="$5"
SERVICE_NAME="$6"
GITSHA="$7"
IFS=':' read -r -a SHARED_DIR_ARR <<< "${SHARED_DIRS}"
RELEASES="${APP_ROOT}/releases"
SHARED="${APP_ROOT}/shared"
CUR="${APP_ROOT}/current"
NEW="${RELEASES}/${REL}"
TAR="/tmp/${REL}.tar.gz"
echo "--> Extracting ${REL}"
mkdir -p "${NEW}"
tar -xzf "${TAR}" -C "${NEW}"
rm -f "${TAR}"
echo "--> Linking shared dirs"
for d in "${SHARED_DIR_ARR[@]}"; do
echo " ${d}"
rm -rf "${NEW:?}/${d}"
ln -s "${SHARED}/${d}" "${NEW}/${d}"
done
if [ -f "${SHARED}/.env" ]; then
ln -sf "${SHARED}/.env" "${NEW}/.env"
fi
printf "sha=%s\nbuilt_at=%s\n" "${GITSHA}" "$(date -u +%FT%TZ)" > "${NEW}/RELEASE"
PREV="$(readlink -f "${CUR}" 2>/dev/null || true)"
echo "--> Swapping symlink"
ln -sfn "${NEW}" "${CUR}"
echo "--> Restarting Apache"
sudo /usr/bin/systemctl restart "${SERVICE_NAME}"
if command -v curl >/dev/null 2>&1; then
echo "--> Health check ${HEALTH_URL}"
if ! curl -fsS --max-time 10 "${HEALTH_URL}" >/dev/null; then
echo "Health check failed, rolling back..."
if [ -n "${PREV}" ] && [ -e "${PREV}" ]; then
ln -sfn "${PREV}" "${CUR}"
sudo /usr/bin/systemctl restart "${SERVICE_NAME}"
fi
exit 1
fi
fi
echo "--> Cleaning old releases"
CUR_REAL="$(readlink -f "${CUR}" 2>/dev/null || true)"
cd "${RELEASES}"
i=0
for name in $(ls -1t); do
path="${RELEASES}/${name}"
if [ "${path}" = "${CUR_REAL}" ] || [ "${path}" = "${PREV}" ] || [ "${path}" = "${NEW}" ]; then
continue
fi
i=$((i+1))
if [ "${i}" -gt "${KEEP_N}" ]; then
rm -rf -- "${path}"
fi
done
echo "--> Deploy complete"
REMOTE