diff --git a/.github/scripts/setup-docker-prune-cron.sh b/.github/scripts/setup-docker-prune-cron.sh new file mode 100644 index 0000000..24f5e46 --- /dev/null +++ b/.github/scripts/setup-docker-prune-cron.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +CRON_CMD="0 3 * * 0 docker system prune -af --volumes > /var/log/docker-prune.log 2>&1" + +echo "[INFO] Configurando limpeza semanal do Docker via cron..." + +# Verifica se já existe a regra no cron do root +if sudo crontab -l 2>/dev/null | grep -q "docker system prune -af --volumes"; then + echo "[INFO] Já existe uma regra de prune configurada no cron. Nada a fazer." +else + # Adiciona a regra ao cron do root + (sudo crontab -l 2>/dev/null; echo "$CRON_CMD") | sudo crontab - + echo "[INFO] Cron configurado: limpeza semanal todo domingo às 03h." +fi + +echo "[INFO] Você pode verificar o log em /var/log/docker-prune.log" diff --git a/.github/scripts/start-preview.sh b/.github/scripts/start-preview.sh index e3a577f..fc35d7d 100644 --- a/.github/scripts/start-preview.sh +++ b/.github/scripts/start-preview.sh @@ -2,30 +2,46 @@ set -e PR_NUMBER=$1 -PORT=$((8000 + PR_NUMBER % 1000)) # porta única para cada PR APP_NAME="simple-project-pr${PR_NUMBER}" NGROK_NAME="ngrok-pr${PR_NUMBER}" +HOST_PORT=$((8000 + PR_NUMBER)) +API_PORT=$((4040 + PR_NUMBER)) -echo "[INFO] Iniciando preview para PR #${PR_NUMBER} na porta ${PORT}" +echo "[INFO] Iniciando preview para PR #${PR_NUMBER} na porta ${HOST_PORT}" -# Se container já existe, remover para atualizar -docker rm -f ${APP_NAME} || true +# Garantir que não há containers anteriores +docker rm -f ${APP_NAME} 2>/dev/null || true +docker rm -f ${NGROK_NAME} 2>/dev/null || true -# Build imagem docker +# Build da imagem sem cache +echo "[INFO] Build da imagem Docker..." docker build -t ${APP_NAME}:latest . -# Rodar container da app -docker run -d --name ${APP_NAME} -p ${PORT}:8080 ${APP_NAME}:latest - -# Matar ngrok anterior se existir -pkill -f "${NGROK_NAME}" || true - -# Rodar ngrok apontando para porta do container -nohup ngrok http ${PORT} --name ${NGROK_NAME} > /tmp/${NGROK_NAME}.log 2>&1 & - -# Esperar ngrok subir e pegar URL -sleep 5 -URL=$(curl --silent http://127.0.0.1:4040/api/tunnels | jq -r ".tunnels[] | select(.config.addr==\"http://localhost:${PORT}\") | .public_url") - -echo "[INFO] Preview URL: ${URL}" -echo "${URL}" +# Rodar o container da aplicação +echo "[INFO] Subindo container da aplicação ${APP_NAME}..." +docker run -d --name ${APP_NAME} -p ${HOST_PORT}:8080 ${APP_NAME}:latest + +# Rodar o container do ngrok expondo API na porta 4040+PR_NUMBER +echo "[INFO] Subindo container do ngrok ${NGROK_NAME}..." +docker run -d --name ${NGROK_NAME} \ + -e NGROK_AUTHTOKEN="${NGROK_AUTHTOKEN}" \ + -p ${API_PORT}:4040 \ + ngrok/ngrok:latest http host.docker.internal:${HOST_PORT} > /tmp/${NGROK_NAME}.log 2>&1 + +# Aguardar o ngrok iniciar e capturar a URL pela API +echo "[INFO] Aguardando ngrok inicializar na porta ${API_PORT}..." +for i in {1..10}; do + sleep 2 + URL=$(curl -s http://127.0.0.1:${API_PORT}/api/tunnels | grep -o 'https://[0-9a-z]*\.ngrok-free\.app' | head -n 1 || true) + if [ -n "$URL" ]; then + break + fi +done + +if [ -z "$URL" ]; then + echo "[ERRO] Não foi possível capturar a URL do Ngrok. Veja os logs em /tmp/${NGROK_NAME}.log" + exit 1 +fi + +echo "[INFO] URL pública gerada: $URL" +echo "$URL" diff --git a/.github/scripts/stop-preview.sh b/.github/scripts/stop-preview.sh index 66e2e2b..861567a 100644 --- a/.github/scripts/stop-preview.sh +++ b/.github/scripts/stop-preview.sh @@ -7,8 +7,28 @@ NGROK_NAME="ngrok-pr${PR_NUMBER}" echo "[INFO] Removendo preview para PR #${PR_NUMBER}" -# Parar container e remover -docker rm -f ${APP_NAME} || true +# Se o container da aplicação existir mas estiver em estado de falha, mostrar logs antes de remover +if docker ps -a --format '{{.Names}} {{.Status}}' | grep -q "${APP_NAME}"; then + STATUS=$(docker inspect -f '{{.State.Status}}' ${APP_NAME} || echo "desconhecido") + if [ "$STATUS" != "running" ]; then + echo "[WARN] Container ${APP_NAME} não está rodando (status: $STATUS). Exibindo últimos logs:" + docker logs --tail=100 ${APP_NAME} || true + fi +fi -# Matar ngrok correspondente -pkill -f "${NGROK_NAME}" || true +# Parar e remover container da aplicação +docker rm -f ${APP_NAME} >/dev/null 2>&1 || true + +# Remover imagem associada ao PR (se existir) +docker rmi -f ${APP_NAME}:latest >/dev/null 2>&1 || true + +# Parar e remover container do ngrok +docker rm -f ${NGROK_NAME} >/dev/null 2>&1 || true + +# Extra: limpar eventuais containers órfãos do mesmo PR +docker ps -a --format '{{.Names}}' | grep -E "${APP_NAME}|${NGROK_NAME}" | xargs -r docker rm -f || true + +# Extra: limpar eventuais imagens órfãs +docker image prune -f >/dev/null 2>&1 || true + +echo "[INFO] Preview do PR #${PR_NUMBER} removido com sucesso." diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 0673b88..105465a 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -4,6 +4,10 @@ on: pull_request: types: [opened, synchronize, reopened, closed] +permissions: + pull-requests: write + contents: read + jobs: preview: runs-on: self-hosted @@ -12,23 +16,30 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up JDK 25 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '25' + java-version: '21' distribution: 'temurin' - name: Build simple-project app if: github.event.action != 'closed' - run: ./mvnw clean package -DskipTests + run: | + chmod +x ./mvnw + ./mvnw clean package -DskipTests - name: Start Preview (container + ngrok) if: github.event.action != 'closed' id: preview + env: + NGROK_AUTHTOKEN: ${{ secrets.NGROK_AUTHTOKEN }} run: | chmod +x .github/scripts/start-preview.sh - URL=$(.github/scripts/start-preview.sh ${{ github.event.number }}) + RAW_OUTPUT=$(.github/scripts/start-preview.sh ${{ github.event.number }}) + URL=$(echo "$RAW_OUTPUT" | tail -n 1) + HOST_PORT=$((8000 + ${{ github.event.number }})) echo "preview_url=$URL" >> $GITHUB_OUTPUT + echo "host_port=$HOST_PORT" >> $GITHUB_OUTPUT - name: Comment PR with Preview URL if: github.event.action != 'closed' @@ -36,7 +47,8 @@ jobs: with: message: | 🚀 Preview da aplicação *simple-project* para este PR: - ${{ steps.preview.outputs.preview_url }} + 🌐 URL pública (Ngrok): ${{ steps.preview.outputs.preview_url }} + 🖥️ Porta local usada no host: `${{ steps.preview.outputs.host_port }}` _(Permanece ativo até o PR ser fechado ou manualmente removido)_ - name: Stop Preview on PR close diff --git a/Dockerfile b/Dockerfile index 695afa8..19a4621 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -# Imagem base com JDK 25 (Temurin) -FROM eclipse-temurin:25-jdk-alpine +# Imagem base com JDK 21 (LTS estável) +FROM eclipse-temurin:21-jdk-alpine WORKDIR /app diff --git a/pom.xml b/pom.xml index 300b995..c130963 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ - 25 + 21 @@ -62,3 +62,4 @@ + diff --git a/src/main/java/com/trandreluis/simple_project/HomeController.java b/src/main/java/com/trandreluis/simple_project/HomeController.java index c49c4e5..f1d87c6 100644 --- a/src/main/java/com/trandreluis/simple_project/HomeController.java +++ b/src/main/java/com/trandreluis/simple_project/HomeController.java @@ -9,7 +9,7 @@ public class HomeController { @GetMapping({"/", "/home"}) public String home(Model model) { - model.addAttribute("message", "Hello, World!"); + model.addAttribute("message", "Hello, World! Now you see the Ngrok magic!"); return "home"; } } \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html index d16f6e3..8d81624 100644 --- a/src/main/resources/templates/home.html +++ b/src/main/resources/templates/home.html @@ -5,6 +5,6 @@ Home -

Hello, World!

+

\ No newline at end of file