From c257deb2ac4639462838de40262b7f8899c92ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:38:31 -0300 Subject: [PATCH 1/6] ci: deploy pela CLI do firebase-tools com verificacao pos-deploy O workflow usava a API programatica do firebase-tools, que encerrava o processo com exit 0 sem publicar nada. Passa a usar o CLI, que falha alto, e adiciona um step que compara o updateTime da function antes e depois, falhando o job se nada foi republicado. Refs #177 --- .github/workflows/deploy.yml | 125 +++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 34 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c7627bca..00f1056d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,46 +10,110 @@ on: - 'scripts/firebase-deploy.js' - '*.json' - '.github/deploy' + - '.github/workflows/deploy.yml' + workflow_dispatch: + inputs: + dry_run: + description: 'Validar o deploy sem publicar (--dry-run)' + type: boolean + default: false jobs: deploy: name: Deploy to Firebase runs-on: ubuntu-latest if: | - github.event.head_commit.message != 'Initial commit' && - !contains(github.event.head_commit.message, '[skip ci]') + github.event_name == 'workflow_dispatch' || + (github.event.head_commit.message != 'Initial commit' && + !contains(github.event.head_commit.message, '[skip ci]')) + + env: + # `secrets` nao pode ser usado direto em `if:`, entao vira env do job + HAS_SA: ${{ secrets.FIREBASE_SERVICE_ACCOUNT != '' }} + FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: '18.x' - - - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/setup-node@v4 with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- + node-version: '22.x' + cache: 'npm' - name: Install root dependencies - run: npm i --only=production + run: npm i --omit=dev - name: Install functions dependencies - run: cd functions && npm i --only=production --no-optional && cd .. + run: npm i --omit=dev --no-optional --prefix functions env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Run deploy + - name: Write functions/.env env: - FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} - FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} SERVER_OPERATOR_TOKEN: ${{ secrets.SERVER_OPERATOR_TOKEN }} - run: npm run deploy + run: npm run write-env + + - name: Authenticate with service account + if: env.HAS_SA == 'true' + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }} + + - name: Setup gcloud + if: env.HAS_SA == 'true' + uses: google-github-actions/setup-gcloud@v2 + + - name: Record deployed state (before) + id: before + if: env.HAS_SA == 'true' + run: | + set -euo pipefail + BEFORE=$(gcloud functions describe app --region us-central1 \ + --project "$FIREBASE_PROJECT_ID" --format='value(updateTime)') + echo "updateTime=$BEFORE" >> "$GITHUB_OUTPUT" + echo "updateTime antes do deploy: $BEFORE" + + - name: Deploy functions + env: + FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} + DRY_RUN: ${{ inputs.dry_run }} + run: | + set -euo pipefail + if [ -z "${FIREBASE_PROJECT_ID:-}" ]; then + echo "::error::secret FIREBASE_PROJECT_ID nao configurado" + exit 1 + fi + ARGS=(--only functions --project "$FIREBASE_PROJECT_ID" --non-interactive) + if [ "${DRY_RUN:-false}" = "true" ]; then + ARGS+=(--dry-run) + fi + if [ "${HAS_SA}" = "true" ]; then + echo "Autenticando via service account (ADC)" + elif [ -n "${FIREBASE_TOKEN:-}" ]; then + echo "::warning::Usando FIREBASE_TOKEN (firebase login:ci). O Google descontinuou esse fluxo - migrar para service account, ver issue #177" + ARGS+=(--token "$FIREBASE_TOKEN") + else + echo "::error::Nenhuma credencial disponivel. Configure o secret FIREBASE_SERVICE_ACCOUNT" + exit 1 + fi + npx --yes firebase-tools@13 deploy "${ARGS[@]}" + + - name: Verify functions were really published + if: env.HAS_SA == 'true' && inputs.dry_run != true + run: | + set -euo pipefail + AFTER=$(gcloud functions describe app --region us-central1 \ + --project "$FIREBASE_PROJECT_ID" --format='value(updateTime)') + BEFORE='${{ steps.before.outputs.updateTime }}' + echo "updateTime antes: $BEFORE" + echo "updateTime depois: $AFTER" + if [ "$AFTER" = "$BEFORE" ]; then + echo "::error::O deploy terminou sem erro, mas o updateTime nao avancou: nada foi publicado (ver issue #177)" + exit 1 + fi + echo "Deploy confirmado: as functions foram republicadas." update-app-json: name: Update application and publish @@ -58,7 +122,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Write README with base URI env: @@ -80,7 +144,8 @@ jobs: git config --local user.email 'action@github.com' git config --local user.name 'GitHub Action' git add ./assets/ - (git diff-index --quiet HEAD && echo "::set-output name=diff::0") || echo "::set-output name=diff::1" + (git diff-index --quiet HEAD && echo "diff=0" >> "$GITHUB_OUTPUT") \ + || echo "diff=1" >> "$GITHUB_OUTPUT" id: git_diff - name: Commit local file changes @@ -100,28 +165,20 @@ jobs: APP_CHANGED: ${{ steps.git_diff.outputs.diff }} run: | CAN_PUBLISH=$(node -p "!(/-/.test(require('./package.json').version)) && process.env.APP_CHANGED") - echo "::set-output name=publish::$CAN_PUBLISH" + echo "publish=$CAN_PUBLISH" >> "$GITHUB_OUTPUT" id: pkg_version - name: Setup Node if: steps.pkg_version.outputs.publish == 1 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: '18.x' + node-version: '22.x' registry-url: 'https://registry.npmjs.org/' - - - name: Cache dependencies - if: steps.pkg_version.outputs.publish == 1 - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- + cache: 'npm' - name: Install dependencies if: steps.pkg_version.outputs.publish == 1 - run: npm ci --only=production + run: npm ci --omit=dev - name: Run publish script if: steps.pkg_version.outputs.publish == 1 From 2cb0e711fd870a04245a2c6ebab8e62313348faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:38:33 -0300 Subject: [PATCH 2/6] ci: reduzir firebase-deploy.js a geracao do functions/.env Remove client.functions.config.set() (API descontinuada pelo Google, e o runtime config do projeto esta vazio: as functions ja leem do .env) e client.deploy(), que era o ponto onde o processo morria em silencio. Refs #177 --- scripts/firebase-deploy.js | 72 +++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/scripts/firebase-deploy.js b/scripts/firebase-deploy.js index fe13a488..64268105 100644 --- a/scripts/firebase-deploy.js +++ b/scripts/firebase-deploy.js @@ -1,51 +1,45 @@ +/** + * Gera o arquivo `functions/.env`, lido em runtime por `functions/__env.js`. + * + * Este script NÃO faz mais o deploy. Antes ele chamava a API programática do + * `firebase-tools` (`client.functions.config.set()` + `client.deploy()`), que + * encerrava o processo com exit 0 sem publicar nada — deixando o workflow verde + * enquanto a produção seguia parada. Ver issue #177. + * + * O deploy agora é feito pelo CLI, que falha alto quando algo dá errado: + * firebase deploy --only functions --project --non-interactive + */ + require('dotenv').config() const path = require('path') const fs = require('fs') -const { FIREBASE_TOKEN, SERVER_OPERATOR_TOKEN } = process.env - require('./scripts-minification') const { name, version } = require('../package.json') const { project, baseUri } = require('./_constants') -const client = require('firebase-tools') - -const config = [ - `pkg.version=${version}`, - `pkg.name=${name}`, - `server.operator_token=${SERVER_OPERATOR_TOKEN}` -] -if (baseUri) { - config.push(`server.base_uri=${baseUri}`) + +const { SERVER_OPERATOR_TOKEN } = process.env + +if (!SERVER_OPERATOR_TOKEN) { + console.error('\x1b[31m%s\x1b[0m', 'SERVER_OPERATOR_TOKEN não definido') + console.error( + 'As functions rejeitam todo webhook sem esse valor (functions/index.js, x-operator-token).' + ) + process.exit(1) } -fs.writeFileSync(path.resolve(__dirname, '../functions/.env'), ` -NAME=${name} +const envFile = path.resolve(__dirname, '../functions/.env') + +fs.writeFileSync(envFile, `NAME=${name} VERSION=${version} SERVER_OPERATOR_TOKEN=${SERVER_OPERATOR_TOKEN} -SERVER_BASE_URI=${baseUri}`) - -client.functions.config.set(config, { project }) - .then(() => client.deploy({ - project, - only: 'functions', - token: FIREBASE_TOKEN, - force: true - })) - - .then(() => { - console.log( - '\x1b[32m%s\x1b[0m', - `\nDeployed with success to Firebase project '${project}'` - ) - console.log( - '\x1b[35m%s\x1b[0m', - `\nBase URI: ${baseUri}` - ) - console.log() - }) - - .catch(err => { - console.error(err) - process.exit(1) - }) +SERVER_BASE_URI=${baseUri} +`) + +console.log('\x1b[32m%s\x1b[0m', `\nfunctions/.env escrito para o projeto '${project}'`) +console.log(` NAME=${name}`) +console.log(` VERSION=${version}`) +console.log(` SERVER_BASE_URI=${baseUri}`) +console.log(' SERVER_OPERATOR_TOKEN=') +console.log() From 065d50f983f61c186cc6218b42e777e94995d6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:38:34 -0300 Subject: [PATCH 3/6] ci: remover predeploy truncado do firebase.json O hook era 'npm --prefix "$RESOURCE_DIR" run', sem nome de script: apenas listava os scripts disponiveis e saia. Refs #177 --- firebase.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/firebase.json b/firebase.json index ca36afd5..cb5cb733 100644 --- a/firebase.json +++ b/firebase.json @@ -1,8 +1,5 @@ { "functions": { - "predeploy": [ - "npm --prefix \"$RESOURCE_DIR\" run" - ], "source": "functions" } } From 9a20d79a5f43092c530bfdfee1ed7ac1d43d19de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:38:35 -0300 Subject: [PATCH 4/6] ci: separar write-env do deploy no package.json Refs #177 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b639109..c3eccf2e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "main": "functions/index.js", "scripts": { "serve": "echo 'Firebase runs with legacy Node.js 8; Use `npm run deploy` instead.'", - "deploy": "NODE_ENV=production node ./scripts/firebase-deploy.js", + "write-env": "NODE_ENV=production node ./scripts/firebase-deploy.js", + "deploy": "npm run write-env && npx --yes firebase-tools@13 deploy --only functions --non-interactive", "release": "standard-version", "release:starter": "standard-version --prerelease starter", "publish:market": "node ./scripts/market-publication.js" From b0baa25b434d12024d4aacc347ade52ed101efa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:44:29 -0300 Subject: [PATCH 5/6] fix(runtime): subir functions para Node 22 O Cloud Functions nao aceita mais nodejs18: os runtimes disponiveis no projeto hoje sao nodejs20 (DEPRECATED, descomissiona em 30/10/2026), nodejs22 (GA) e nodejs24 (GA, so gen2). Com engines 18 nenhum deploy pode dar certo. firebase-admin@10, firebase-functions@4 e @ecomplus/application-sdk foram verificados carregando sem erro no Node 22, entao o bump nao arrasta upgrade de SDK. Refs #177 --- functions/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/package.json b/functions/package.json index 7ce63fcf..f18216c5 100644 --- a/functions/package.json +++ b/functions/package.json @@ -10,7 +10,7 @@ "logs": "firebase functions:log" }, "engines": { - "node": "18" + "node": "22" }, "dependencies": { "@ecomplus/application-sdk": "^22.0.0-firestore.1.15.7", From 2736c6794e18cff8e3f92d2653fd17f319305007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Rocha=20Gon=C3=A7alves?= <35348281+vitorrgg@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:44:31 -0300 Subject: [PATCH 6/6] fix(runtime): subir functions para Node 22 O Cloud Functions nao aceita mais nodejs18: os runtimes disponiveis no projeto hoje sao nodejs20 (DEPRECATED, descomissiona em 30/10/2026), nodejs22 (GA) e nodejs24 (GA, so gen2). Com engines 18 nenhum deploy pode dar certo. firebase-admin@10, firebase-functions@4 e @ecomplus/application-sdk foram verificados carregando sem erro no Node 22, entao o bump nao arrasta upgrade de SDK. Refs #177 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 3c032078..2bd5a0a9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18 +22