Merge pull request #3 from Makepad-fr/codex/auto-deploy-nginx-main #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy Nginx | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - "compose.yml" | |
| - "envs/production/**" | |
| - "sites/**" | |
| - ".github/workflows/manual-deploy.yml" | |
| workflow_dispatch: | |
| concurrency: | |
| group: nginx-production-deploy | |
| cancel-in-progress: false | |
| jobs: | |
| deploy: | |
| runs-on: ubuntu-latest | |
| environment: production | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Configure SSH key | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.ssh" | |
| chmod 700 "${HOME}/.ssh" | |
| printf '%s\n' "${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}" > "${HOME}/.ssh/id_ed25519" | |
| chmod 600 "${HOME}/.ssh/id_ed25519" | |
| - name: Prepare deployment bundle | |
| shell: bash | |
| env: | |
| MAKEPAD_PROXY_PROD_APP_NETWORK: ${{ secrets.MAKEPAD_PROXY_PROD_APP_NETWORK }} | |
| MAKEPAD_PROXY_CANARY_APP_NETWORK: ${{ secrets.MAKEPAD_PROXY_CANARY_APP_NETWORK }} | |
| MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK: ${{ secrets.MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK }} | |
| MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK: ${{ secrets.MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK }} | |
| run: | | |
| set -euo pipefail | |
| for required_network in \ | |
| MAKEPAD_PROXY_PROD_APP_NETWORK \ | |
| MAKEPAD_PROXY_CANARY_APP_NETWORK \ | |
| MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK \ | |
| MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK; do | |
| if [[ -z "${!required_network}" ]]; then | |
| echo "::error::Missing required production secret: ${required_network}" >&2 | |
| exit 1 | |
| fi | |
| done | |
| bundle_root="${RUNNER_TEMP}/bundle" | |
| mkdir -p "${bundle_root}/envs/production" "${bundle_root}/sites" | |
| cp compose.yml "${bundle_root}/compose.yml" | |
| cp "envs/production/compose.yml" "${bundle_root}/envs/production/compose.yml" | |
| cp "envs/production/.env.proxy" "${bundle_root}/envs/production/.env.proxy" | |
| cp sites/00-common.conf.template "${bundle_root}/sites/00-common.conf.template" | |
| cp sites/catwlk-prod.conf.template "${bundle_root}/sites/catwlk-prod.conf.template" | |
| cp sites/catwlk-canary.conf.template "${bundle_root}/sites/catwlk-canary.conf.template" | |
| cp sites/alerteconso-prod.conf.template "${bundle_root}/sites/alerteconso-prod.conf.template" | |
| cp sites/le-petit-coin-prod.conf.template "${bundle_root}/sites/le-petit-coin-prod.conf.template" | |
| { | |
| echo "MAKEPAD_PROXY_PROD_APP_NETWORK=${MAKEPAD_PROXY_PROD_APP_NETWORK}" | |
| echo "MAKEPAD_PROXY_CANARY_APP_NETWORK=${MAKEPAD_PROXY_CANARY_APP_NETWORK}" | |
| echo "MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK=${MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK}" | |
| echo "MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK=${MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK}" | |
| } > "${bundle_root}/envs/production/.env.deploy" | |
| - name: Deploy via Docker Swarm | |
| shell: bash | |
| env: | |
| REMOTE_HOST: ${{ secrets.DEPLOY_SSH_HOST }} | |
| REMOTE_PORT: ${{ secrets.DEPLOY_SSH_PORT }} | |
| REMOTE_USER: ${{ secrets.DEPLOY_SSH_USER }} | |
| REMOTE_DIR: ${{ secrets.DEPLOY_REMOTE_DIR }} | |
| STACK_NAME: ${{ secrets.DEPLOY_STACK_NAME }} | |
| run: | | |
| set -euo pipefail | |
| : "${REMOTE_HOST:?}" "${REMOTE_USER:?}" "${REMOTE_DIR:?}" "${STACK_NAME:?}" | |
| bundle_root="${RUNNER_TEMP}/bundle" | |
| remote_port=${REMOTE_PORT:-22} | |
| ssh_opts=(-o StrictHostKeyChecking=accept-new -p "${remote_port}") | |
| scp_opts=(-o StrictHostKeyChecking=accept-new -P "${remote_port}") | |
| remote_target="${REMOTE_USER}@${REMOTE_HOST}" | |
| ssh "${ssh_opts[@]}" "${remote_target}" mkdir -p "${REMOTE_DIR}/envs/production" "${REMOTE_DIR}/sites" | |
| scp "${scp_opts[@]}" "${bundle_root}/compose.yml" "${remote_target}:${REMOTE_DIR}/compose.yml" | |
| scp "${scp_opts[@]}" "${bundle_root}/envs/production/compose.yml" "${remote_target}:${REMOTE_DIR}/envs/production/compose.yml" | |
| scp "${scp_opts[@]}" "${bundle_root}/envs/production/.env.proxy" "${remote_target}:${REMOTE_DIR}/envs/production/.env.proxy" | |
| scp "${scp_opts[@]}" "${bundle_root}/envs/production/.env.deploy" "${remote_target}:${REMOTE_DIR}/envs/production/.env.deploy" | |
| scp "${scp_opts[@]}" "${bundle_root}/sites/00-common.conf.template" "${remote_target}:${REMOTE_DIR}/sites/00-common.conf.template" | |
| scp "${scp_opts[@]}" "${bundle_root}/sites/catwlk-prod.conf.template" "${remote_target}:${REMOTE_DIR}/sites/catwlk-prod.conf.template" | |
| scp "${scp_opts[@]}" "${bundle_root}/sites/catwlk-canary.conf.template" "${remote_target}:${REMOTE_DIR}/sites/catwlk-canary.conf.template" | |
| scp "${scp_opts[@]}" "${bundle_root}/sites/alerteconso-prod.conf.template" "${remote_target}:${REMOTE_DIR}/sites/alerteconso-prod.conf.template" | |
| scp "${scp_opts[@]}" "${bundle_root}/sites/le-petit-coin-prod.conf.template" "${remote_target}:${REMOTE_DIR}/sites/le-petit-coin-prod.conf.template" | |
| ssh "${ssh_opts[@]}" "${remote_target}" bash -se -- "${REMOTE_DIR}" "${STACK_NAME}" <<'EOF' | |
| set -euo pipefail | |
| remote_dir=$1 | |
| stack_name=$2 | |
| deploy_env=production | |
| env_deploy="${remote_dir}/envs/${deploy_env}/.env.deploy" | |
| for app_network in \ | |
| "$(grep '^MAKEPAD_PROXY_PROD_APP_NETWORK=' "${env_deploy}" | tail -n 1 | cut -d= -f2-)" \ | |
| "$(grep '^MAKEPAD_PROXY_CANARY_APP_NETWORK=' "${env_deploy}" | tail -n 1 | cut -d= -f2-)" \ | |
| "$(grep '^MAKEPAD_PROXY_ALERTECONSO_APP_NETWORK=' "${env_deploy}" | tail -n 1 | cut -d= -f2-)" \ | |
| "$(grep '^MAKEPAD_PROXY_LE_PETIT_COIN_APP_NETWORK=' "${env_deploy}" | tail -n 1 | cut -d= -f2-)"; do | |
| docker network inspect "${app_network}" >/dev/null 2>&1 \ | |
| || docker network create --driver overlay --attachable "${app_network}" | |
| done | |
| docker compose \ | |
| --env-file "${remote_dir}/envs/${deploy_env}/.env.proxy" \ | |
| --env-file "${env_deploy}" \ | |
| -f "${remote_dir}/compose.yml" \ | |
| -f "${remote_dir}/envs/${deploy_env}/compose.yml" \ | |
| config > "${remote_dir}/stack.rendered.yml" | |
| python3 - "${remote_dir}/stack.rendered.yml" "${remote_dir}/stack.yml" <<'PY' | |
| from pathlib import Path | |
| import sys | |
| source = Path(sys.argv[1]) | |
| target = Path(sys.argv[2]) | |
| text = source.read_text() | |
| text = text.replace('published: "80"', 'published: 80') | |
| text = text.replace('published: "443"', 'published: 443') | |
| text = "\n".join(line for line in text.splitlines() if line != "name: nginx") + "\n" | |
| target.write_text(text) | |
| PY | |
| docker stack deploy --compose-file "${remote_dir}/stack.yml" "${stack_name}" | |
| EOF |