From 3dfc430c858ebec64e734330af3ef6f2bd6699c8 Mon Sep 17 00:00:00 2001 From: fpereirasilv Date: Thu, 15 Oct 2026 14:58:06 -0300 Subject: [PATCH] fix: robust git commit hash detection via fs, env vars and docker support --- .gitattributes | 1 + Dockerfile | 3 ++ version.json | 3 ++ vite.config.js | 96 +++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 .gitattributes create mode 100644 version.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0fdc3a0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +version.json export-subst diff --git a/Dockerfile b/Dockerfile index 71f9b6f..96451d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,9 @@ # Estágio 1: Build da aplicação React FROM node:20-alpine AS builder +# Instala git para resolução da versão de commit durante o build +RUN apk add --no-cache git + WORKDIR /app # Copia manifestos de dependência diff --git a/version.json b/version.json new file mode 100644 index 0000000..3d15a4a --- /dev/null +++ b/version.json @@ -0,0 +1,3 @@ +{ + "commit": "d8500cf" +} diff --git a/vite.config.js b/vite.config.js index 6e128aa..e8c9a72 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,19 +1,99 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import fs from 'fs' +import path from 'path' import { execSync } from 'child_process' -let commitHash = process.env.COMMIT_REF - ? process.env.COMMIT_REF.slice(0, 7) - : ''; +function resolveCommitHash() { + // 1. Variáveis de ambiente de plataformas de hospedagem comuns (Netlify, Vercel, Cloudflare, Coolify, CI) + const envVars = [ + 'COMMIT_REF', + 'VERCEL_GIT_COMMIT_SHA', + 'CF_PAGES_COMMIT_SHA', + 'COOLIFY_COMMIT_SHA', + 'SOURCE_COMMIT', + 'GIT_COMMIT', + 'GITHUB_SHA', + 'CI_COMMIT_SHA', + 'GITEA_ACTIONS_SHA', + 'VITE_COMMIT_HASH', + 'COMMIT_HASH' + ]; -if (!commitHash) { - try { - commitHash = execSync('git rev-parse --short HEAD').toString().trim(); - } catch (e) { - commitHash = 'dev'; + for (const key of envVars) { + const val = process.env[key]; + if (val && typeof val === 'string' && val.trim().length >= 7) { + return val.trim().slice(0, 7); + } } + + // 2. Leitura direta dos arquivos .git via Node.js fs (dispensa ter o binário 'git' instalado no container) + try { + let gitDir = path.resolve('.git'); + if (fs.existsSync(gitDir)) { + const stat = fs.statSync(gitDir); + if (stat.isFile()) { + const content = fs.readFileSync(gitDir, 'utf8'); + const match = content.match(/gitdir:\s*(.+)/i); + if (match) gitDir = path.resolve(match[1].trim()); + } + + const headFile = path.join(gitDir, 'HEAD'); + if (fs.existsSync(headFile)) { + const headContent = fs.readFileSync(headFile, 'utf8').trim(); + if (headContent.startsWith('ref:')) { + const refPath = headContent.replace(/^ref:\s*/, '').trim(); + const refFile = path.join(gitDir, refPath); + if (fs.existsSync(refFile)) { + const sha = fs.readFileSync(refFile, 'utf8').trim(); + if (sha.length >= 7) return sha.slice(0, 7); + } + // Se estiver compactado em packed-refs + const packedRefsFile = path.join(gitDir, 'packed-refs'); + if (fs.existsSync(packedRefsFile)) { + const lines = fs.readFileSync(packedRefsFile, 'utf8').split('\n'); + for (const line of lines) { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('^')) { + const parts = trimmed.split(' '); + if (parts.length >= 2 && parts[1] === refPath) { + return parts[0].slice(0, 7); + } + } + } + } + } else if (/^[0-9a-f]{7,40}$/i.test(headContent)) { + return headContent.slice(0, 7); + } + } + } + } catch (e) { + // Continua para o próximo método se falhar + } + + // 3. Execução do comando git caso o binário esteja disponível + try { + const hash = execSync('git rev-parse --short HEAD', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim(); + if (hash && hash.length >= 7) return hash.slice(0, 7); + } catch (e) { + // git não instalado ou erro + } + + // 4. Arquivo version.json estático se existir + try { + if (fs.existsSync('version.json')) { + const v = JSON.parse(fs.readFileSync('version.json', 'utf8')); + if (v.commit && !v.commit.startsWith('$Format') && v.commit.length >= 7) { + return v.commit.slice(0, 7); + } + } + } catch (e) {} + + return 'dev'; } +const commitHash = resolveCommitHash(); + // https://vite.dev/config/ export default defineConfig({ plugins: [react()],