128 lines
4.0 KiB
YAML
128 lines
4.0 KiB
YAML
name: Deploy (stellaamor)
|
||
|
||
on:
|
||
push:
|
||
branches: [ "main" ]
|
||
|
||
jobs:
|
||
deploy:
|
||
runs-on: [ mainhost, docker ]
|
||
concurrency:
|
||
group: deploy-stellaamor
|
||
cancel-in-progress: false
|
||
|
||
env:
|
||
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||
SSH_USER: ${{ secrets.SSH_USER }}
|
||
SSH_KEY: ${{ secrets.SSH_KEY }}
|
||
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
|
||
|
||
APP_ROOT: /var/www/stellaamor
|
||
UPLOADS_DIR: uploads
|
||
KEEP_N: "5"
|
||
HEALTH_URL: https://stellaamor.com/
|
||
SERVICE_RELOAD: "systemctl reload apache2 || true"
|
||
|
||
steps:
|
||
- name: Checkout (pure git)
|
||
run: |
|
||
git init
|
||
git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY"
|
||
git fetch --depth=1 origin "$GITHUB_SHA"
|
||
git checkout -q "$GITHUB_SHA"
|
||
|
||
# Build only if package.json exists — run Node inside a throwaway container
|
||
- name: Build frontend (if present)
|
||
if: hashFiles('package.json') != ''
|
||
run: |
|
||
docker run --rm -v "$PWD:/app" -w /app node:20 bash -lc "
|
||
npm ci
|
||
npm run build
|
||
"
|
||
|
||
- name: Prepare release tarball
|
||
run: |
|
||
set -euo pipefail
|
||
REL="$(date -u +%Y%m%d-%H%M%SZ)-${{ github.sha }}"
|
||
echo "REL=$REL" >> $GITHUB_ENV
|
||
|
||
UPLOADS="${{ env.UPLOADS_DIR }}"
|
||
OUT="/tmp/${REL}.tar.gz"
|
||
|
||
# create tar OUTSIDE the repo dir, then move it into ./release
|
||
tar -czf "$OUT" \
|
||
--exclude-vcs \
|
||
--exclude='./node_modules' \
|
||
--exclude="./${UPLOADS}" \
|
||
--exclude='./release' \
|
||
.
|
||
|
||
mkdir -p release
|
||
mv "$OUT" "release/${REL}.tar.gz"
|
||
|
||
|
||
- name: Use host SSH key
|
||
run: |
|
||
mkdir -p ~/.ssh
|
||
chmod 700 ~/.ssh
|
||
# Symlink to the host’s deploy key (already readable by the runner)
|
||
ln -sf /home/gitea-runner/.ssh/deploy_stellaamor ~/.ssh/id_ed25519
|
||
echo "StrictHostKeyChecking no" >> ~/.ssh/config
|
||
chmod 600 ~/.ssh/id_ed25519
|
||
|
||
|
||
|
||
- name: Upload & activate atomically
|
||
run: |
|
||
set -euo pipefail
|
||
REL="${{ env.REL }}"
|
||
TAR="release/${REL}.tar.gz"
|
||
APP="${{ env.APP_ROOT }}"
|
||
SHARED="${APP}/shared"
|
||
RELEASES="${APP}/releases"
|
||
CUR="${APP}/current"
|
||
UPLOADS="${{ env.UPLOADS_DIR }}"
|
||
|
||
# ensure layout exists
|
||
ssh -i ~/.ssh/id_ed25519 ${SSH_USER}@${SSH_HOST} "
|
||
set -e
|
||
sudo install -d -o ${SSH_USER} -g ${SSH_USER} -m 755 ${RELEASES} ${SHARED} ${SHARED}/${UPLOADS}
|
||
"
|
||
|
||
# upload tar
|
||
scp -i ~/.ssh/id_ed25519 ${TAR} ${SSH_USER}@${SSH_HOST}:/tmp/${REL}.tar.gz
|
||
|
||
# unpack, link shared, flip symlink, reload, health check, prune
|
||
ssh -i ~/.ssh/id_ed25519 ${SSH_USER}@${SSH_HOST} '
|
||
set -euo pipefail
|
||
REL="'${REL}'"; APP="'${APP}'"; SHARED="'${SHARED}'"; RELEASES="'${RELEASES}'"; CUR="'${CUR}'"; UPLOADS="'${UPLOADS}'";
|
||
|
||
NEW="${RELEASES}/${REL}"
|
||
mkdir -p "${NEW}"
|
||
tar -xzf "/tmp/${REL}.tar.gz" -C "${NEW}"
|
||
rm -f "/tmp/${REL}.tar.gz"
|
||
|
||
rm -rf "${NEW}/${UPLOADS}"
|
||
ln -s "${SHARED}/${UPLOADS}" "${NEW}/${UPLOADS}"
|
||
|
||
if [ -f "${SHARED}/.env" ]; then ln -sf "${SHARED}/.env" "${NEW}/.env"; fi
|
||
|
||
printf "sha=%s\nbuilt_at=%s\n" "'${{ github.sha }}'" "$(date -u +%FT%TZ)" > "${NEW}/RELEASE"
|
||
|
||
PREV="$(readlink -f "${CUR}" || true)"
|
||
ln -sfn "${NEW}" "${CUR}"
|
||
|
||
'"${{ env.SERVICE_RELOAD }}"' >/dev/null 2>&1 || true
|
||
|
||
if command -v curl >/dev/null 2>&1; then
|
||
curl -fsS --max-time 5 "'"${{ env.HEALTH_URL }}"'" >/dev/null || {
|
||
echo "Health check failed, rolling back..."
|
||
[ -n "${PREV}" ] && ln -sfn "${PREV}" "${CUR}" && '"${{ env.SERVICE_RELOAD }}"' >/dev/null 2>&1 || true
|
||
exit 1
|
||
}
|
||
fi
|
||
|
||
cd "${RELEASES}"
|
||
ls -1tr | head -n -'${{ env.KEEP_N }}' | xargs -r -I{} rm -rf "{}"
|
||
'
|