Skip to content

feat(booking): public calendar honors configured hours & days #87

feat(booking): public calendar honors configured hours & days

feat(booking): public calendar honors configured hours & days #87

name: Release to Hostinger
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
deployments: write
concurrency:
group: production
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
NEXT_PUBLIC_LLM_API_KEY: ${{ secrets.NEXT_PUBLIC_LLM_API_KEY }}
DEPLOY_ROOT: /home/${{ secrets.HOSTINGER_SSH_USERNAME }}/domains/temrevil.com
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type-check
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Upload static build artifact
uses: actions/upload-artifact@v7
with:
name: site-dist
path: dist
deploy:
needs: validate
runs-on: ubuntu-latest
environment:
name: production
url: https://temrevil.com
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Download static build artifact
uses: actions/download-artifact@v5
with:
name: site-dist
path: deploy_bundle
- name: Add Apache runtime config
run: cp deploy/hostinger/.htaccess deploy_bundle/.htaccess
- name: Create release archive
run: tar -czf release.tgz -C deploy_bundle .
# SSH/SCP to Hostinger occasionally fails with a transient "dial tcp: i/o
# timeout". We drive ssh/scp directly (sshpass) and wrap each in
# nick-fields/retry: up to 3 attempts, 15s apart — bounded, not endless.
# DEPLOY_ROOT/RELEASE_SHA are expanded locally then set for the remote shell.
- name: Install sshpass
run: sudo apt-get update -qq && sudo apt-get install -y -qq sshpass
- name: Prepare remote deploy directories
uses: nick-fields/retry@v3.0.2
env:
SSHPASS: ${{ secrets.HOSTINGER_SSH_PASSWORD }}
SSH_HOST: ${{ secrets.HOSTINGER_SSH_HOST }}
SSH_USER: ${{ secrets.HOSTINGER_SSH_USERNAME }}
SSH_PORT: ${{ secrets.HOSTINGER_SSH_PORT }}
with:
timeout_minutes: 5
max_attempts: 3
retry_wait_seconds: 15
command: |
sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=30 -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "DEPLOY_ROOT='$DEPLOY_ROOT' bash -s" <<'REMOTE'
set -eu
mkdir -p "$DEPLOY_ROOT/.codex-deploy/incoming"
mkdir -p "$DEPLOY_ROOT/.codex-deploy/releases"
mkdir -p "$DEPLOY_ROOT/.codex-deploy/backups"
REMOTE
- name: Upload release archive
uses: nick-fields/retry@v3.0.2
env:
SSHPASS: ${{ secrets.HOSTINGER_SSH_PASSWORD }}
SSH_HOST: ${{ secrets.HOSTINGER_SSH_HOST }}
SSH_USER: ${{ secrets.HOSTINGER_SSH_USERNAME }}
SSH_PORT: ${{ secrets.HOSTINGER_SSH_PORT }}
with:
timeout_minutes: 5
max_attempts: 3
retry_wait_seconds: 15
command: |
sshpass -e scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=30 -P "$SSH_PORT" release.tgz "$SSH_USER@$SSH_HOST:$DEPLOY_ROOT/.codex-deploy/incoming/release.tgz"
- name: Activate release on Hostinger
uses: nick-fields/retry@v3.0.2
env:
SSHPASS: ${{ secrets.HOSTINGER_SSH_PASSWORD }}
SSH_HOST: ${{ secrets.HOSTINGER_SSH_HOST }}
SSH_USER: ${{ secrets.HOSTINGER_SSH_USERNAME }}
SSH_PORT: ${{ secrets.HOSTINGER_SSH_PORT }}
RELEASE_SHA: ${{ github.sha }}
with:
timeout_minutes: 5
max_attempts: 3
retry_wait_seconds: 15
command: |
sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=30 -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "DEPLOY_ROOT='$DEPLOY_ROOT' RELEASE_SHA='$RELEASE_SHA' bash -s" <<'REMOTE'
set -eu
CURRENT_DIR="$DEPLOY_ROOT/public_html"
INCOMING_ARCHIVE="$DEPLOY_ROOT/.codex-deploy/incoming/release.tgz"
STAGE_DIR="$DEPLOY_ROOT/.codex-deploy/releases/$RELEASE_SHA"
BACKUP_DIR="$DEPLOY_ROOT/.codex-deploy/backups/$(date +%Y%m%d%H%M%S)"
rm -rf "$STAGE_DIR"
mkdir -p "$STAGE_DIR"
tar -xzf "$INCOMING_ARCHIVE" -C "$STAGE_DIR"
if [ -d "$CURRENT_DIR/.well-known" ]; then
mkdir -p "$STAGE_DIR/.well-known"
cp -a "$CURRENT_DIR/.well-known/." "$STAGE_DIR/.well-known/"
fi
mkdir -p "$BACKUP_DIR"
mv "$CURRENT_DIR" "$BACKUP_DIR/public_html"
mv "$STAGE_DIR" "$CURRENT_DIR"
rm -f "$INCOMING_ARCHIVE"
REMOTE