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)
|
||||
|
||||
on:
|
||||
@@ -40,6 +55,7 @@ jobs:
|
||||
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
||||
DEPLOY_BASE_PATH: ${{ vars.DEPLOY_BASE_PATH }}
|
||||
TARGET_HOST: ${{ vars[inputs.host-var] }}
|
||||
INFISICAL_DOMAIN: ${{ vars.INFISICAL_HOST }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -87,6 +103,57 @@ jobs:
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
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
|
||||
run: |
|
||||
HOST="${{ vars[inputs.host-var] }}"
|
||||
@@ -114,9 +181,51 @@ jobs:
|
||||
|
||||
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
|
||||
ssh ${DEPLOY_USER}@${HOST} "
|
||||
set -e
|
||||
export ${IRUN_ENV:-INFISICAL_TOKEN=}
|
||||
cd ${REMOTE_PATH}
|
||||
# Se esiste già uno .rollback, non cancellarlo: potrebbe essere l'unica
|
||||
# traccia di un deploy precedente il cui rollback non è andato a buon
|
||||
@@ -130,7 +239,7 @@ jobs:
|
||||
if [ -f ${COMPOSE} ]; then
|
||||
cp -f ${COMPOSE} .rollback/${COMPOSE}
|
||||
[ -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
|
||||
echo 'services:' > .rollback/pin.yml
|
||||
for cid in \$ids; do
|
||||
@@ -329,8 +438,11 @@ jobs:
|
||||
CBASE="cd ${REMOTE_PATH} && DOCKER_CONFIG=/tmp/.docker-ci docker compose -f ${COMPOSE}"
|
||||
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
||||
|
||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} pull"
|
||||
ssh ${DEPLOY_USER}@${HOST} "${CBASE} up -d ${{ inputs.compose-opts }}"
|
||||
# I comandi passano da .irun.sh: i secret Infisical vengono iniettati
|
||||
# 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
|
||||
run: |
|
||||
@@ -366,15 +478,15 @@ jobs:
|
||||
[ -f "$ENV_FILE" ] && CBASE="${CBASE} --env-file ${ENV_FILE}"
|
||||
|
||||
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
|
||||
# healthcheck definito, "healthy" (vedi .wait-healthy.sh, creato
|
||||
# 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) ──"
|
||||
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
|
||||
@@ -393,7 +505,7 @@ jobs:
|
||||
COMPOSE="docker-compose-${ENV_NAME}.yml"
|
||||
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
|
||||
@@ -479,6 +591,7 @@ jobs:
|
||||
container_ok=0
|
||||
ssh ${DEPLOY_USER}@${HOST} "
|
||||
set -e
|
||||
export ${IRUN_ENV:-INFISICAL_TOKEN=}
|
||||
cd ${REMOTE_PATH}
|
||||
if [ -f .rollback/${COMPOSE} ]; then
|
||||
cp -f .rollback/${COMPOSE} ${COMPOSE}
|
||||
@@ -486,9 +599,9 @@ jobs:
|
||||
PIN=''
|
||||
[ -f .rollback/pin.yml ] && PIN='-f .rollback/pin.yml'
|
||||
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...'
|
||||
sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}
|
||||
sh .irun.sh \"sh .wait-healthy.sh ${COMPOSE} ${ENV_FILE} ${TIMEOUT}\"
|
||||
else
|
||||
echo 'Nessuno snapshot disponibile: nessun rollback container (probabile primo deploy).'
|
||||
fi
|
||||
@@ -503,7 +616,7 @@ jobs:
|
||||
# deploy fallito (o, se prima non c'era una voce, nessuna voce),
|
||||
# puntando a un container che non esiste più.
|
||||
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)
|
||||
ssh ${DEPLOY_USER}@${HOST} "rm -rf /tmp/.docker-ci" || true
|
||||
|
||||
Reference in New Issue
Block a user