Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa88e9df6b |
@@ -1,24 +1,22 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
# BRIEF: Build and deploy to the Dev environment on push to the dev branch.
|
# BRIEF: Deploy to the Dev environment on push to the dev branch via the
|
||||||
# Portable across Go server repos: ALL deployment config comes from repo
|
# restricted per-repo deploy pattern. This is a THIN trigger: it only
|
||||||
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
|
# validates the tier+tag and hands "<tier> <tag>" to the forced-command
|
||||||
# The dev branch is the ongoing integration branch.
|
# deploy-mokogit user over SSH (mokocli cli/deploy.php). The server-side
|
||||||
|
# forced command sudo's to a root-owned deployer that builds, pushes,
|
||||||
|
# recreates and health-checks — the runner never builds, holds a registry
|
||||||
|
# token, or runs the health check. See `.vault system/deploy` and runbook
|
||||||
|
# 16-restricted-deploy-pattern.
|
||||||
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
||||||
|
# NOTE: deploy-*.yml are repo-managed (per-repo deploy user + secrets/vars)
|
||||||
|
# and excluded from template sync — see mokocli workflow_sync PLATFORM_EXCLUDES['go'].
|
||||||
#
|
#
|
||||||
# Required repo VARIABLES (all tier-scoped so each environment is independent —
|
# Required repo VARIABLES:
|
||||||
# a repo may host its rc/dev/prod tiers on different machines):
|
|
||||||
# DEV_SSH_HOST, DEV_SSH_PORT, DEV_SSH_USERNAME - SSH deploy target for the dev tier
|
# DEV_SSH_HOST, DEV_SSH_PORT, DEV_SSH_USERNAME - SSH deploy target for the dev tier
|
||||||
# DEV_REGISTRY, DEV_REGISTRY_USER, DEV_IMAGE - container registry + login user + image
|
# (DEV_SSH_USERNAME = deploy-mokogit, the forced-command deploy user)
|
||||||
# DEV_CONTAINER - compose service/container to recreate
|
# Required SECRETS (already configured; reused, not re-set):
|
||||||
# DEV_COMPOSE_PROJECT - docker compose -p project name
|
# DEPLOY_SSH_KEY - deploy-mokogit private key (repo secret)
|
||||||
# DEV_COMPOSE_DIR - dir containing docker-compose.yml on host
|
|
||||||
# DEV_SOURCE_DIR - build source checkout on host
|
|
||||||
# DEV_TAG_ENV - compose env-var name that pins the image tag
|
|
||||||
# DEV_HEALTH_URL - external URL to verify after deploy
|
|
||||||
# Required SECRETS (already configured org-wide; reused, not re-set):
|
|
||||||
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
|
|
||||||
# MOKOGIT_TOKEN - registry/API token (org secret)
|
|
||||||
|
|
||||||
name: Deploy (Dev)
|
name: Deploy (Dev)
|
||||||
|
|
||||||
@@ -39,7 +37,7 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-dev:
|
deploy-dev:
|
||||||
name: "Build & Deploy to Dev"
|
name: "Deploy to Dev"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source
|
- name: Checkout source
|
||||||
@@ -62,75 +60,29 @@ jobs:
|
|||||||
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
||||||
chmod 600 ~/.ssh/deploy_key
|
chmod 600 ~/.ssh/deploy_key
|
||||||
|
|
||||||
- name: Build and deploy to RC via SSH
|
- name: Setup MokoCLI tools
|
||||||
env:
|
env:
|
||||||
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||||
TAG: ${{ steps.config.outputs.tag }}
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
run: |
|
run: |
|
||||||
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
|
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
|
||||||
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
|
if [ -f /opt/mokocli/cli/deploy.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||||
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
|
echo Using pre-installed /opt/mokocli
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.DEV_SSH_PORT }} \
|
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||||
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
else
|
||||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
|
echo Falling back to fresh clone
|
||||||
${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }} \
|
if ! command -v composer > /dev/null 2>&1; then
|
||||||
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||||
set -e
|
|
||||||
echo 'SSH connected to Dev environment'
|
|
||||||
|
|
||||||
if [ -z "$TAG" ]; then
|
|
||||||
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
HEALTH_FMT='{{.State.Health.Status}}'
|
|
||||||
|
|
||||||
echo 'Cleaning Docker build cache...'
|
|
||||||
docker builder prune -af 2>/dev/null || true
|
|
||||||
docker image prune -af 2>/dev/null || true
|
|
||||||
|
|
||||||
echo 'Pulling source...'
|
|
||||||
SOURCE_DIR='${{ vars.DEV_SOURCE_DIR }}'
|
|
||||||
if [ ! -d "$SOURCE_DIR/.git" ]; then
|
|
||||||
git clone -b dev https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
|
|
||||||
fi
|
|
||||||
cd "$SOURCE_DIR"
|
|
||||||
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
|
|
||||||
git fetch origin dev
|
|
||||||
git reset --hard origin/dev
|
|
||||||
|
|
||||||
echo "Building image: ${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG"
|
|
||||||
docker build --no-cache --build-arg GOFLAGS='-p 1' \
|
|
||||||
--tag "${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG" \
|
|
||||||
-f Dockerfile .
|
|
||||||
|
|
||||||
echo 'Pushing to registry...'
|
|
||||||
echo "$REGISTRY_TOKEN" | docker login ${{ vars.DEV_REGISTRY }} -u ${{ vars.DEV_REGISTRY_USER }} --password-stdin
|
|
||||||
docker push "${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG"
|
|
||||||
|
|
||||||
echo 'Restarting Dev container...'
|
|
||||||
cd '${{ vars.DEV_COMPOSE_DIR }}'
|
|
||||||
# Drive the rc service image tag via its compose env-var (no sed on the shared
|
|
||||||
# file); remove any lingering fixed-name container first, then force-recreate.
|
|
||||||
docker rm -f '${{ vars.DEV_CONTAINER }}' 2>/dev/null || true
|
|
||||||
${{ vars.DEV_TAG_ENV }}="$TAG" docker compose -p '${{ vars.DEV_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.DEV_CONTAINER }}'
|
|
||||||
|
|
||||||
echo 'Health check...'
|
|
||||||
for i in 1 2 3 4 5 6 7 8; do
|
|
||||||
sleep 15
|
|
||||||
if docker inspect --format="$HEALTH_FMT" '${{ vars.DEV_CONTAINER }}' 2>/dev/null | grep -q healthy; then
|
|
||||||
echo 'Dev container healthy!'
|
|
||||||
exit 0
|
|
||||||
fi
|
fi
|
||||||
echo "Waiting... (attempt $i/8)"
|
rm -rf /tmp/mokocli
|
||||||
done
|
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||||
echo 'Health check failed'
|
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||||
docker logs '${{ vars.DEV_CONTAINER }}' --tail 20
|
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
||||||
exit 1
|
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||||
DEPLOY_EOF
|
fi
|
||||||
|
|
||||||
- name: Verify Dev instance
|
- name: Deploy (dev)
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
run: |
|
||||||
sleep 5
|
php ${MOKO_CLI}/deploy.php --tier dev --tag "${{ steps.config.outputs.tag }}" \
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.DEV_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }} "curl -sf '${{ vars.DEV_HEALTH_URL }}'" && echo " Dev API healthy"
|
--ssh-host ${{ vars.DEV_SSH_HOST }} --ssh-port ${{ vars.DEV_SSH_PORT }} \
|
||||||
|
--ssh-user ${{ vars.DEV_SSH_USERNAME }} --ssh-key ~/.ssh/deploy_key
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
# BRIEF: Build and deploy to the Prod environment on push to the main branch.
|
# BRIEF: Deploy to the Prod environment on push to the main branch via the
|
||||||
# Portable across Go server repos: ALL deployment config comes from repo
|
# restricted per-repo deploy pattern. This is a THIN trigger: it only
|
||||||
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
|
# validates the tier+tag and hands "<tier> <tag>" to the forced-command
|
||||||
|
# deploy-mokogit user over SSH (mokocli cli/deploy.php). The server-side
|
||||||
|
# forced command sudo's to a root-owned deployer that builds, pushes,
|
||||||
|
# recreates and health-checks — the runner never builds, holds a registry
|
||||||
|
# token, or runs the health check. See `.vault system/deploy` and runbook
|
||||||
|
# 16-restricted-deploy-pattern.
|
||||||
# Prod deploys on merge to main (dev -> rc -> main pipeline).
|
# Prod deploys on merge to main (dev -> rc -> main pipeline).
|
||||||
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
||||||
|
# NOTE: deploy-*.yml are repo-managed (per-repo deploy user + secrets/vars)
|
||||||
|
# and excluded from template sync — see mokocli workflow_sync PLATFORM_EXCLUDES['go'].
|
||||||
#
|
#
|
||||||
# Required repo VARIABLES (all tier-scoped so each environment is independent —
|
# Required repo VARIABLES:
|
||||||
# a repo may host its rc/dev/prod tiers on different machines):
|
|
||||||
# PROD_SSH_HOST, PROD_SSH_PORT, PROD_SSH_USERNAME - SSH deploy target for the prod tier
|
# PROD_SSH_HOST, PROD_SSH_PORT, PROD_SSH_USERNAME - SSH deploy target for the prod tier
|
||||||
# PROD_REGISTRY, PROD_REGISTRY_USER, PROD_IMAGE - container registry + login user + image
|
# (PROD_SSH_USERNAME = deploy-mokogit, the forced-command deploy user)
|
||||||
# PROD_CONTAINER - compose service/container to recreate
|
# Required SECRETS (already configured; reused, not re-set):
|
||||||
# PROD_COMPOSE_PROJECT - docker compose -p project name
|
# DEPLOY_SSH_KEY - deploy-mokogit private key (repo secret)
|
||||||
# PROD_COMPOSE_DIR - dir containing docker-compose.yml on host
|
|
||||||
# PROD_SOURCE_DIR - build source checkout on host
|
|
||||||
# PROD_TAG_ENV - compose env-var name that pins the image tag
|
|
||||||
# PROD_HEALTH_URL - external URL to verify after deploy
|
|
||||||
# Required SECRETS (already configured org-wide; reused, not re-set):
|
|
||||||
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
|
|
||||||
# MOKOGIT_TOKEN - registry/API token (org secret)
|
|
||||||
|
|
||||||
name: Deploy (Prod)
|
name: Deploy (Prod)
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-prod:
|
deploy-prod:
|
||||||
name: "Build & Deploy to Prod"
|
name: "Deploy to Prod"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source
|
- name: Checkout source
|
||||||
@@ -62,75 +61,29 @@ jobs:
|
|||||||
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
||||||
chmod 600 ~/.ssh/deploy_key
|
chmod 600 ~/.ssh/deploy_key
|
||||||
|
|
||||||
- name: Build and deploy to RC via SSH
|
- name: Setup MokoCLI tools
|
||||||
env:
|
env:
|
||||||
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||||
TAG: ${{ steps.config.outputs.tag }}
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
run: |
|
run: |
|
||||||
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
|
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
|
||||||
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
|
if [ -f /opt/mokocli/cli/deploy.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||||
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
|
echo Using pre-installed /opt/mokocli
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.PROD_SSH_PORT }} \
|
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||||
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
else
|
||||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
|
echo Falling back to fresh clone
|
||||||
${{ vars.PROD_SSH_USERNAME }}@${{ vars.PROD_SSH_HOST }} \
|
if ! command -v composer > /dev/null 2>&1; then
|
||||||
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||||
set -e
|
|
||||||
echo 'SSH connected to Prod environment'
|
|
||||||
|
|
||||||
if [ -z "$TAG" ]; then
|
|
||||||
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
HEALTH_FMT='{{.State.Health.Status}}'
|
|
||||||
|
|
||||||
echo 'Cleaning Docker build cache...'
|
|
||||||
docker builder prune -af 2>/dev/null || true
|
|
||||||
docker image prune -af 2>/dev/null || true
|
|
||||||
|
|
||||||
echo 'Pulling source...'
|
|
||||||
SOURCE_DIR='${{ vars.PROD_SOURCE_DIR }}'
|
|
||||||
if [ ! -d "$SOURCE_DIR/.git" ]; then
|
|
||||||
git clone -b main https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
|
|
||||||
fi
|
|
||||||
cd "$SOURCE_DIR"
|
|
||||||
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
|
|
||||||
git fetch origin main
|
|
||||||
git reset --hard origin/main
|
|
||||||
|
|
||||||
echo "Building image: ${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG"
|
|
||||||
docker build --no-cache --build-arg GOFLAGS='-p 1' \
|
|
||||||
--tag "${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG" \
|
|
||||||
-f Dockerfile .
|
|
||||||
|
|
||||||
echo 'Pushing to registry...'
|
|
||||||
echo "$REGISTRY_TOKEN" | docker login ${{ vars.PROD_REGISTRY }} -u ${{ vars.PROD_REGISTRY_USER }} --password-stdin
|
|
||||||
docker push "${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG"
|
|
||||||
|
|
||||||
echo 'Restarting Prod container...'
|
|
||||||
cd '${{ vars.PROD_COMPOSE_DIR }}'
|
|
||||||
# Drive the rc service image tag via its compose env-var (no sed on the shared
|
|
||||||
# file); remove any lingering fixed-name container first, then force-recreate.
|
|
||||||
docker rm -f '${{ vars.PROD_CONTAINER }}' 2>/dev/null || true
|
|
||||||
${{ vars.PROD_TAG_ENV }}="$TAG" docker compose -p '${{ vars.PROD_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.PROD_CONTAINER }}'
|
|
||||||
|
|
||||||
echo 'Health check...'
|
|
||||||
for i in 1 2 3 4 5 6 7 8; do
|
|
||||||
sleep 15
|
|
||||||
if docker inspect --format="$HEALTH_FMT" '${{ vars.PROD_CONTAINER }}' 2>/dev/null | grep -q healthy; then
|
|
||||||
echo 'Prod container healthy!'
|
|
||||||
exit 0
|
|
||||||
fi
|
fi
|
||||||
echo "Waiting... (attempt $i/8)"
|
rm -rf /tmp/mokocli
|
||||||
done
|
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||||
echo 'Health check failed'
|
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||||
docker logs '${{ vars.PROD_CONTAINER }}' --tail 20
|
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
||||||
exit 1
|
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||||
DEPLOY_EOF
|
fi
|
||||||
|
|
||||||
- name: Verify Prod instance
|
- name: Deploy (prod)
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
run: |
|
||||||
sleep 5
|
php ${MOKO_CLI}/deploy.php --tier prod --tag "${{ steps.config.outputs.tag }}" \
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.PROD_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.PROD_SSH_USERNAME }}@${{ vars.PROD_SSH_HOST }} "curl -sf '${{ vars.PROD_HEALTH_URL }}'" && echo " Prod API healthy"
|
--ssh-host ${{ vars.PROD_SSH_HOST }} --ssh-port ${{ vars.PROD_SSH_PORT }} \
|
||||||
|
--ssh-user ${{ vars.PROD_SSH_USERNAME }} --ssh-key ~/.ssh/deploy_key
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
# BRIEF: Build and deploy to the RC environment on push to the rc branch.
|
# BRIEF: Deploy to the RC environment on push to the rc branch via the
|
||||||
# Portable across Go server repos: ALL deployment config comes from repo
|
# restricted per-repo deploy pattern. This is a THIN trigger: it only
|
||||||
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
|
# validates the tier+tag and hands "<tier> <tag>" to the forced-command
|
||||||
|
# deploy-mokogit user over SSH (mokocli cli/deploy.php). The server-side
|
||||||
|
# forced command sudo's to a root-owned deployer that builds, pushes,
|
||||||
|
# recreates and health-checks — the runner never builds, holds a registry
|
||||||
|
# token, or runs the health check. See `.vault system/deploy` and runbook
|
||||||
|
# 16-restricted-deploy-pattern.
|
||||||
# The rc branch is created by promote-rc when a PR to main opens.
|
# The rc branch is created by promote-rc when a PR to main opens.
|
||||||
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
|
||||||
|
# NOTE: deploy-*.yml are repo-managed (per-repo deploy user + secrets/vars)
|
||||||
|
# and excluded from template sync — see mokocli workflow_sync PLATFORM_EXCLUDES['go'].
|
||||||
#
|
#
|
||||||
# Required repo VARIABLES (all tier-scoped so each environment is independent —
|
# Required repo VARIABLES:
|
||||||
# a repo may host its rc/dev/prod tiers on different machines):
|
|
||||||
# RC_SSH_HOST, RC_SSH_PORT, RC_SSH_USERNAME - SSH deploy target for the rc tier
|
# RC_SSH_HOST, RC_SSH_PORT, RC_SSH_USERNAME - SSH deploy target for the rc tier
|
||||||
# RC_REGISTRY, RC_REGISTRY_USER, RC_IMAGE - container registry + login user + image
|
# (RC_SSH_USERNAME = deploy-mokogit, the forced-command deploy user)
|
||||||
# RC_CONTAINER - compose service/container to recreate
|
# Required SECRETS (already configured; reused, not re-set):
|
||||||
# RC_COMPOSE_PROJECT - docker compose -p project name
|
# DEPLOY_SSH_KEY - deploy-mokogit private key (repo secret)
|
||||||
# RC_COMPOSE_DIR - dir containing docker-compose.yml on host
|
|
||||||
# RC_SOURCE_DIR - build source checkout on host
|
|
||||||
# RC_TAG_ENV - compose env-var name that pins the image tag
|
|
||||||
# RC_HEALTH_URL - external URL to verify after deploy
|
|
||||||
# Required SECRETS (already configured org-wide; reused, not re-set):
|
|
||||||
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
|
|
||||||
# MOKOGIT_TOKEN - registry/API token (org secret)
|
|
||||||
|
|
||||||
name: Deploy (RC)
|
name: Deploy (RC)
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-rc:
|
deploy-rc:
|
||||||
name: "Build & Deploy to RC"
|
name: "Deploy to RC"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source
|
- name: Checkout source
|
||||||
@@ -64,75 +63,29 @@ jobs:
|
|||||||
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
|
||||||
chmod 600 ~/.ssh/deploy_key
|
chmod 600 ~/.ssh/deploy_key
|
||||||
|
|
||||||
- name: Build and deploy to RC via SSH
|
- name: Setup MokoCLI tools
|
||||||
env:
|
env:
|
||||||
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||||
TAG: ${{ steps.config.outputs.tag }}
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
run: |
|
run: |
|
||||||
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
|
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
|
||||||
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
|
if [ -f /opt/mokocli/cli/deploy.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||||
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
|
echo Using pre-installed /opt/mokocli
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.RC_SSH_PORT }} \
|
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||||
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
else
|
||||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
|
echo Falling back to fresh clone
|
||||||
${{ vars.RC_SSH_USERNAME }}@${{ vars.RC_SSH_HOST }} \
|
if ! command -v composer > /dev/null 2>&1; then
|
||||||
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||||
set -e
|
|
||||||
echo 'SSH connected to RC environment'
|
|
||||||
|
|
||||||
if [ -z "$TAG" ]; then
|
|
||||||
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
HEALTH_FMT='{{.State.Health.Status}}'
|
|
||||||
|
|
||||||
echo 'Cleaning Docker build cache...'
|
|
||||||
docker builder prune -af 2>/dev/null || true
|
|
||||||
docker image prune -af 2>/dev/null || true
|
|
||||||
|
|
||||||
echo 'Pulling source...'
|
|
||||||
SOURCE_DIR='${{ vars.RC_SOURCE_DIR }}'
|
|
||||||
if [ ! -d "$SOURCE_DIR/.git" ]; then
|
|
||||||
git clone -b rc https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
|
|
||||||
fi
|
|
||||||
cd "$SOURCE_DIR"
|
|
||||||
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
|
|
||||||
git fetch origin rc
|
|
||||||
git reset --hard origin/rc
|
|
||||||
|
|
||||||
echo "Building image: ${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG"
|
|
||||||
docker build --no-cache --build-arg GOFLAGS='-p 1' \
|
|
||||||
--tag "${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG" \
|
|
||||||
-f Dockerfile .
|
|
||||||
|
|
||||||
echo 'Pushing to registry...'
|
|
||||||
echo "$REGISTRY_TOKEN" | docker login ${{ vars.RC_REGISTRY }} -u ${{ vars.RC_REGISTRY_USER }} --password-stdin
|
|
||||||
docker push "${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG"
|
|
||||||
|
|
||||||
echo 'Restarting RC container...'
|
|
||||||
cd '${{ vars.RC_COMPOSE_DIR }}'
|
|
||||||
# Drive the rc service image tag via its compose env-var (no sed on the shared
|
|
||||||
# file); remove any lingering fixed-name container first, then force-recreate.
|
|
||||||
docker rm -f '${{ vars.RC_CONTAINER }}' 2>/dev/null || true
|
|
||||||
${{ vars.RC_TAG_ENV }}="$TAG" docker compose -p '${{ vars.RC_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.RC_CONTAINER }}'
|
|
||||||
|
|
||||||
echo 'Health check...'
|
|
||||||
for i in 1 2 3 4 5 6 7 8; do
|
|
||||||
sleep 15
|
|
||||||
if docker inspect --format="$HEALTH_FMT" '${{ vars.RC_CONTAINER }}' 2>/dev/null | grep -q healthy; then
|
|
||||||
echo 'RC container healthy!'
|
|
||||||
exit 0
|
|
||||||
fi
|
fi
|
||||||
echo "Waiting... (attempt $i/8)"
|
rm -rf /tmp/mokocli
|
||||||
done
|
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||||
echo 'Health check failed'
|
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||||
docker logs '${{ vars.RC_CONTAINER }}' --tail 20
|
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
||||||
exit 1
|
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||||
DEPLOY_EOF
|
fi
|
||||||
|
|
||||||
- name: Verify RC instance
|
- name: Deploy (rc)
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
run: |
|
||||||
sleep 5
|
php ${MOKO_CLI}/deploy.php --tier rc --tag "${{ steps.config.outputs.tag }}" \
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ vars.RC_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.RC_SSH_USERNAME }}@${{ vars.RC_SSH_HOST }} "curl -sf '${{ vars.RC_HEALTH_URL }}'" && echo " RC API healthy"
|
--ssh-host ${{ vars.RC_SSH_HOST }} --ssh-port ${{ vars.RC_SSH_PORT }} \
|
||||||
|
--ssh-user ${{ vars.RC_SSH_USERNAME }} --ssh-key ~/.ssh/deploy_key
|
||||||
|
|||||||
Reference in New Issue
Block a user