#14: Gitea CI, registry composes, Node 22 image and changelog
- Gitea Actions: Trivy, Vitest in a Dockerfile test stage, arm64 image build, image scan and smoke test; releases reuse the image by content hash. - docker-compose.<edition>.registry.yaml run the stack from the published image. - Dockerfile: Node 22, a test stage, and no npm in the runtime image. - README, CLAUDE.md and CHANGELOG describe the CI, the image and the release flow. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
640e52c0c9
commit
a4a2584f37
12 files changed
+606
-9
No files matched your search
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
# Teste de fumaça da imagem do CraftDock, sem o servidor de Minecraft: o painel sobe,
|
||||
# serve a interface, recusa quem não está logado, traz os ícones gerados no build e o
|
||||
# healthcheck da própria imagem fica saudável.
|
||||
#
|
||||
# scripts/smoke-imagem.sh <imagem>
|
||||
#
|
||||
# Cada falha é impressa e o script sai com 1 no fim, para mostrar tudo de uma vez.
|
||||
set -uo pipefail
|
||||
|
||||
imagem=${1:?uso: smoke-imagem.sh <imagem>}
|
||||
app=craftdock-smoke-${GITHUB_RUN_ID:-$$}
|
||||
falhas=0
|
||||
falhou() { echo "FALHOU $1"; falhas=$((falhas + 1)); }
|
||||
|
||||
# Os daemons dos runners persistem entre jobs: limpa sempre, inclusive se falhar.
|
||||
trap 'docker rm -f "$app" >/dev/null 2>&1' EXIT
|
||||
|
||||
# Valores descartáveis. O hash é o de teste que a suíte já usa (config.test.js); a
|
||||
# senha dele não importa aqui, o smoke não faz login. Sem docker.sock: o painel sobe e
|
||||
# só as rotas que falam com o Docker deixam de funcionar.
|
||||
hash='$2a$12$YjrtHh2BNcUT0P76L2ZUF.mCtxzUwN.gZ4siUqji2oxrDbIXRdvfe'
|
||||
docker run -d --name "$app" \
|
||||
-e ADMIN_PASSWORD_HASH_B64="$(printf %s "$hash" | base64 -w0)" \
|
||||
-e SESSION_SECRET=segredo-do-smoke \
|
||||
"$imagem" >/dev/null || exit 1
|
||||
|
||||
ip=""
|
||||
for _ in $(seq 1 40); do
|
||||
ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$app" 2>/dev/null)
|
||||
[ -n "$ip" ] && curl -fsS -o /dev/null "http://$ip:3000/api/health" 2>/dev/null && break
|
||||
sleep 1
|
||||
done
|
||||
base=http://$ip:3000
|
||||
curl -fsS -o /dev/null "$base/api/health" || { echo "FALHOU /api/health: sem resposta"; docker logs "$app" | tail -20; exit 1; }
|
||||
|
||||
status() { [ "$(curl -s -o /dev/null -w '%{http_code}' "$base$2")" = "$1" ] || falhou "$2: esperado $1"; }
|
||||
|
||||
status 200 /
|
||||
status 200 /api/health
|
||||
# Tudo sob /api, menos auth e health, exige sessão.
|
||||
status 401 /api/status
|
||||
status 401 /api/players
|
||||
status 401 /api/properties
|
||||
status 401 /api/world
|
||||
|
||||
curl -s "$base/" | grep -qi 'craftdock' || falhou "/: a interface não carregou"
|
||||
curl -s "$base/api/health" | grep -q '"status":"ok"' || falhou "/api/health: corpo inesperado"
|
||||
|
||||
# Os ícones de itens são gerados no build (não ficam no repositório).
|
||||
n=$(docker exec "$app" sh -c 'ls /app/src/public/assets/mc 2>/dev/null | wc -l')
|
||||
[ "${n:-0}" -gt 0 ] || falhou "os ícones do Minecraft não foram gerados no build"
|
||||
|
||||
# O addon nativo do LevelDB (leitura de mundos Bedrock) carrega na imagem final.
|
||||
docker exec "$app" node -e "import('leveldb-zlib').then(()=>process.exit(0)).catch(e=>{console.error(e.message);process.exit(1)})" || falhou "leveldb-zlib não carrega"
|
||||
|
||||
# O healthcheck da própria imagem (src/healthcheck.js) reporta saudável.
|
||||
for _ in $(seq 1 30); do
|
||||
estado=$(docker inspect -f '{{.State.Health.Status}}' "$app" 2>/dev/null)
|
||||
[ "$estado" = healthy ] && break
|
||||
sleep 2
|
||||
done
|
||||
[ "$estado" = healthy ] || falhou "o healthcheck da imagem não ficou healthy (estado: ${estado:-nenhum})"
|
||||
|
||||
[ "$falhas" = 0 ] && echo "ok: interface, autenticação, ícones, LevelDB e healthcheck conferidos"
|
||||
[ "$falhas" = 0 ]
|
||||
Reference in new issue
Block a user