Skip to content

Deploy Signup services using Helmsman #15

Deploy Signup services using Helmsman

Deploy Signup services using Helmsman #15

name: Deploy Signup services using Helmsman
on:
workflow_dispatch:
inputs:
profile:
description: "Deployment profile to use"
required: true
default: "esignet"
type: choice
options:
- esignet
- mosip-platform-1.2.0.x
- mosip-platform-1.2.1.x
mode:
description: "Choose Helmsman mode: dry-run or apply"
required: true
default: "dry-run"
type: choice
options:
- dry-run
- apply
delete_existing_jobs:
description: "Delete existing signup/kernel jobs before deployment (required for re-runs)"
required: false
default: false
type: boolean
domain_name:
description: "Domain name for this environment (e.g. example.xyz.net)"
required: true
type: string
env_name:
description: "Environment name (e.g. sandbox, dev, staging)"
required: false
type: string
push:
paths:
- Helmsman/dsf/**/signup-dsf.yaml
permissions:
actions: write
contents: read
jobs:
validate-inputs:
runs-on: ubuntu-latest
environment:
name: ${{ github.ref_name }}
steps:
- name: Validate required variables
run: |
errors=()
DOMAIN="${{ github.event.inputs.domain_name || vars.DOMAIN_NAME }}"
ENV="${{ github.event.inputs.env_name || vars.ENV_NAME }}"
[ -z "$DOMAIN" ] && errors+=("domain_name is empty — set vars.DOMAIN_NAME under Environment '${{ github.ref_name }}'")
[ -z "$ENV" ] && errors+=("env_name is empty — set vars.ENV_NAME under Environment '${{ github.ref_name }}'")
if [ ${#errors[@]} -gt 0 ]; then
echo "❌ Required variables missing:"
printf ' - %s\n' "${errors[@]}"
echo "Go to: Settings → Environments → ${{ github.ref_name }} → Variables"
exit 1
fi
echo "✓ domain_name = $DOMAIN"
echo "✓ env_name = $ENV"
deploy:
runs-on: ubuntu-latest
needs: validate-inputs
environment:
name: ${{ github.ref_name }}
env:
KUBECONFIG: ${{ github.workspace }}/.kube/config
PATH: ${{ github.workspace }}/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBECTL_PATH: ${{ github.workspace }}/.local/bin/kubectl
# Default value ensures env.HELMSMAN_MODE is always defined for if-conditions;
# the "Set Default Mode" step overrides it via GITHUB_ENV.
HELMSMAN_MODE: dry-run
domain_name: ${{ github.event.inputs.domain_name || vars.DOMAIN_NAME }}
env_name: ${{ github.event.inputs.env_name || vars.ENV_NAME }}
# Signup captcha secrets — configure as ENVIRONMENT secrets:
# Repository → Settings → Environments → <branch-name> → Secrets
MOSIP_SIGNUP_CAPTCHA_SITE_KEY: ${{ secrets.MOSIP_SIGNUP_CAPTCHA_SITE_KEY }}
MOSIP_SIGNUP_CAPTCHA_SECRET_KEY: ${{ secrets.MOSIP_SIGNUP_CAPTCHA_SECRET_KEY }}
# Cluster access secrets
KUBECONFIG_SECRET: ${{ secrets.KUBECONFIG }}
CLUSTER_WIREGUARD_WG0: ${{ secrets.CLUSTER_WIREGUARD_WG0 }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Persist workflow inputs as environment variables
if: github.event_name == 'workflow_dispatch'
env:
GH_TOKEN: ${{ secrets.GH_INFRA_PAT }}
run: |
REPO="${{ github.repository }}"
ENVIRONMENT="${{ github.ref_name }}"
ENCODED_ENVIRONMENT=$(python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=''))" "$ENVIRONMENT")
save_var() {
local name=$1 value=$2
if [ -z "$value" ]; then echo "⏭ Skipping $name — no input provided, existing value preserved"; return; fi
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH \
-H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/environments/$ENCODED_ENVIRONMENT/variables/$name" \
-d "{\"name\":\"$name\",\"value\":\"$value\"}")
if [ "$STATUS" = "404" ]; then
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/environments/$ENCODED_ENVIRONMENT/variables" \
-d "{\"name\":\"$name\",\"value\":\"$value\"}")
if [ "$STATUS" = "201" ]; then
echo "✓ Created $name"
else
echo "✗ Failed to create $name (HTTP $STATUS)"; exit 1
fi
elif [ "$STATUS" = "200" ] || [ "$STATUS" = "204" ]; then
echo "✓ Updated $name"
else
echo "✗ Failed to save $name (HTTP $STATUS)"; exit 1
fi
}
save_var "DOMAIN_NAME" "${{ github.event.inputs.domain_name }}"
save_var "ENV_NAME" "${{ github.event.inputs.env_name }}"
- name: Mask sensitive data
run: |
echo "::add-mask::${{ secrets.MOSIP_SIGNUP_CAPTCHA_SITE_KEY }}"
echo "::add-mask::${{ secrets.MOSIP_SIGNUP_CAPTCHA_SECRET_KEY }}"
echo "::add-mask::${{ secrets.KUBECONFIG }}"
echo "::add-mask::${{ secrets.CLUSTER_WIREGUARD_WG0 }}"
- name: Setup kubectl and kubeconfig
env:
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
run: |
mkdir -p ${{ github.workspace }}/.local/bin
mkdir -p ${{ github.workspace }}/.kube
curl -LO https://dl.k8s.io/release/v1.31.3/bin/linux/amd64/kubectl
chmod +x kubectl
mv ./kubectl ${{ github.workspace }}/.local/bin/kubectl
echo "$KUBECONFIG_CONTENT" > ${{ github.workspace }}/.kube/config
chmod 400 ${{ github.workspace }}/.kube/config
echo "${{ github.workspace }}/.local/bin" >> $GITHUB_PATH
echo "KUBECTL_PATH=${{ github.workspace }}/.local/bin/kubectl" >> $GITHUB_ENV
${{ github.workspace }}/.local/bin/kubectl version --client
${{ github.workspace }}/.local/bin/kubectl config view
- name: Set Default Mode
run: |
if [ -z "${{ github.event.inputs.mode }}" ]; then
echo "HELMSMAN_MODE=apply" >> $GITHUB_ENV
else
echo "HELMSMAN_MODE=${{ github.event.inputs.mode }}" >> $GITHUB_ENV
fi
- name: Set Profile
run: |
if [ -n "${{ github.event.inputs.profile }}" ]; then
PROFILE="${{ github.event.inputs.profile }}"
else
# push trigger — detect profile dir from changed signup-dsf.yaml path
BEFORE="${{ github.event.before }}"
SHA="${{ github.sha }}"
if [[ -z "$BEFORE" || "$BEFORE" == "0000000000000000000000000000000000000000" ]]; then
BEFORE="HEAD~1"
fi
CHANGED=$(git diff --name-only "$BEFORE" "$SHA" -- 'Helmsman/dsf/' 2>/dev/null || \
git diff --name-only HEAD~1 HEAD -- 'Helmsman/dsf/' 2>/dev/null || echo "")
PROFILE=$(echo "$CHANGED" | grep 'signup-dsf.yaml' | head -1 | sed 's|Helmsman/dsf/\([^/]*\)/.*|\1|')
if [[ -z "$PROFILE" ]]; then
echo "Error: could not detect profile from changed DSF files."
exit 1
fi
fi
echo "PROFILE=$PROFILE" >> "$GITHUB_ENV"
echo "Using profile: $PROFILE"
- name: Setup ufw firewall
run: |
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow 51820/udp
sudo ufw status
- name: Install WireGuard
run: sudo apt-get install -y wireguard
- name: Configure WireGuard
run: echo "${{ secrets.CLUSTER_WIREGUARD_WG0 }}" | sudo tee /etc/wireguard/wg0.conf > /dev/null
- name: Start WireGuard
run: |
sudo chmod 600 /etc/wireguard/wg0.conf
sudo chmod 700 /etc/wireguard/
sudo chmod 644 /lib/systemd/system/wg-quick@.service
sudo systemctl daemon-reload
sudo wg-quick up wg0
sudo wg show wg0
- name: Setup Helm
run: |
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
sudo chmod 700 get_helm.sh
sudo ./get_helm.sh
helm version --client
- name: Install Helmsman
run: |
curl -L https://github.com/Praqma/helmsman/releases/download/v3.17.1/helmsman_3.17.1_linux_amd64.tar.gz -o helmsman.tar.gz
tar xzf helmsman.tar.gz
sudo mv helmsman /usr/local/bin
kubectl version --client
helmsman -v
- name: Verify cluster access
run: |
kubectl version --client
kubectl get nodes
kubectl cluster-info
- name: Check eSignet DSF is completed
run: |
STATUS=$(kubectl get namespace default -o jsonpath='{.metadata.labels.esignet-dsf}' 2>/dev/null || echo "")
if [[ "$STATUS" != "completed" ]]; then
echo "❌ eSignet DSF not completed. Run the eSignet workflow first."
exit 1
fi
echo "✅ eSignet DSF is completed. Proceeding with signup deployment."
- name: Validate required secrets
run: |
MISSING=0
if [ -z "$MOSIP_SIGNUP_CAPTCHA_SITE_KEY" ]; then
echo "❌ MOSIP_SIGNUP_CAPTCHA_SITE_KEY secret is not configured"
MISSING=1
else
echo "✅ MOSIP_SIGNUP_CAPTCHA_SITE_KEY is configured"
fi
if [ -z "$MOSIP_SIGNUP_CAPTCHA_SECRET_KEY" ]; then
echo "❌ MOSIP_SIGNUP_CAPTCHA_SECRET_KEY secret is not configured"
MISSING=1
else
echo "✅ MOSIP_SIGNUP_CAPTCHA_SECRET_KEY is configured"
fi
if [ "$MISSING" -eq 1 ]; then
echo ""
echo "Configure missing secrets as ENVIRONMENT secrets:"
echo " Repository → Settings → Environments → ${{ github.ref_name }} → Add secret"
echo "Required: MOSIP_SIGNUP_CAPTCHA_SITE_KEY, MOSIP_SIGNUP_CAPTCHA_SECRET_KEY"
exit 1
fi
echo "All required secrets are configured"
- name: Set domain-derived environment variables for hooks
run: |
# Used by kernel-preinstall.sh (domain-config configmap) and
# signup-service-preinstall.sh (keycloak-host configmap)
echo "MOSIP_API_HOST=api.${domain_name}" >> $GITHUB_ENV
echo "MOSIP_API_INTERNAL_HOST=api-internal.${domain_name}" >> $GITHUB_ENV
echo "MOSIP_IAM_EXTERNAL_HOST=iam.${domain_name}" >> $GITHUB_ENV
echo "✓ MOSIP_API_HOST = api.${domain_name}"
echo "✓ MOSIP_API_INTERNAL_HOST = api-internal.${domain_name}"
echo "✓ MOSIP_IAM_EXTERNAL_HOST = iam.${domain_name}"
- name: Show deployment variables
run: |
echo "profile = $PROFILE"
echo "domain_name = $domain_name"
echo "env_name = $env_name"
echo "MOSIP_API_HOST = $MOSIP_API_HOST"
echo "MOSIP_API_INTERNAL_HOST = $MOSIP_API_INTERNAL_HOST"
echo "MOSIP_IAM_EXTERNAL_HOST = $MOSIP_IAM_EXTERNAL_HOST"
- name: Delete existing signup and kernel jobs (if requested)
if: ${{ github.event.inputs.delete_existing_jobs == 'true' }}
run: |
echo "Deleting existing jobs in signup and kernel namespaces..."
kubectl -n signup delete jobs --all --ignore-not-found=true || true
kubectl -n kernel delete jobs --all --ignore-not-found=true || true
echo "Cleanup completed."
- name: Deploy signup services using Helmsman
run: |
export HOME="${{ github.workspace }}"
export WORKDIR="$HOME/Helmsman"
echo "Using DSF: $WORKDIR/dsf/$PROFILE/signup-dsf.yaml"
helmsman --${HELMSMAN_MODE} --keep-untracked-releases -f $WORKDIR/dsf/$PROFILE/signup-dsf.yaml
- name: Label namespace on successful deployment
if: success() && env.HELMSMAN_MODE == 'apply'
run: |
kubectl label namespace default signup-dsf=completed --overwrite
echo "✅ Signup DSF deployment completed successfully"
- name: Deployment Summary
if: always()
run: |
echo "=================================="
echo "Signup Deployment Summary"
echo "=================================="
echo "Profile: $PROFILE"
echo "Mode: $HELMSMAN_MODE"
echo "Branch: ${{ github.ref_name }}"
echo "Commit: ${{ github.sha }}"
echo ""
echo "Signup pods status:"
kubectl get pods -n signup 2>/dev/null || echo "signup namespace not ready"
echo ""
echo "Kernel pods status:"
kubectl get pods -n kernel 2>/dev/null || echo "kernel namespace not ready"