Files
igaming-brands/.gitea/workflows/deploy.yml
T
lilsus 7e53cf3ce6
Build & Deploy Brands / build-and-deploy (push) Failing after 16s
ci: npm ci --ignore-scripts (skip hugo-extended postinstall that hangs on arm64)
2026-07-16 06:46:45 +03:00

168 lines
7.9 KiB
YAML

# =============================================================================
# deploy.yml — build every brand in this content repo with Hugo and deploy each
# to <brand>.lilsus.fun via rsync over SSH. Runs on every push to main (i.e.
# after each n8n pipeline run that commits repo/<brand>/...).
#
# INSTALL: copy this file to .gitea/workflows/deploy.yml in the CONTENT repo
# (lilsus/igaming-brands AND/OR lilsus/igaming-brands-i18n).
#
# REQUIRED Gitea secrets (repo → Settings → Actions → Secrets):
# DEPLOY_SSH_KEY - private SSH key (PEM) whose public key is in the server's
# authorized_keys for DEPLOY_USER. No passphrase.
# DEPLOY_HOST - server hostname/IP that Caddy runs on (e.g. lilsus.fun)
# DEPLOY_USER - ssh user with write access to DEPLOY_PATH
# DEPLOY_PATH - base web root, e.g. /srv/www (brand goes to <path>/<brand>)
# The server's SSH host key is trusted on first connect (accept-new) and pinned
# after, so no SSH_KNOWN_HOSTS secret is needed. For strict pinning instead, add
# a SSH_KNOWN_HOSTS secret and change accept-new -> yes in the deploy step.
# OPTIONAL Gitea variables (Settings → Actions → Variables):
# TEMPLATE_REPO - clone URL of the template repo
# (default: https://git.lilsus.fun/lilsus/igaming-template.git)
# HUGO_VERSION - pinned Hugo Extended version (default 0.140.2)
# SITE_TLD - base domain for per-brand hosts (default lilsus.fun)
#
# RUNNER REQUIREMENTS: a registered Gitea act_runner whose image has bash, git,
# curl, tar, rsync, openssh-client and Node.js >= 20 (for Tailwind/PostCSS).
# The default `gitea/runner`/`catthehacker/ubuntu` images include these.
# =============================================================================
name: Build & Deploy Brands
run-name: deploy ${{ gitea.sha }}
on:
push:
branches: [main]
paths:
- "repo/**"
- ".gitea/workflows/deploy.yml"
workflow_dispatch: {}
concurrency:
group: deploy-${{ gitea.ref }}
cancel-in-progress: false
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
TEMPLATE_REPO: ${{ vars.TEMPLATE_REPO || 'https://git.lilsus.fun/lilsus/igaming-template.git' }}
HUGO_VERSION: ${{ vars.HUGO_VERSION || '0.140.2' }}
SITE_TLD: ${{ vars.SITE_TLD || 'lilsus.fun' }}
CONTENT_DIR: ${{ gitea.workspace }}/content-repo
TEMPLATE_DIR: ${{ gitea.workspace }}/template-repo
HUGO_BIN: ${{ gitea.workspace }}/.hugo/hugo
steps:
# --- 1. Clone the content repo (this repo) directly. actions/checkout is
# avoided so we don't depend on the runner reaching github.com. ---
- name: Clone content repo
run: |
set -euo pipefail
rm -rf "$CONTENT_DIR"
git clone --depth 1 \
"${{ gitea.server_url }}/${{ gitea.repository }}.git" \
"$CONTENT_DIR"
cd "$CONTENT_DIR" && git checkout -q "${{ gitea.sha }}" || true
echo "Brands:"; ls -1 "$CONTENT_DIR/repo" || (echo "no repo/ dir" && exit 1)
# --- 2. Clone the template (engine) repo. Public repo → no token needed. ---
- name: Clone template repo
run: |
set -euo pipefail
rm -rf "$TEMPLATE_DIR"
git clone --depth 1 "$TEMPLATE_REPO" "$TEMPLATE_DIR"
test -d "$TEMPLATE_DIR/layouts" || (echo "template has no layouts/" && exit 1)
test -f "$TEMPLATE_DIR/data/locales.yaml" || echo "WARN: template missing data/locales.yaml"
# --- 3. Install Hugo Extended (pinned) to match local verification.
# Installed to a workspace path and invoked by absolute path
# ($HUGO_BIN) so we don't depend on the runner's PATH-file behaviour. ---
- name: Install Hugo Extended
run: |
set -euo pipefail
# Pick the tarball matching the runner CPU architecture (the runner
# image may be arm64, not amd64 — a mismatch gives "Exec format error").
case "$(uname -m)" in
x86_64|amd64) HUGO_ARCH="linux-amd64" ;;
aarch64|arm64) HUGO_ARCH="linux-arm64" ;;
*) echo "unsupported arch: $(uname -m)"; exit 1 ;;
esac
HUGO_TARBALL="hugo_extended_${HUGO_VERSION}_${HUGO_ARCH}.tar.gz"
URL="https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/${HUGO_TARBALL}"
echo "Runner arch $(uname -m) -> downloading $URL"
curl -fsSL --retry 3 -o /tmp/hugo.tar.gz "$URL"
mkdir -p "$(dirname "$HUGO_BIN")"
tar -xzf /tmp/hugo.tar.gz -C "$(dirname "$HUGO_BIN")" hugo
"$HUGO_BIN" version
# --- 4. Install Node deps once (Tailwind/PostCSS used by Hugo Pipes).
# --ignore-scripts is critical: the template's hugo-extended
# devDependency has a postinstall that downloads a ~50MB Hugo binary,
# which hangs npm ci for minutes on arm64. We install Hugo ourselves
# in step 3, so skipping lifecycle scripts is safe and much faster.
# Tailwind v3 + PostCSS + autoprefixer are pure JS (no build step). ---
- name: Install template Node deps
run: |
set -euo pipefail
node --version
cd "$TEMPLATE_DIR"
if [ -f package-lock.json ]; then
npm ci --no-audit --no-fund --ignore-scripts
else
npm install --no-audit --no-fund --ignore-scripts
fi
# --- 5. Prepare the SSH deploy key for rsync. Host key is trusted on
# first connect and pinned thereafter (StrictHostKeyChecking=accept-new
# in the deploy step), so no SSH_KNOWN_HOSTS secret is required. ---
- name: Configure SSH
run: |
set -euo pipefail
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY }}" > "$HOME/.ssh/deploy_key"
chmod 600 "$HOME/.ssh/deploy_key"
touch "$HOME/.ssh/known_hosts" && chmod 644 "$HOME/.ssh/known_hosts"
# --- 6. Build every brand and deploy it to <brand>.<SITE_TLD>. ---
- name: Build & deploy each brand
run: |
set -euo pipefail
DEPLOY_HOST='${{ secrets.DEPLOY_HOST }}'
DEPLOY_USER='${{ secrets.DEPLOY_USER }}'
DEPLOY_PATH='${{ secrets.DEPLOY_PATH }}'
[ -n "$DEPLOY_HOST" ] && [ -n "$DEPLOY_USER" ] && [ -n "$DEPLOY_PATH" ] \
|| { echo "Missing DEPLOY_HOST/USER/PATH secrets"; exit 1; }
SSH_OPTS="-i $HOME/.ssh/deploy_key -o UserKnownHostsFile=$HOME/.ssh/known_hosts -o StrictHostKeyChecking=accept-new"
for BRAND_PATH in "$CONTENT_DIR"/repo/*/; do
BRAND="$(basename "$BRAND_PATH")"
BASE_URL="https://${BRAND}.${SITE_TLD}/"
BUILD_DIR="${{ gitea.workspace }}/build/${BRAND}"
echo "::group::Build ${BRAND} -> ${BASE_URL}"
node "$TEMPLATE_DIR/scripts/ci-build-brand.mjs" \
--template "$TEMPLATE_DIR" \
--brand-dir "$BRAND_PATH" \
--out "$BUILD_DIR"
# node_modules must be reachable from the build dir for Hugo PostCSS.
ln -sfn "$TEMPLATE_DIR/node_modules" "$BUILD_DIR/node_modules"
"$HUGO_BIN" --source "$BUILD_DIR" --gc --minify --baseURL "$BASE_URL"
test -f "$BUILD_DIR/public/index.html" || { echo "build produced no index.html"; exit 1; }
echo "::endgroup::"
echo "::group::Deploy ${BRAND}"
# Ensure the target dir exists, then mirror public/ into it.
ssh $SSH_OPTS "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '${DEPLOY_PATH}/${BRAND}'"
rsync -az --delete \
-e "ssh $SSH_OPTS" \
"$BUILD_DIR/public/" \
"${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/${BRAND}/"
echo "Deployed ${BRAND} to ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/${BRAND}/"
echo "::endgroup::"
done
- name: Cleanup SSH key
if: always()
run: rm -f "$HOME/.ssh/deploy_key"