Skip to content

build(deps): bump @next/third-parties from 16.3.5 to 16.3.6 #459

build(deps): bump @next/third-parties from 16.3.5 to 16.3.6

build(deps): bump @next/third-parties from 16.3.5 to 16.3.6 #459

name: Cloudflare Pages Deploy
on:
workflow_dispatch:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions: {}
env:
ARTIFACT_NAME: roadmap-dsa-artifact
jobs:
build:
runs-on: ubuntu-latest
name: Build Pages
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# Histórico completo, e não o clone raso (profundidade 1) do padrão.
# O motivo é medido: num clone raso o `git log <caminho>` NÃO falha,
# ele devolve a data do HEAD para qualquer arquivo. Quem deriva data
# do histórico no build (o `lastmod` do sitemap) recebe a mesma data
# para as 40 URLs e não tem como perceber. O repositório tem 269
# commits e 18 MB de `.git`: o custo do histórico inteiro cabe no
# ruído do passo de checkout.
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: "22"
cache: npm
- name: Restore cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: |
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx', '**.md', '**.mdx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- name: Install dependencies
run: npm ci
- name: Build with Next.js
run: npm run build
env:
# Apoiadores vêm da APOIA.se no build. A chave vai no header
# `x-api-key` e o segredo no `Authorization: Bearer` (doc v0.1 da
# APOIA.se); ver `src/app/apoie/apoiadores.ts`.
#
# Estes três nomes substituem `APOIASE_TOKEN`/`APOIASE_CAMPAIGN_ID`,
# que o workflow injetava e que NUNCA existiram como secret: o build
# caía calado na lista de plano B, e era por isso que a página
# publicada mostrava 3 apoiadores com 5 apoios na campanha. Sem os
# secrets o comportamento continua o mesmo, com uma diferença que é o
# ponto: agora o log do build diz que caiu.
APOIASE_KEY: ${{ secrets.APOIASE_KEY }}
APOIASE_SECRET: ${{ secrets.APOIASE_SECRET }}
APOIASE_CAMPAIGN: ${{ secrets.APOIASE_CAMPAIGN }}
# Google Analytics só no build da `main`. Este mesmo job roda em PR,
# e o deploy de preview do Cloudflare é um site público de verdade:
# sem este recorte, cada PR mandaria pageview para a propriedade de
# produção. String vazia = o componente devolve null e o gtag.js nem
# é pedido. O ID não é segredo (sai no HTML), por isso `vars`; o
# fallback em `secrets` é só para não quebrar se alguém cadastrar no
# lugar errado.
NEXT_PUBLIC_GA_ID: ${{ github.ref == 'refs/heads/main' && (vars.NEXT_PUBLIC_GA_ID || secrets.NEXT_PUBLIC_GA_ID) || '' }}
# Só usada se a verificação do Search Console for pela tag HTML em vez
# do TXT no DNS. Vale em qualquer branch: é uma meta tag inerte.
NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION: ${{ vars.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION }}
# Prova de que o que se testa é o que se publica. O mesmo comando roda nos
# três jobs; se os três hashes baterem, ninguém reconstruiu no meio do
# caminho. É a diferença entre reaproveitar o artefato e dizer que
# reaproveitou.
- name: Impressão digital do out/
run: |
arquivos=$(find out -type f | wc -l | tr -d " ")
hash=$(find out -type f -print0 | sort -z | xargs -0 sha256sum | sha256sum | cut -d" " -f1)
echo "out/: $arquivos arquivos, sha256 do conjunto = $hash"
echo "\`build\`: **$arquivos** arquivos, sha256 do conjunto \`$hash\`" >> "$GITHUB_STEP_SUMMARY"
- name: Upload artifact
if: github.event.pull_request.head.repo.fork == false && github.actor != 'dependabot[bot]'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ env.ARTIFACT_NAME }}
retention-days: 3
path: ./out
- name: Skip
if: github.event.pull_request.head.repo.fork == true || github.actor == 'dependabot[bot]'
run: echo "Skipping artifact upload for forked or Dependabot PR"
# O portão que faltava. Antes, `tests.yml` e este workflow disparavam os DOIS
# em `push: main`, em paralelo e sem nenhum `needs` entre eles: medido no push
# do merge do #44, o deploy terminou às 03:13:17 e a suíte só às 03:17:37.
# São 4m20 de produção no ar sem ninguém ter olhado — o CI avisava, não
# barrava. E não havia via indireta: `branches/main/protection` responde
# "Branch not protected".
#
# Este job roda ENTRE o build e o deploy, e testa o artefato JÁ CONSTRUÍDO em
# vez de reconstruir. Os dois motivos:
# · o que se testa passa a ser byte a byte o que se publica (a `impressao
# digital` abaixo prova isso, comparando o hash nos três jobs);
# · o `npm run build` deixa de rodar duas vezes por push.
test:
runs-on: ubuntu-latest
needs: build
name: Playwright (no artefato que vai ao ar)
permissions:
contents: read
# Só fora de PR. Em PR quem testa é o `tests.yml`, que constrói por conta
# própria — e precisa continuar assim, porque PR de fork não recebe
# artefato (o `Upload artifact` acima é bloqueado para fork) e porque o
# preview do revisor não deve esperar 5 minutos de suíte para aparecer.
if: github.event_name != 'pull_request'
steps:
# Sem `fetch-depth: 0` de propósito: este job não constrói e não lê o
# histórico. Ele só precisa de `tests/`, do `playwright.config.ts` e das
# dependências.
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: "22"
cache: npm
- name: Install dependencies
run: npm ci
- name: Install Playwright (chromium)
run: npx playwright install --with-deps chromium
- name: Download a Build Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: ${{ env.ARTIFACT_NAME }}
path: ./out
- name: Impressão digital do out/
run: |
arquivos=$(find out -type f | wc -l | tr -d " ")
hash=$(find out -type f -print0 | sort -z | xargs -0 sha256sum | sha256sum | cut -d" " -f1)
echo "out/: $arquivos arquivos, sha256 do conjunto = $hash"
echo "\`test\`: **$arquivos** arquivos, sha256 do conjunto \`$hash\`" >> "$GITHUB_STEP_SUMMARY"
# `npm test`, NUNCA `npm run test:build`. O `test:build` reconstrói, e
# reconstruir aqui desfaz a razão de este job existir: a suíte passaria a
# exercitar um build diferente do que o `deploy` publica.
- name: Run tests
run: npm test
env:
# A credencial entra AQUI, num job que não constrói nada, por um motivo
# só: `tests/segredo-nao-vai-para-o-cliente.spec.ts` tem duas metades, e
# a segunda procura o VALOR literal do segredo dentro do `out/`. Sem as
# variáveis ela se declara `skip`, e a metade mais conclusiva da
# varredura nunca rodaria em lugar nenhum — só na máquina de quem tem
# `.env.local`, que é justamente quem não precisa dela.
#
# Com elas, o artefato que ACABOU de ser construído com a credencial de
# verdade é conferido contra a credencial de verdade, no caminho entre o
# build e o deploy. É a diferença entre "nenhuma forma conhecida de
# segredo aparece" e "este segredo não aparece".
#
# O teste nunca imprime o valor (a mensagem de falha cita o NOME da
# variável e o arquivo), e o Actions ainda mascara secret no log por
# cima disso. Este job não roda em pull_request, então PR de fork
# continua sem ver nada.
APOIASE_KEY: ${{ secrets.APOIASE_KEY }}
APOIASE_SECRET: ${{ secrets.APOIASE_SECRET }}
APOIASE_CAMPAIGN: ${{ secrets.APOIASE_CAMPAIGN }}
- name: Upload report on failure
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: playwright-report-deploy
path: playwright-report/
retention-days: 5
deploy:
runs-on: ubuntu-latest
needs: [build, test]
# `needs` com job pulado pula o dependente junto, e o `test` é pulado em PR
# de propósito. `!failure() && !cancelled()` é o idioma para dependência
# opcional: roda quando nenhum dos dois REPROVOU. Se o `test` reprovar,
# `failure()` é verdadeiro e o deploy não acontece — que é o ponto.
if: ${{ !failure() && !cancelled() && (github.event_name != 'pull_request' || (github.event.pull_request.head.repo.fork == false && github.actor != 'dependabot[bot]')) }}
name: Deploy to Cloudflare Pages
permissions:
contents: read
deployments: write
pull-requests: write # To create a comment in the PR
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- name: Download a Build Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: ${{ env.ARTIFACT_NAME }}
path: ./out
- name: Impressão digital do out/
run: |
arquivos=$(find out -type f | wc -l | tr -d " ")
hash=$(find out -type f -print0 | sort -z | xargs -0 sha256sum | sha256sum | cut -d" " -f1)
echo "out/: $arquivos arquivos, sha256 do conjunto = $hash"
echo "\`deploy\`: **$arquivos** arquivos, sha256 do conjunto \`$hash\`" >> "$GITHUB_STEP_SUMMARY"
- name: Deploy
id: deploy
uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy out --project-name=${{ secrets.CLOUDFLARE_PROJECT_NAME }} --branch ${{ github.ref_name }}
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
- name: Add Preview Url in PR Comment
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
with:
header: pr-preview-url
hide_and_recreate: true
hide_classify: "OUTDATED"
message: |
### 🚀 **Preview Url** 🚀
[${{ steps.deploy.outputs.deployment-url }}](${{ steps.deploy.outputs.deployment-url }})