Files
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

104 lines
3.8 KiB
Bash
Executable File

#!/bin/bash
#
# Aplica migrations do ConectaSUS para uma lista explicita de municipios.
#
# ./migrate.sh <ambiente> <tag> <municipio[,municipio...]>
#
# A migration roda em um container descartavel da imagem informada. Assim ela
# nao depende de qual versao esta no ar e usa os mesmos .env,
# connections.json e storage montados no host do ambiente.
set -euo pipefail
AMBIENTE="${1:-}"
TAG="${2:-}"
MUNICIPIOS_CSV="${3:-}"
REGISTRY="${REGISTRY:-192.168.0.41:3001}"
IMAGE_NAME="${IMAGE_NAME:-rkm/conectasus-api}"
AQUI="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
log() { echo "[migrate] $*"; }
fail() { echo "[migrate][ERRO] $*" >&2; exit 1; }
[ -n "${AMBIENTE}" ] || fail "uso: $0 <ambiente> <tag> <municipio[,municipio...]>"
[ -n "${TAG}" ] || fail "uso: $0 <ambiente> <tag> <municipio[,municipio...]>"
[ -n "${MUNICIPIOS_CSV}" ] || fail "informe ao menos um municipio"
ENV_FILE="${AQUI}/${AMBIENTE}.env"
[ -f "${ENV_FILE}" ] || fail "ambiente desconhecido: ${AMBIENTE} (esperado ${ENV_FILE})"
# shellcheck disable=SC1090
set -a; . "${ENV_FILE}"; set +a
if grep -q 'TROCAR' "${ENV_FILE}"; then
fail "${ENV_FILE} ainda tem valores de gabarito (TROCAR)."
fi
for v in CONFIG_DIR; do
[ -n "${!v:-}" ] || fail "${v} nao definido em ${ENV_FILE}"
done
IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
# Nomes de conexao do Laravel nao devem conter espacos nem caracteres que
# possam alterar a linha de comando. A lista e propositalmente explicita:
# conexoes tecnicas (por exemplo, sigtap) nao devem receber migrations por
# acidente.
IFS=',' read -r -a MUNICIPIOS_BRUTOS <<< "${MUNICIPIOS_CSV}"
declare -a MUNICIPIOS=()
declare -A VISTOS=()
for bruto in "${MUNICIPIOS_BRUTOS[@]}"; do
municipio="$(echo "${bruto}" | tr -d '[:space:]')"
[ -n "${municipio}" ] || fail "ha um municipio vazio na lista: ${MUNICIPIOS_CSV}"
[[ "${municipio}" =~ ^[A-Za-z0-9_-]+$ ]] || fail "nome de municipio invalido: ${municipio}"
[ -z "${VISTOS[${municipio}]:-}" ] || fail "municipio repetido na lista: ${municipio}"
VISTOS["${municipio}"]=1
MUNICIPIOS+=("${municipio}")
done
log "ambiente : ${AMBIENTE}"
log "imagem : ${IMAGE}"
log "municipios: ${MUNICIPIOS[*]}"
log "puxando ${IMAGE}"
docker pull "${IMAGE}" >/dev/null || fail "pull falhou (registry acessivel? credencial presente?)"
# --mount valida as fontes no host do Docker. Isso e essencial quando o job
# roda em container do act_runner, cujo filesystem nao contem CONFIG_DIR.
MOUNTS=(
--mount "type=bind,src=${CONFIG_DIR}/.env,dst=/var/www/api/.env,readonly"
--mount "type=bind,src=${CONFIG_DIR}/connections.json,dst=/var/www/api/connections.json,readonly"
--mount "type=bind,src=${CONFIG_DIR}/storage,dst=/var/www/api/storage"
)
PHP_RUN=(docker run --rm "${MOUNTS[@]}" --workdir /var/www/api --entrypoint php "${IMAGE}")
# Confere o JSON e todas as conexoes antes de alterar qualquer banco. Nao lista
# nem imprime o conteudo do arquivo, que pode conter credenciais.
for municipio in "${MUNICIPIOS[@]}"; do
if ! "${PHP_RUN[@]}" -r '
$connections = json_decode(file_get_contents("connections.json"), true);
if (!is_array($connections) || !array_key_exists($argv[1], $connections)) {
fwrite(STDERR, "conexao nao encontrada no connections.json: " . $argv[1] . PHP_EOL);
exit(1);
}
' "${municipio}"; then
fail "validacao da conexao falhou; nenhum banco recebeu migration"
fi
done
MIGRATE_RUN=("${PHP_RUN[@]}")
if [ -n "${NETWORK:-}" ]; then
MIGRATE_RUN=(docker run --rm --network "${NETWORK}" "${MOUNTS[@]}" --workdir /var/www/api --entrypoint php "${IMAGE}")
fi
total="${#MUNICIPIOS[@]}"
for i in "${!MUNICIPIOS[@]}"; do
municipio="${MUNICIPIOS[${i}]}"
log "[$((i + 1))/${total}] aplicando migrations em ${municipio}"
"${MIGRATE_RUN[@]}" artisan migrate --database="${municipio}" --force
done
log "migrations concluidas para ${total} municipio(s)"