# Copyright (C) 2026 Moko Consulting # # 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