feat: add live deploy target with multi-instance support to deploy-module.yml
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>
This commit is contained in:
Jonathan Miller
2026-05-26 16:54:39 -05:00
parent 96b6db73a9
commit 8ae829ad89
+126 -30
View File
@@ -1,4 +1,28 @@
name: Deploy Dolibarr Module
# 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:
@@ -7,30 +31,26 @@ on:
description: 'Module repo name (e.g. MokoCRM, MokoDoliSign)'
required: true
server:
description: 'Target server'
description: 'Target environment'
required: true
default: 'dev'
type: choice
options:
- dev
- demo
- both
- live
- dev+demo
- all
env:
GITEA_URL: https://git.mokoconsulting.tech
ORG: MokoConsulting
DEV_HOST: waas.dev.mokoconsulting.tech
DEV_USER: mokoconsulting_dev
DEV_MODS_DIR: /home/mokoconsulting_dev/MokoDoliMods
DEV_CUSTOM_DIR: /home/mokoconsulting_dev/crm.dev.mokoconsulting.tech/htdocs/custom
DEMO_HOST: waas.demo.mokoconsulting.tech
DEMO_USER: mokoconsulting_demo
DEMO_MODS_DIR: /home/mokoconsulting_demo/MokoDoliMods
DEMO_CUSTOM_DIR: /home/mokoconsulting_demo/crm.demo.mokoconsulting.tech/htdocs/custom
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: |
@@ -39,11 +59,11 @@ jobs:
-H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${GITEA_URL}/api/v1/repos/${ORG}/${REPO}")
if [ "$STATUS" != "200" ]; then
echo "ERROR: ${ORG}/${REPO} not found"; exit 1
echo "::error::${ORG}/${REPO} not found (HTTP ${STATUS})"
exit 1
fi
echo "REPO=${REPO}" >> $GITHUB_ENV
# Derive symlink name
LINK_NAME=$(echo "$REPO" | sed 's/MokoDoli//;s/Moko//' | tr '[:upper:]' '[:lower:]')
[ "$REPO" = "MokoCRM" ] && LINK_NAME="mokocrm"
[ "$REPO" = "MokoDoliProjTemplate" ] && LINK_NAME="mokoprojtemplate"
@@ -56,27 +76,27 @@ jobs:
"${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"
[ -n "$TAG" ] && echo "Deploying: $TAG" || echo "No tags - deploying main"
- name: Deploy to dev
if: inputs.server == 'dev' || inputs.server == 'both'
if: inputs.server == 'dev' || inputs.server == 'dev+demo' || inputs.server == 'all'
uses: appleboy/ssh-action@v1
with:
host: ${{ env.DEV_HOST }}
username: ${{ env.DEV_USER }}
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="${{ env.DEV_MODS_DIR }}"
CUSTOM="${{ env.DEV_CUSTOM_DIR }}"
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 "https://git.mokoconsulting.tech/${{ env.ORG }}/${REPO}.git"
git clone "${{ env.GITEA_URL }}/${{ env.ORG }}/${REPO}.git"
cd "$REPO"
fi
@@ -90,27 +110,27 @@ jobs:
cd "$CUSTOM"
[ -L "$LINK" ] || [ -d "$LINK" ] && rm -rf "$LINK"
ln -sf "$MODS/$REPO/src" "$LINK"
echo "OK: $LINK $MODS/$REPO/src (${TAG:-main})"
echo "OK: $LINK -> $MODS/$REPO/src (${TAG:-main})"
- name: Deploy to demo
if: inputs.server == 'demo' || inputs.server == 'both'
if: inputs.server == 'demo' || inputs.server == 'dev+demo' || inputs.server == 'all'
uses: appleboy/ssh-action@v1
with:
host: ${{ env.DEMO_HOST }}
username: ${{ env.DEMO_USER }}
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="${{ env.DEMO_MODS_DIR }}"
CUSTOM="${{ env.DEMO_CUSTOM_DIR }}"
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 "https://git.mokoconsulting.tech/${{ env.ORG }}/${REPO}.git"
git clone "${{ env.GITEA_URL }}/${{ env.ORG }}/${REPO}.git"
cd "$REPO"
fi
@@ -124,4 +144,80 @@ jobs:
cd "$CUSTOM"
[ -L "$LINK" ] || [ -d "$LINK" ] && rm -rf "$LINK"
ln -sf "$MODS/$REPO/src" "$LINK"
echo "OK: $LINK $MODS/$REPO/src (${TAG:-main})"
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