added infisical integration
This commit is contained in:
@@ -1,3 +1,18 @@
|
|||||||
|
# ═══════════════════════════════════════════════════════════════════
|
||||||
|
# Secret richiesti (a livello repo/org, ereditati con `secrets: inherit`):
|
||||||
|
# DEPLOY_SSH_KEY, MAVEN_USERNAME, MAVEN_PASSWORD
|
||||||
|
# INFISICAL_CLIENT_ID, INFISICAL_CLIENT_SECRET, INFISICAL_PROJECT_ID
|
||||||
|
#
|
||||||
|
# INFISICAL: i secret applicativi vengono iniettati a runtime dalla CLI
|
||||||
|
# infisical installata SUL SERVER di deploy (nessun file di secret viene
|
||||||
|
# scritto su disco). L'environment Infisical coincide con il nome ambiente
|
||||||
|
# ricavato dai file (docker-compose-<env>.yml / .env_<env>).
|
||||||
|
# Il file .env_<env> del repo resta la base: le variabili iniettate da
|
||||||
|
# Infisical hanno precedenza, perché per docker compose l'ambiente della
|
||||||
|
# shell vince sui valori di --env-file.
|
||||||
|
# Se i secret INFISICAL_* non sono configurati il workflow si comporta
|
||||||
|
# esattamente come prima (nessuna iniezione).
|
||||||
|
# ═══════════════════════════════════════════════════════════════════
|
||||||
name: Deploy Environment (reusable)
|
name: Deploy Environment (reusable)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -40,6 +55,7 @@ jobs:
|
|||||||
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
||||||
DEPLOY_BASE_PATH: ${{ vars.DEPLOY_BASE_PATH }}
|
DEPLOY_BASE_PATH: ${{ vars.DEPLOY_BASE_PATH }}
|
||||||
TARGET_HOST: ${{ vars[inputs.host-var] }}
|
TARGET_HOST: ${{ vars[inputs.host-var] }}
|
||||||
|
INFISICAL_DOMAIN: ${{ vars.INFISICAL_HOST }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -87,6 +103,57 @@ jobs:
|
|||||||
chmod 600 ~/.ssh/id_ed25519
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
ssh-keyscan -H "${{ vars[inputs.host-var] }}" >> ~/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -H "${{ vars[inputs.host-var] }}" >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
# INFISICAL: login con machine identity (universal auth) sul
|
||||||
|
# server di deploy, dove la CLI è installata. Il login restituisce
|
||||||
|
# un access token a vita breve: è l'UNICA credenziale che viaggia
|
||||||
|
# negli step successivi, mentre client id/secret non escono da qui.
|
||||||
|
# Le credenziali sono passate via stdin e non come argomenti, così
|
||||||
|
# non compaiono nella process list del server (`ps`).
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
- name: Login Infisical
|
||||||
|
run: |
|
||||||
|
HOST="${{ vars[inputs.host-var] }}"
|
||||||
|
CID="${{ secrets.INFISICAL_CLIENT_ID }}"
|
||||||
|
CSEC="${{ secrets.INFISICAL_CLIENT_SECRET }}"
|
||||||
|
PID="${{ vars.INFISICAL_PROJECT_ID }}"
|
||||||
|
|
||||||
|
if [ -z "$CID" ] || [ -z "$CSEC" ] || [ -z "$PID" ]; then
|
||||||
|
echo "Secret INFISICAL_* non configurati: deploy senza iniezione dei secret (comportamento legacy)."
|
||||||
|
echo "IRUN_ENV=INFISICAL_TOKEN=" >> $GITHUB_ENV
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ssh ${DEPLOY_USER}@${HOST} "command -v infisical >/dev/null 2>&1"; then
|
||||||
|
echo "ERRORE: CLI 'infisical' non trovata su ${HOST}."
|
||||||
|
echo "Installala sul server oppure rimuovi i secret INFISICAL_* per tornare al deploy legacy."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOKEN=$(printf '%s\n%s\n%s\n' "$CID" "$CSEC" "$INFISICAL_DOMAIN" | ssh ${DEPLOY_USER}@${HOST} '
|
||||||
|
read -r cid
|
||||||
|
read -r csec
|
||||||
|
read -r dom
|
||||||
|
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$cid"
|
||||||
|
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$csec"
|
||||||
|
export INFISICAL_DOMAIN="$dom"
|
||||||
|
export INFISICAL_DISABLE_UPDATE_CHECK=true
|
||||||
|
infisical login --method=universal-auth --silent --plain
|
||||||
|
')
|
||||||
|
|
||||||
|
TOKEN=$(echo "$TOKEN" | tr -d '\r' | tail -n 1)
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
echo "ERRORE: login Infisical fallito su ${INFISICAL_DOMAIN}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "::add-mask::$TOKEN"
|
||||||
|
|
||||||
|
# Prefisso di ambiente riusato da tutti gli ssh successivi: viene
|
||||||
|
# letto da .irun.sh sul server per decidere se e come iniettare i
|
||||||
|
# secret. Il token è mascherato nei log.
|
||||||
|
echo "IRUN_ENV=INFISICAL_TOKEN='${TOKEN}' INFISICAL_PROJECT_ID='${PID}' INFISICAL_ENV='${ENV_NAME}' INFISICAL_DOMAIN='${INFISICAL_DOMAIN}' INFISICAL_DISABLE_UPDATE_CHECK=true" >> $GITHUB_ENV
|
||||||
|
echo "Login Infisical OK (${INFISICAL_DOMAIN}) - environment '${ENV_NAME}', path '/' ricorsivo."
|
||||||
|
|
||||||
- name: Docker login sul server
|
- name: Docker login sul server
|
||||||
run: |
|
run: |
|
||||||
HOST="${{ vars[inputs.host-var] }}"
|
HOST="${{ vars[inputs.host-var] }}"
|
||||||
@@ -114,9 +181,51 @@ jobs:
|
|||||||
|
|
||||||
ssh ${DEPLOY_USER}@${HOST} "mkdir -p ${REMOTE_PATH}"
|
ssh ${DEPLOY_USER}@${HOST} "mkdir -p ${REMOTE_PATH}"
|
||||||
|
|
||||||
|
# Wrapper unico per TUTTI i comandi che devono vedere i secret
|
||||||
|
# (docker compose pull/up/ps e gli script .wait-healthy.sh /
|
||||||
|
# .sync-fe-hosts.sh, che a loro volta invocano docker compose).
|
||||||
|
# Va copiato per primo: viene usato già dallo snapshot qui sotto
|
||||||
|
# e dallo step di rollback.
|
||||||
|
cat > /tmp/irun.sh << 'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
# Esegue il comando ricevuto iniettando i secret di Infisical come
|
||||||
|
# variabili d'ambiente del processo. Per docker compose l'ambiente
|
||||||
|
# della shell ha precedenza su --env-file: il file .env_<ambiente>
|
||||||
|
# del repo resta quindi la base e Infisical sovrascrive/integra.
|
||||||
|
# Se INFISICAL_TOKEN non e' valorizzato il comando viene eseguito
|
||||||
|
# tale e quale: comportamento legacy invariato.
|
||||||
|
set -e
|
||||||
|
CMD="$*"
|
||||||
|
|
||||||
|
if [ -z "${INFISICAL_TOKEN}" ]; then
|
||||||
|
exec sh -c "${CMD}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v infisical >/dev/null 2>&1; then
|
||||||
|
echo "ERRORE: CLI 'infisical' non installata su questo server." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --recursive non e' presente su tutte le versioni della CLI: lo si
|
||||||
|
# usa solo se supportato, evitando un "unknown flag" in produzione.
|
||||||
|
RFLAG=""
|
||||||
|
if infisical run --help 2>/dev/null | grep -q -- "--recursive"; then
|
||||||
|
RFLAG="--recursive"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec infisical run \
|
||||||
|
--projectId="${INFISICAL_PROJECT_ID}" \
|
||||||
|
--env="${INFISICAL_ENV}" \
|
||||||
|
--path=/ \
|
||||||
|
$RFLAG \
|
||||||
|
--command="${CMD}"
|
||||||
|
EOF
|
||||||
|
scp /tmp/irun.sh ${DEPLOY_USER}@${HOST}:${REMOTE_PATH}/.irun.sh
|
||||||
|
|
||||||
# Snapshot dello stato corrente PRIMA di sovrascrivere i file
|
# Snapshot dello stato corrente PRIMA di sovrascrivere i file
|
||||||
ssh ${DEPLOY_USER}@${HOST} "
|
ssh ${DEPLOY_USER}@${HOST} "
|
||||||
set -e
|
set -e
|
||||||
|
export ${IRUN_ENV:-INFISICAL_TOKEN=}
|
||||||
cd ${REMOTE_PATH}
|
cd ${REMOTE_PATH}
|
||||||
# Se esiste già uno .rollback, non cancellarlo: potrebbe essere l'unica
|
# Se esiste già uno .rollback, non cancellarlo: potrebbe essere l'unica
|
||||||
# traccia di un deploy precedente il cui rollback non è andato a buon
|
# traccia di un deploy precedente il cui rollback non è andato a buon
|
||||||
@@ -130,7 +239,7 @@ jobs:
|
|||||||
if [ -f ${COMPOSE} ]; then
|
if [ -f ${COMPOSE} ]; then
|
||||||
cp -f ${COMPOSE} .rollback/${COMPOSE}
|
cp -f ${COMPOSE} .rollback/${COMPOSE}
|
||||||
[ -f ${ENV_FILE} ] && cp -f ${ENV_FILE} .rollback/${ENV_FILE} || true
|
[ -f ${ENV_FILE} ] && cp -f ${ENV_FILE} .rollback/${ENV_FILE} || true
|
||||||
ids=\$(docker compose -f ${COMPOSE} ${ENVFLAG} ps -q 2>/dev/null || true)
|
ids=\$(sh .irun.sh \"docker compose -f ${COMPOSE} ${ENVFLAG} ps -q\" 2>/dev/null || true)
|
||||||
if [ -n \"\$ids\" ]; then
|
if [ -n \"\$ids\" ]; then
|
||||||
echo 'services:' > .rollback/pin.yml
|
echo 'services:' > .rollback/pin.yml
|
||||||
for cid in \$ids; do
|
for cid in \$ids; do
|
||||||
@@ -329,8 +438,11 @@ jobs:
|
|||||||
CBASE="cd ${REMOTE_PATH} && DOCKER_CONFIG=/tmp/.docker-ci docker compose -f ${COMPOSE}"
|
CBASE="cd ${REMOTE_PATH} && DOCKER_CONFIG=/tmp/.docker-ci docker compose -f ${COMPOSE}"
|
||||||
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
||||||
|
|
||||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} pull"
|
# I comandi passano da .irun.sh: i secret Infisical vengono iniettati
|
||||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} up -d ${{ inputs.compose-opts }}"
|
# nel processo docker compose (interpolazione ${VAR} nel compose file
|
||||||
|
# e blocchi "environment:"), senza mai finire su disco.
|
||||||
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh '${CBASE} pull'"
|
||||||
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh '${CBASE} up -d ${{ inputs.compose-opts }}'"
|
||||||
|
|
||||||
- name: Post-deploy
|
- name: Post-deploy
|
||||||
run: |
|
run: |
|
||||||
@@ -366,15 +478,15 @@ jobs:
|
|||||||
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
||||||
|
|
||||||
echo "── Container status (iniziale) ──"
|
echo "── Container status (iniziale) ──"
|
||||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} ps"
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh '${CBASE} ps'"
|
||||||
|
|
||||||
# Attende che tutti i container siano "running" e, se hanno un
|
# Attende che tutti i container siano "running" e, se hanno un
|
||||||
# healthcheck definito, "healthy" (vedi .wait-healthy.sh, creato
|
# healthcheck definito, "healthy" (vedi .wait-healthy.sh, creato
|
||||||
# nello step "Prepara server" e condiviso con il rollback).
|
# nello step "Prepara server" e condiviso con il rollback).
|
||||||
ssh ${DEPLOY_USER}@${HOST} "cd ${REMOTE_PATH} && sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}"
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh 'cd ${REMOTE_PATH} && sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}'"
|
||||||
|
|
||||||
echo "── Container status (finale) ──"
|
echo "── Container status (finale) ──"
|
||||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} ps"
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh '${CBASE} ps'"
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# HOSTS: dopo un deploy riuscito, recuperiamo l'IP del container
|
# HOSTS: dopo un deploy riuscito, recuperiamo l'IP del container
|
||||||
@@ -393,7 +505,7 @@ jobs:
|
|||||||
COMPOSE="docker-compose-${ENV_NAME}.yml"
|
COMPOSE="docker-compose-${ENV_NAME}.yml"
|
||||||
ENV_FILE=".env_${ENV_NAME}"
|
ENV_FILE=".env_${ENV_NAME}"
|
||||||
|
|
||||||
ssh ${DEPLOY_USER}@${HOST} "cd ${REMOTE_PATH} && sh .sync-fe-hosts.sh ${COMPOSE} ${ENV_FILE}"
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV} sh ${REMOTE_PATH}/.irun.sh 'cd ${REMOTE_PATH} && sh .sync-fe-hosts.sh ${COMPOSE} ${ENV_FILE}'"
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# CLEANUP: eseguito SOLO se tutti gli step precedenti sono andati
|
# CLEANUP: eseguito SOLO se tutti gli step precedenti sono andati
|
||||||
@@ -479,6 +591,7 @@ jobs:
|
|||||||
container_ok=0
|
container_ok=0
|
||||||
ssh ${DEPLOY_USER}@${HOST} "
|
ssh ${DEPLOY_USER}@${HOST} "
|
||||||
set -e
|
set -e
|
||||||
|
export ${IRUN_ENV:-INFISICAL_TOKEN=}
|
||||||
cd ${REMOTE_PATH}
|
cd ${REMOTE_PATH}
|
||||||
if [ -f .rollback/${COMPOSE} ]; then
|
if [ -f .rollback/${COMPOSE} ]; then
|
||||||
cp -f .rollback/${COMPOSE} ${COMPOSE}
|
cp -f .rollback/${COMPOSE} ${COMPOSE}
|
||||||
@@ -486,9 +599,9 @@ jobs:
|
|||||||
PIN=''
|
PIN=''
|
||||||
[ -f .rollback/pin.yml ] && PIN='-f .rollback/pin.yml'
|
[ -f .rollback/pin.yml ] && PIN='-f .rollback/pin.yml'
|
||||||
echo 'Ripristino container alla versione precedente...'
|
echo 'Ripristino container alla versione precedente...'
|
||||||
DOCKER_CONFIG=/tmp/.docker-ci docker compose -f ${COMPOSE} \$PIN ${ENVFLAG} up -d
|
sh .irun.sh \"DOCKER_CONFIG=/tmp/.docker-ci docker compose -f ${COMPOSE} \$PIN ${ENVFLAG} up -d\"
|
||||||
echo 'Attendo che i container ripristinati siano running/healthy...'
|
echo 'Attendo che i container ripristinati siano running/healthy...'
|
||||||
sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}
|
sh .irun.sh \"sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}\"
|
||||||
else
|
else
|
||||||
echo 'Nessuno snapshot disponibile: nessun rollback container (probabile primo deploy).'
|
echo 'Nessuno snapshot disponibile: nessun rollback container (probabile primo deploy).'
|
||||||
fi
|
fi
|
||||||
@@ -503,7 +616,7 @@ jobs:
|
|||||||
# deploy fallito (o, se prima non c'era una voce, nessuna voce),
|
# deploy fallito (o, se prima non c'era una voce, nessuna voce),
|
||||||
# puntando a un container che non esiste più.
|
# puntando a un container che non esiste più.
|
||||||
hosts_ok=0
|
hosts_ok=0
|
||||||
ssh ${DEPLOY_USER}@${HOST} "cd ${REMOTE_PATH} && sh .sync-fe-hosts.sh ${COMPOSE} ${ENV_FILE}" || hosts_ok=1
|
ssh ${DEPLOY_USER}@${HOST} "${IRUN_ENV:-INFISICAL_TOKEN=} sh ${REMOTE_PATH}/.irun.sh 'cd ${REMOTE_PATH} && sh .sync-fe-hosts.sh ${COMPOSE} ${ENV_FILE}'" || hosts_ok=1
|
||||||
|
|
||||||
# Cleanup config temporaneo (best-effort, non deve mascherare l'esito del rollback)
|
# Cleanup config temporaneo (best-effort, non deve mascherare l'esito del rollback)
|
||||||
ssh ${DEPLOY_USER}@${HOST} "rm -rf /tmp/.docker-ci" || true
|
ssh ${DEPLOY_USER}@${HOST} "rm -rf /tmp/.docker-ci" || true
|
||||||
|
|||||||
Reference in New Issue
Block a user