Compare commits
14 Commits
929b9b3090
...
feature/te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70bde90792 | ||
|
|
f7e691a24c | ||
|
|
1b4adde2bb | ||
|
|
9217a71d5a | ||
|
|
de11388a77 | ||
|
|
9ab5fb67a6 | ||
|
|
699caf348b | ||
|
|
9abdf38a8a | ||
|
|
0183f4d027 | ||
|
|
9d2cb407ff | ||
|
|
63ee007a48 | ||
|
|
adf6e3a5b2 | ||
|
|
936ff29f56 | ||
|
|
5589ebc7b7 |
@@ -6,22 +6,31 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: [ mainhost, docker ]
|
runs-on: [ mainhost ] # must match your runner label (e.g. mainhost:host)
|
||||||
concurrency:
|
|
||||||
group: deploy-stellaamor
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SSH_HOST: ${{ secrets.SSH_HOST }}
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
||||||
SSH_USER: ${{ secrets.SSH_USER }}
|
SSH_USER: ${{ secrets.SSH_USER }}
|
||||||
SSH_KEY: ${{ secrets.SSH_KEY }}
|
SSH_OPTS: >-
|
||||||
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
|
-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/stellaamor
|
APP_ROOT: /var/www/stellaamor
|
||||||
UPLOADS_DIR: uploads
|
UPLOADS_DIR: uploads
|
||||||
KEEP_N: "5"
|
KEEP_N: "5"
|
||||||
HEALTH_URL: https://stellaamor.com/
|
HEALTH_URL: https://stellaamor.com/
|
||||||
SERVICE_RELOAD: "systemctl reload apache2 || true"
|
SERVICE_RELOAD: "systemctl reload apache2 || true"
|
||||||
|
SSH_KEY_PATH: /home/gitea-runner/.ssh/id_ed25519
|
||||||
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (pure git)
|
- name: Checkout (pure git)
|
||||||
@@ -31,88 +40,41 @@ jobs:
|
|||||||
git fetch --depth=1 origin "$GITHUB_SHA"
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
||||||
git checkout -q "$GITHUB_SHA"
|
git checkout -q "$GITHUB_SHA"
|
||||||
|
|
||||||
# Build only if package.json exists — run Node inside a throwaway container
|
- name: SSH smoke test
|
||||||
- name: Build frontend (if present)
|
run: ssh $SSH_OPTS -i "$SSH_KEY_PATH" ${SSH_USER}@${SSH_HOST} true
|
||||||
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
|
|
||||||
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
|
- name: Upload & activate atomically
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
REL="${{ env.REL }}"
|
REL="$(date -u +%Y%m%d-%H%M%SZ)-${{ github.sha }}"
|
||||||
TAR="release/${REL}.tar.gz"
|
echo "REL=$REL" >> $GITHUB_ENV
|
||||||
|
TAR="/tmp/${REL}.tar.gz"
|
||||||
APP="${{ env.APP_ROOT }}"
|
APP="${{ env.APP_ROOT }}"
|
||||||
SHARED="${APP}/shared"
|
SHARED="${APP}/shared"
|
||||||
RELEASES="${APP}/releases"
|
RELEASES="${APP}/releases"
|
||||||
CUR="${APP}/current"
|
CUR="${APP}/current"
|
||||||
UPLOADS="${{ env.UPLOADS_DIR }}"
|
UPLOADS="${{ env.UPLOADS_DIR }}"
|
||||||
|
|
||||||
# ensure layout exists
|
tar -czf "$TAR" --exclude-vcs --exclude='./node_modules' --exclude="./${UPLOADS}" --exclude='./release' .
|
||||||
ssh -i ~/.ssh/id_ed25519 ${SSH_USER}@${SSH_HOST} "
|
mkdir -p release && mv "$TAR" "release/${REL}.tar.gz"
|
||||||
set -e
|
|
||||||
sudo install -d -o ${SSH_USER} -g ${SSH_USER} -m 755 ${RELEASES} ${SHARED} ${SHARED}/${UPLOADS}
|
|
||||||
"
|
|
||||||
|
|
||||||
# upload tar
|
ssh $SSH_OPTS -i "$SSH_KEY_PATH" ${SSH_USER}@${SSH_HOST} \
|
||||||
scp -i ~/.ssh/id_ed25519 ${TAR} ${SSH_USER}@${SSH_HOST}:/tmp/${REL}.tar.gz
|
"set -e; install -d -m 755 ${RELEASES} ${SHARED} ${SHARED}/${UPLOADS}"
|
||||||
|
|
||||||
# unpack, link shared, flip symlink, reload, health check, prune
|
scp -O $SSH_OPTS -vvv -i "$SSH_KEY_PATH" "release/${REL}.tar.gz" ${SSH_USER}@${SSH_HOST}:/tmp/${REL}.tar.gz
|
||||||
ssh -i ~/.ssh/id_ed25519 ${SSH_USER}@${SSH_HOST} '
|
|
||||||
|
ssh $SSH_OPTS -i "$SSH_KEY_PATH" ${SSH_USER}@${SSH_HOST} '
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
REL="'${REL}'"; APP="'${APP}'"; SHARED="'${SHARED}'"; RELEASES="'${RELEASES}'"; CUR="'${CUR}'"; UPLOADS="'${UPLOADS}'";
|
REL="'${REL}'"; APP="'${APP}'"; SHARED="'${SHARED}'"; RELEASES="'${RELEASES}'"; CUR="'${CUR}'"; UPLOADS="'${UPLOADS}'";
|
||||||
|
|
||||||
NEW="${RELEASES}/${REL}"
|
NEW="${RELEASES}/${REL}"
|
||||||
mkdir -p "${NEW}"
|
mkdir -p "${NEW}"
|
||||||
tar -xzf "/tmp/${REL}.tar.gz" -C "${NEW}"
|
tar -xzf "/tmp/${REL}.tar.gz" -C "${NEW}" && rm -f "/tmp/${REL}.tar.gz"
|
||||||
rm -f "/tmp/${REL}.tar.gz"
|
rm -rf "${NEW}/${UPLOADS}" && ln -s "${SHARED}/${UPLOADS}" "${NEW}/${UPLOADS}"
|
||||||
|
[ -f "${SHARED}/.env" ] && ln -sf "${SHARED}/.env" "${NEW}/.env" || true
|
||||||
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"
|
printf "sha=%s\nbuilt_at=%s\n" "'${{ github.sha }}'" "$(date -u +%FT%TZ)" > "${NEW}/RELEASE"
|
||||||
|
|
||||||
PREV="$(readlink -f "${CUR}" || true)"
|
PREV="$(readlink -f "${CUR}" || true)"
|
||||||
ln -sfn "${NEW}" "${CUR}"
|
ln -sfn "${NEW}" "${CUR}"
|
||||||
|
|
||||||
'"${{ env.SERVICE_RELOAD }}"' >/dev/null 2>&1 || true
|
'"${{ env.SERVICE_RELOAD }}"' >/dev/null 2>&1 || true
|
||||||
|
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsS --max-time 5 "'"${{ env.HEALTH_URL }}"'" >/dev/null || {
|
curl -fsS --max-time 5 "'"${{ env.HEALTH_URL }}"'" >/dev/null || {
|
||||||
echo "Health check failed, rolling back..."
|
echo "Health check failed, rolling back..."
|
||||||
@@ -120,7 +82,5 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
cd "${RELEASES}" && ls -1tr | head -n -'${{ env.KEEP_N }}' | xargs -r -I{} rm -rf "{}"
|
||||||
cd "${RELEASES}"
|
|
||||||
ls -1tr | head -n -'${{ env.KEEP_N }}' | xargs -r -I{} rm -rf "{}"
|
|
||||||
'
|
'
|
||||||
|
|||||||
47
.gitea/workflows/rollback.yml
Normal file
47
.gitea/workflows/rollback.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# manual rollback
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
steps:
|
||||||
|
description: "How many releases to roll back (1 = previous)"
|
||||||
|
default: "1"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rollback:
|
||||||
|
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/stellaamor
|
||||||
|
SERVICE_RELOAD: "systemctl reload apache2 || true"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Roll back symlink to an older release
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
APP="${{ env.APP_ROOT }}"
|
||||||
|
RELEASES="${APP}/releases"
|
||||||
|
CUR="${APP}/current"
|
||||||
|
N="${{ github.event.inputs.steps || '1' }}"
|
||||||
|
|
||||||
|
# pick target release (1=previous)
|
||||||
|
TARGET="$(ls -1tr "${RELEASES}" | tail -n +"$((N+1))" | tail -n 1)"
|
||||||
|
if [ -z "${TARGET}" ]; then
|
||||||
|
echo "No release found to roll back to."; exit 1
|
||||||
|
fi
|
||||||
|
echo "Rolling back to: ${TARGET}"
|
||||||
|
|
||||||
|
ssh $SSH_OPTS -i "$SSH_KEY_PATH" ${SSH_USER}@${SSH_HOST} "
|
||||||
|
set -euo pipefail
|
||||||
|
APP='${APP}'; RELEASES='${RELEASES}'; CUR='${CUR}'; TARGET='${TARGET}';
|
||||||
|
[ -d \"\${RELEASES}/\${TARGET}\" ] || { echo 'Target release missing'; exit 1; }
|
||||||
|
ln -sfn \"\${RELEASES}/\${TARGET}\" \"\${CUR}\"
|
||||||
|
${SERVICE_RELOAD} >/dev/null 2>&1 || true
|
||||||
|
"
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
RewriteBase /
|
RewriteBase /
|
||||||
|
|
||||||
RewriteCond %{HTTPS} off
|
|
||||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
|
||||||
|
|
||||||
# Add trailing slash to URLs (except files and directories)
|
# Add trailing slash to URLs (except files and directories)
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="inner-row">
|
<div class="inner-row">
|
||||||
<div class="text-col">
|
<div class="text-col">
|
||||||
<h1 class="title mb-3">Discover <span class="text-primary">Your Love Story</span> with Stella Amor</h1>
|
<h1 class="title mb-3">Discover <span class="text-primary">Your Love Story</span> with Stella Amor</h1>
|
||||||
<p class="lead mb-1">Join free today with unique date filters for finance, kinks, lifestyle, and beyond. Start exploring now!</p>
|
<p class="lead mb-1">Join free today with unique dating filters for finance, kinks, lifestyle, and much more. Start exploring now!</p>
|
||||||
<a href="/register/" class="mb-3 btn btn-dark cta-btn">Sign up today</a>
|
<a href="/register/" class="mb-3 btn btn-dark cta-btn">Sign up today</a>
|
||||||
<p class="login-text">Already have an account? <a href="/login/" class="login-link">Login now</a></p>
|
<p class="login-text">Already have an account? <a href="/login/" class="login-link">Login now</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user