8ae829ad89
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 3s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 44s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (push) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (push) Has been cancelled
Platform: moko-platform CI / CI Summary (push) Has been cancelled
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
- Add 'live' and 'all' options to server selector - Live deploy reads LIVE_TARGETS JSON secret for multiple production instances - Move dev/demo host config from hardcoded env to vars.* - Add summary step for deploy reporting Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
224 lines
8.1 KiB
YAML
224 lines
8.1 KiB
YAML
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
#
|
|
# FILE INFORMATION
|
|
# DEFGROUP: Gitea.Workflow
|
|
# INGROUP: moko-platform.Deploy
|
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
|
# PATH: /templates/workflows/deploy-module.yml
|
|
# VERSION: 02.00.00
|
|
# BRIEF: Deploy Dolibarr module to dev, demo, or live environments
|
|
#
|
|
# Secrets required:
|
|
# GA_TOKEN - Gitea API token for repo access
|
|
# DEPLOY_SSH_KEY - SSH private key for server access
|
|
# LIVE_TARGETS - JSON array of live instances (optional), e.g.:
|
|
# [{"host":"client1.example.com","user":"deploy",
|
|
# "mods_dir":"/path/MokoDoliMods",
|
|
# "custom_dir":"/path/htdocs/custom"}]
|
|
#
|
|
# Variables required:
|
|
# DEV_HOST, DEV_USER, DEV_MODS_DIR, DEV_CUSTOM_DIR
|
|
# DEMO_HOST, DEMO_USER, DEMO_MODS_DIR, DEMO_CUSTOM_DIR
|
|
|
|
name: "Dolibarr: Deploy Module"
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
module_repo:
|
|
description: 'Module repo name (e.g. MokoCRM, MokoDoliSign)'
|
|
required: true
|
|
server:
|
|
description: 'Target environment'
|
|
required: true
|
|
default: 'dev'
|
|
type: choice
|
|
options:
|
|
- dev
|
|
- demo
|
|
- live
|
|
- dev+demo
|
|
- all
|
|
|
|
env:
|
|
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
|
ORG: ${{ vars.GITEA_ORG || 'MokoConsulting' }}
|
|
|
|
jobs:
|
|
deploy:
|
|
name: Deploy ${{ inputs.module_repo }} to ${{ inputs.server }}
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Validate module repo
|
|
run: |
|
|
REPO="${{ inputs.module_repo }}"
|
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
-H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
|
"${GITEA_URL}/api/v1/repos/${ORG}/${REPO}")
|
|
if [ "$STATUS" != "200" ]; then
|
|
echo "::error::${ORG}/${REPO} not found (HTTP ${STATUS})"
|
|
exit 1
|
|
fi
|
|
echo "REPO=${REPO}" >> $GITHUB_ENV
|
|
|
|
LINK_NAME=$(echo "$REPO" | sed 's/MokoDoli//;s/Moko//' | tr '[:upper:]' '[:lower:]')
|
|
[ "$REPO" = "MokoCRM" ] && LINK_NAME="mokocrm"
|
|
[ "$REPO" = "MokoDoliProjTemplate" ] && LINK_NAME="mokoprojtemplate"
|
|
echo "LINK_NAME=${LINK_NAME}" >> $GITHUB_ENV
|
|
|
|
- name: Get latest stable tag
|
|
run: |
|
|
TAGS=$(curl -s \
|
|
-H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
|
"${GITEA_URL}/api/v1/repos/${ORG}/${{ env.REPO }}/tags?limit=1")
|
|
TAG=$(echo "$TAGS" | jq -r '.[0].name // empty')
|
|
echo "TAG=${TAG}" >> $GITHUB_ENV
|
|
[ -n "$TAG" ] && echo "Deploying: $TAG" || echo "No tags - deploying main"
|
|
|
|
- name: Deploy to dev
|
|
if: inputs.server == 'dev' || inputs.server == 'dev+demo' || inputs.server == 'all'
|
|
uses: appleboy/ssh-action@v1
|
|
with:
|
|
host: ${{ vars.DEV_HOST }}
|
|
username: ${{ vars.DEV_USER }}
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
script: |
|
|
REPO="${{ env.REPO }}"
|
|
LINK="${{ env.LINK_NAME }}"
|
|
TAG="${{ env.TAG }}"
|
|
MODS="${{ vars.DEV_MODS_DIR }}"
|
|
CUSTOM="${{ vars.DEV_CUSTOM_DIR }}"
|
|
|
|
mkdir -p "$MODS" && cd "$MODS"
|
|
if [ -d "$REPO" ]; then
|
|
cd "$REPO" && git fetch --tags origin
|
|
else
|
|
git clone "${{ env.GITEA_URL }}/${{ env.ORG }}/${REPO}.git"
|
|
cd "$REPO"
|
|
fi
|
|
|
|
if [ -n "$TAG" ]; then
|
|
git checkout "$TAG" --quiet
|
|
else
|
|
git checkout main --quiet
|
|
git pull --ff-only origin main --quiet
|
|
fi
|
|
|
|
cd "$CUSTOM"
|
|
[ -L "$LINK" ] || [ -d "$LINK" ] && rm -rf "$LINK"
|
|
ln -sf "$MODS/$REPO/src" "$LINK"
|
|
echo "OK: $LINK -> $MODS/$REPO/src (${TAG:-main})"
|
|
|
|
- name: Deploy to demo
|
|
if: inputs.server == 'demo' || inputs.server == 'dev+demo' || inputs.server == 'all'
|
|
uses: appleboy/ssh-action@v1
|
|
with:
|
|
host: ${{ vars.DEMO_HOST }}
|
|
username: ${{ vars.DEMO_USER }}
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
script: |
|
|
REPO="${{ env.REPO }}"
|
|
LINK="${{ env.LINK_NAME }}"
|
|
TAG="${{ env.TAG }}"
|
|
MODS="${{ vars.DEMO_MODS_DIR }}"
|
|
CUSTOM="${{ vars.DEMO_CUSTOM_DIR }}"
|
|
|
|
mkdir -p "$MODS" && cd "$MODS"
|
|
if [ -d "$REPO" ]; then
|
|
cd "$REPO" && git fetch --tags origin
|
|
else
|
|
git clone "${{ env.GITEA_URL }}/${{ env.ORG }}/${REPO}.git"
|
|
cd "$REPO"
|
|
fi
|
|
|
|
if [ -n "$TAG" ]; then
|
|
git checkout "$TAG" --quiet
|
|
else
|
|
git checkout main --quiet
|
|
git pull --ff-only origin main --quiet
|
|
fi
|
|
|
|
cd "$CUSTOM"
|
|
[ -L "$LINK" ] || [ -d "$LINK" ] && rm -rf "$LINK"
|
|
ln -sf "$MODS/$REPO/src" "$LINK"
|
|
echo "OK: $LINK -> $MODS/$REPO/src (${TAG:-main})"
|
|
|
|
- name: Deploy to live
|
|
if: inputs.server == 'live' || inputs.server == 'all'
|
|
env:
|
|
LIVE_TARGETS: ${{ secrets.LIVE_TARGETS }}
|
|
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
run: |
|
|
if [ -z "$LIVE_TARGETS" ] || [ "$LIVE_TARGETS" = "null" ]; then
|
|
echo "::error::LIVE_TARGETS secret is not configured."
|
|
echo "Set it to a JSON array of target objects."
|
|
exit 1
|
|
fi
|
|
|
|
COUNT=$(echo "$LIVE_TARGETS" | jq 'length')
|
|
echo "Deploying to ${COUNT} live instance(s)..."
|
|
|
|
echo "$DEPLOY_KEY" > /tmp/deploy_key
|
|
chmod 600 /tmp/deploy_key
|
|
|
|
FAILED=0
|
|
for i in $(seq 0 $((COUNT - 1))); do
|
|
HOST=$(echo "$LIVE_TARGETS" | jq -r ".[$i].host")
|
|
USER=$(echo "$LIVE_TARGETS" | jq -r ".[$i].user")
|
|
MODS=$(echo "$LIVE_TARGETS" | jq -r ".[$i].mods_dir")
|
|
CUSTOM=$(echo "$LIVE_TARGETS" | jq -r ".[$i].custom_dir")
|
|
PORT=$(echo "$LIVE_TARGETS" | jq -r ".[$i].port // 22")
|
|
LABEL=$(echo "$LIVE_TARGETS" | jq -r ".[$i].label // empty")
|
|
[ -z "$LABEL" ] && LABEL="$HOST"
|
|
|
|
echo ""
|
|
echo "=== Instance $((i+1))/${COUNT}: ${LABEL} (${USER}@${HOST}:${PORT}) ==="
|
|
|
|
ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15 \
|
|
-i /tmp/deploy_key -p "$PORT" "${USER}@${HOST}" \
|
|
"REPO='${{ env.REPO }}' LINK='${{ env.LINK_NAME }}' TAG='${{ env.TAG }}' MODS='${MODS}' CUSTOM='${CUSTOM}' GITEA_URL='${{ env.GITEA_URL }}' ORG='${{ env.ORG }}' bash" <<'REMOTE_SCRIPT' || { echo "::warning::Failed: ${LABEL}"; FAILED=$((FAILED+1)); continue; }
|
|
mkdir -p "$MODS" && cd "$MODS"
|
|
if [ -d "$REPO" ]; then
|
|
cd "$REPO" && git fetch --tags origin
|
|
else
|
|
git clone "${GITEA_URL}/${ORG}/${REPO}.git"
|
|
cd "$REPO"
|
|
fi
|
|
|
|
if [ -n "$TAG" ]; then
|
|
git checkout "$TAG" --quiet
|
|
else
|
|
git checkout main --quiet
|
|
git pull --ff-only origin main --quiet
|
|
fi
|
|
|
|
cd "$CUSTOM"
|
|
[ -L "$LINK" ] || [ -d "$LINK" ] && rm -rf "$LINK"
|
|
ln -sf "$MODS/$REPO/src" "$LINK"
|
|
echo "OK: $LINK -> $MODS/$REPO/src (${TAG:-main})"
|
|
REMOTE_SCRIPT
|
|
done
|
|
|
|
rm -f /tmp/deploy_key
|
|
|
|
if [ "$FAILED" -gt 0 ]; then
|
|
echo "::error::${FAILED} of ${COUNT} live deployment(s) failed"
|
|
exit 1
|
|
fi
|
|
echo "All ${COUNT} live instance(s) deployed successfully."
|
|
|
|
- name: Summary
|
|
if: always()
|
|
run: |
|
|
echo "## Deploy: ${{ env.REPO }} -> ${{ inputs.server }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Module | \`${{ env.REPO }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Symlink | \`${{ env.LINK_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Version | \`${{ env.TAG || 'main' }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Target | \`${{ inputs.server }}\` |" >> $GITHUB_STEP_SUMMARY
|