This commit is contained in:
134
.gitea/workflows/deploy.yml
Normal file
134
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
name: Deploy (stellaamor)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ] # change if you use main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: [ self-hosted, mainhost, docker ]
|
||||||
|
concurrency:
|
||||||
|
group: deploy-stellaamor
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
# ---- required (set these as repo/org SECRETS) ----
|
||||||
|
SSH_HOST: ${{ secrets.SSH_HOST }} # e.g. 192.168.122.50 (the stellaamor VM)
|
||||||
|
SSH_USER: ${{ secrets.SSH_USER }} # e.g. deploy
|
||||||
|
SSH_KEY: ${{ secrets.SSH_KEY }} # private key (ed25519), one line
|
||||||
|
# optional but recommended: known_hosts entry for your VM
|
||||||
|
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
|
||||||
|
|
||||||
|
# ---- repo-scoped settings (safe to commit) ----
|
||||||
|
APP_ROOT: /var/www/stellaamor # base dir on the VM
|
||||||
|
UPLOADS_DIR: uploads # relative to shared/
|
||||||
|
KEEP_N: "5" # how many releases to keep
|
||||||
|
HEALTH_URL: https://stellaamor.com/ # simple GET should return 200
|
||||||
|
SERVICE_RELOAD: "systemctl reload apache2 || true"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# only build assets if you actually have a package.json with build script
|
||||||
|
- name: Maybe build frontend (Vue/etc)
|
||||||
|
if: hashFiles('package.json') != ''
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
- name: npm ci
|
||||||
|
if: hashFiles('package.json') != ''
|
||||||
|
run: npm ci
|
||||||
|
- name: npm build
|
||||||
|
if: hashFiles('package.json') != ''
|
||||||
|
run: 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
|
||||||
|
|
||||||
|
mkdir -p release
|
||||||
|
# include everything except VCS, node dev dirs, and your uploads (they live in shared/)
|
||||||
|
tar \
|
||||||
|
--exclude-vcs \
|
||||||
|
--exclude='./node_modules' \
|
||||||
|
--exclude='./${{ env.UPLOADS_DIR }}' \
|
||||||
|
-czf "release/${REL}.tar.gz" \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Write SSH key
|
||||||
|
run: |
|
||||||
|
umask 077
|
||||||
|
printf "%s" "${SSH_KEY}" > ~/.ssh/id_ed25519
|
||||||
|
if [ -n "${SSH_KNOWN_HOSTS}" ]; then
|
||||||
|
printf "%s\n" "${SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
|
||||||
|
else
|
||||||
|
# fall back only if you must (less secure)
|
||||||
|
echo "StrictHostKeyChecking no" >> ~/.ssh/config
|
||||||
|
fi
|
||||||
|
|
||||||
|
- 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"
|
||||||
|
|
||||||
|
# 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}
|
||||||
|
sudo install -d -o ${SSH_USER} -g ${SSH_USER} -m 755 ${SHARED}/${{ env.UPLOADS_DIR }}
|
||||||
|
"
|
||||||
|
|
||||||
|
# upload tar
|
||||||
|
scp -i ~/.ssh/id_ed25519 ${TAR} ${SSH_USER}@${SSH_HOST}:/tmp/${REL}.tar.gz
|
||||||
|
|
||||||
|
# unpack to new release, link shared, write metadata, flip symlink, reload, health check
|
||||||
|
ssh -i ~/.ssh/id_ed25519 ${SSH_USER}@${SSH_HOST} '
|
||||||
|
set -euo pipefail
|
||||||
|
REL="'${REL}'"; APP="'${APP}'"; SHARED="'${SHARED}'"; RELEASES="'${RELEASES}'"; CUR="'${CUR}'";
|
||||||
|
|
||||||
|
NEW="${RELEASES}/${REL}"
|
||||||
|
mkdir -p "${NEW}"
|
||||||
|
tar -xzf "/tmp/${REL}.tar.gz" -C "${NEW}"
|
||||||
|
rm -f "/tmp/${REL}.tar.gz"
|
||||||
|
|
||||||
|
# link shared paths (uploads, env/config if you keep one there)
|
||||||
|
rm -rf "${NEW}/${UPLOADS_DIR:-'${{ env.UPLOADS_DIR }}'}"
|
||||||
|
ln -s "${SHARED}/${UPLOADS_DIR:-'${{ env.UPLOADS_DIR }}'}" "${NEW}/${UPLOADS_DIR:-'${{ env.UPLOADS_DIR }}'}"
|
||||||
|
|
||||||
|
# optional: link a shared .env if you use one
|
||||||
|
if [ -f "${SHARED}/.env" ]; then
|
||||||
|
ln -sf "${SHARED}/.env" "${NEW}/.env"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# metadata
|
||||||
|
printf "sha=%s\nbuilt_at=%s\n" "'${{ github.sha }}'" "$(date -u +%FT%TZ)" > "${NEW}/RELEASE"
|
||||||
|
|
||||||
|
# keep previous target for rollback
|
||||||
|
PREV="$(readlink -f "${CUR}" || true)"
|
||||||
|
ln -sfn "${NEW}" "${CUR}"
|
||||||
|
|
||||||
|
# reload services
|
||||||
|
'"${{ env.SERVICE_RELOAD }}"' >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# health check (simple GET)
|
||||||
|
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
|
||||||
|
|
||||||
|
# prune old releases
|
||||||
|
cd "${RELEASES}"
|
||||||
|
ls -1tr | head -n -'${{ env.KEEP_N }}' | xargs -r -I{} rm -rf "{}"
|
||||||
|
'
|
||||||
|
|
||||||
Reference in New Issue
Block a user