ci: a real smoke test for the localized routes, and a single redirect from the root
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cbf724db2a
commit
3a1a095e97
4 files changed
+78
-7
No files matched your search
@@ -99,17 +99,20 @@ jobs:
|
|||||||
docker run --rm --network host -v trivy-cache:/root/.cache/ -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \
|
docker run --rm --network host -v trivy-cache:/root/.cache/ -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \
|
||||||
image --severity HIGH,CRITICAL --exit-code 1 espdocs:ci
|
image --severity HIGH,CRITICAL --exit-code 1 espdocs:ci
|
||||||
|
|
||||||
|
# Rotas por idioma, redirects e regras do livro (scripts/smoke-imagem.sh).
|
||||||
|
# Um curl só na raiz não basta: ela redireciona, e uma página interna
|
||||||
|
# quebrada ainda passaria.
|
||||||
- name: A imagem sobe e responde
|
- name: A imagem sobe e responde
|
||||||
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
docker run -d --name espdocs-ci --network host -e PORT=3999 espdocs:ci
|
docker run -d --name espdocs-ci --network host -e PORT=3999 espdocs:ci
|
||||||
for i in $(seq 1 30); do
|
status=0
|
||||||
curl -fsS http://127.0.0.1:3999/ >/dev/null && ok=1 && break
|
scripts/smoke-imagem.sh http://127.0.0.1:3999 || status=1
|
||||||
sleep 2
|
docker logs espdocs-ci | tail -15
|
||||||
done
|
# O Next registra falhas de render no log mesmo quando responde.
|
||||||
docker logs espdocs-ci | tail -5
|
if docker logs espdocs-ci 2>&1 | grep -q '⨯'; then echo "O servidor registrou erro de render"; status=1; fi
|
||||||
docker rm -f espdocs-ci >/dev/null
|
docker rm -f espdocs-ci >/dev/null
|
||||||
test "${ok:-0}" = 1
|
exit "$status"
|
||||||
|
|
||||||
# Passou em tudo: publica a mesma imagem que foi testada, sem reconstruir.
|
# Passou em tudo: publica a mesma imagem que foi testada, sem reconstruir.
|
||||||
- name: Publica inputs-<hash>
|
- name: Publica inputs-<hash>
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ Tudo o que muda de relevante no ESPDocs está aqui. O formato segue o
|
|||||||
- Conjunto de dados canônicos em `data/pt/` (`series.json`, `frameworks.json`, `conexoes/*.json`) e módulos em `lib/data/pt/` (`glossario.js`, `diagnostico.js`, `componentes.js`, `topicos.js`) com carregadores por locale em `lib/data/index.js`.
|
- Conjunto de dados canônicos em `data/pt/` (`series.json`, `frameworks.json`, `conexoes/*.json`) e módulos em `lib/data/pt/` (`glossario.js`, `diagnostico.js`, `componentes.js`, `topicos.js`) com carregadores por locale em `lib/data/index.js`.
|
||||||
- Script automatizado de validação `check:i18n` integrado ao `npm run check`, verificando paridade de chaves, ausência de valores vazios e garantia estrita de ausência de referências ao livro fora do português.
|
- Script automatizado de validação `check:i18n` integrado ao `npm run check`, verificando paridade de chaves, ausência de valores vazios e garantia estrita de ausência de referências ao livro fora do português.
|
||||||
|
|
||||||
|
### Alterado
|
||||||
|
|
||||||
|
- O teste de subida da imagem na CI virou `scripts/smoke-imagem.sh`: confere as
|
||||||
|
rotas de cada idioma, a negociação de `Accept-Language`, os redirects 308 das
|
||||||
|
URLs antigas, o 404 do livro fora do português e a metadata no `<head>`, e
|
||||||
|
falha se o servidor registrar erro de render. O `curl` só na raiz deixou passar
|
||||||
|
uma home quebrada.
|
||||||
|
- A metadata (título, `canonical`, Open Graph) sempre sai no `<head>` do HTML
|
||||||
|
inicial, para qualquer cliente, como já era antes do i18n.
|
||||||
|
- A raiz `/` redireciona direto para `/<idioma>`, em um salto só.
|
||||||
|
|
||||||
## [1.1.0] - 2026-11-01
|
## [1.1.0] - 2026-11-01
|
||||||
|
|
||||||
### Adicionado
|
### Adicionado
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ export default function middleware(request) {
|
|||||||
// 1. Raiz: negociação de idioma (307)
|
// 1. Raiz: negociação de idioma (307)
|
||||||
if (pathname === "/") {
|
if (pathname === "/") {
|
||||||
const targetLocale = resolveRootLocale(request);
|
const targetLocale = resolveRootLocale(request);
|
||||||
const url = new URL(`/${targetLocale}/`, request.url);
|
const url = new URL(`/${targetLocale}`, request.url);
|
||||||
url.search = search;
|
url.search = search;
|
||||||
const response = NextResponse.redirect(url, 307);
|
const response = NextResponse.redirect(url, 307);
|
||||||
response.headers.set("Vary", "Accept-Language, Cookie");
|
response.headers.set("Vary", "Accept-Language, Cookie");
|
||||||
|
|||||||
Executable
+57
@@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Teste de fumaça do servidor: rotas por idioma, redirects e regras do livro.
|
||||||
|
#
|
||||||
|
# scripts/smoke-imagem.sh http://127.0.0.1:3999
|
||||||
|
#
|
||||||
|
# Cada falha é impressa e o script sai com 1 no fim, para mostrar tudo de uma vez.
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
base=${1:?uso: smoke-imagem.sh <url-base>}
|
||||||
|
falhas=0
|
||||||
|
|
||||||
|
# status <esperado> <caminho> [cabeçalho]
|
||||||
|
status() {
|
||||||
|
local got
|
||||||
|
got=$(curl -s -o /dev/null -w '%{http_code}' ${3:+-H "$3"} "$base$2")
|
||||||
|
[ "$got" = "$1" ] || { echo "FALHOU $2 ${3:-}: esperado $1, veio $got"; falhas=$((falhas + 1)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
# destino <status> <caminho> <redirecionamento esperado> [cabeçalho]
|
||||||
|
destino() {
|
||||||
|
local out
|
||||||
|
out=$(curl -s -o /dev/null -w '%{http_code} %{redirect_url}' ${4:+-H "$4"} "$base$2")
|
||||||
|
[ "$out" = "$1 $base$3" ] || { echo "FALHOU $2 ${4:-}: esperado '$1 $3', veio '${out#* }'" ; falhas=$((falhas + 1)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
# O servidor leva alguns segundos para subir.
|
||||||
|
for _ in $(seq 1 30); do curl -fsS -o /dev/null "$base/pt" && break; sleep 2; done
|
||||||
|
|
||||||
|
# Páginas que existem em todos os idiomas ativos (a home é a que mais depende do render no servidor).
|
||||||
|
for l in pt en es fr de zh-CN; do status 200 "/$l"; done
|
||||||
|
for p in /series /sobre /livro; do status 200 "/pt$p"; done
|
||||||
|
|
||||||
|
# Negociação de idioma na raiz.
|
||||||
|
destino 307 / /pt 'Accept-Language: pt-BR,pt;q=0.9'
|
||||||
|
destino 307 / /es 'Accept-Language: es-MX,es;q=0.9,en;q=0.5'
|
||||||
|
destino 307 / /fr 'Accept-Language: fr-CA,fr;q=0.9'
|
||||||
|
destino 307 / /de 'Accept-Language: de-AT,de;q=0.8'
|
||||||
|
destino 307 / /zh-CN 'Accept-Language: zh-CN,zh;q=0.9'
|
||||||
|
destino 307 / /en 'Accept-Language: it-IT'
|
||||||
|
destino 307 / /pt 'Accept-Language: en;q=0.5,pt;q=0.9'
|
||||||
|
destino 307 / /es 'Cookie: NEXT_LOCALE=es'
|
||||||
|
|
||||||
|
# URLs antigas (sem prefixo) eram em português.
|
||||||
|
destino 308 /series/ESP32-S3 /pt/series/ESP32-S3 'Accept-Language: en-US'
|
||||||
|
destino 308 /livro /pt/livro 'Accept-Language: en-US'
|
||||||
|
|
||||||
|
# O livro existe só em português.
|
||||||
|
for l in en es fr de zh-CN; do status 404 "/$l/livro"; done
|
||||||
|
|
||||||
|
# Metadata no <head> inicial (title, canonical, hreflang), para qualquer cliente.
|
||||||
|
html=$(curl -s -A 'Mozilla/5.0 Chrome/130' "$base/pt/sobre")
|
||||||
|
head=${html%%</head>*}
|
||||||
|
for marca in '<title>' 'rel="canonical"'; do
|
||||||
|
case "$head" in *"$marca"*) ;; *) echo "FALHOU /pt/sobre: $marca fora do <head>"; falhas=$((falhas + 1));; esac
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $((falhas > 0))
|
||||||
Reference in new issue
Block a user