Merge pull request 'feature/version-badge' (#40) from feature/version-badge into master
Reviewed-on: #40
This commit was merged in pull request #40.
This commit is contained in:
12
Dockerfile
12
Dockerfile
@@ -7,6 +7,15 @@ RUN cd client && npm install
|
||||
COPY client/ ./client/
|
||||
RUN cd client && npm run build
|
||||
|
||||
# ── Version metadata ──────────────────────────────────────────────────────────
|
||||
# Pass these at build time:
|
||||
# docker build --build-arg GIT_SHA=$(git rev-parse HEAD) \
|
||||
# --build-arg BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) .
|
||||
ARG GIT_SHA=dev
|
||||
ARG BUILD_TIME=unknown
|
||||
RUN echo "{\"sha\":\"${GIT_SHA}\",\"shortSha\":\"${GIT_SHA:0:7}\",\"buildTime\":\"${BUILD_TIME}\"}" \
|
||||
> /build/client/dist/version.json
|
||||
|
||||
FROM node:20-alpine AS production
|
||||
RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
@@ -25,5 +34,6 @@ COPY demo/ ./demo/
|
||||
COPY client/public/static ./client/dist/static
|
||||
RUN mkdir -p /data
|
||||
EXPOSE 3001
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD wget -qO- http://localhost:3001/api/health || exit 1
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget -qO- http://localhost:3001/api/health || exit 1
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
5
client/public/version.json
Normal file
5
client/public/version.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"sha": "dev",
|
||||
"shortSha": "dev",
|
||||
"buildTime": null
|
||||
}
|
||||
@@ -42,8 +42,13 @@ function GiteaIcon() {
|
||||
);
|
||||
}
|
||||
|
||||
function AppFooter() {
|
||||
function AppFooter({ version }) {
|
||||
const year = new Date().getFullYear();
|
||||
const sha = version?.shortSha || null;
|
||||
const built = version?.buildTime
|
||||
? new Date(version.buildTime).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{`
|
||||
@@ -53,13 +58,27 @@ function AppFooter() {
|
||||
}
|
||||
`}</style>
|
||||
<footer style={sf.footer}>
|
||||
<span style={sf.copy}>© {year} Jason Stedwell</span>
|
||||
<span style={sf.sep}>·</span>
|
||||
<span style={sf.copy}>© {year} Jason Stedwell</span>
|
||||
<span style={sf.sep}>·</span>
|
||||
<DevTicker />
|
||||
<span style={sf.sep}>·</span>
|
||||
<span style={sf.sep}>·</span>
|
||||
<a href={REPO_URL} target="_blank" rel="noopener noreferrer" style={sf.link}>
|
||||
<GiteaIcon /> cpas
|
||||
</a>
|
||||
{sha && sha !== 'dev' && (
|
||||
<>
|
||||
<span style={sf.sep}>·</span>
|
||||
<a
|
||||
href={`${REPO_URL}/commit/${version.sha}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={sf.link}
|
||||
title={built ? `Built ${built}` : 'View commit'}
|
||||
>
|
||||
{sha}
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</footer>
|
||||
</>
|
||||
);
|
||||
@@ -129,6 +148,14 @@ const sf = {
|
||||
export default function App() {
|
||||
const [tab, setTab] = useState('dashboard');
|
||||
const [showReadme, setShowReadme] = useState(false);
|
||||
const [version, setVersion] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/version.json')
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(v => { if (v) setVersion(v); })
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ToastProvider>
|
||||
@@ -156,7 +183,7 @@ export default function App() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AppFooter />
|
||||
<AppFooter version={version} />
|
||||
|
||||
{showReadme && <ReadmeModal onClose={() => setShowReadme(false)} />}
|
||||
</div>
|
||||
|
||||
13
server.js
13
server.js
@@ -29,8 +29,19 @@ function audit(action, entityType, entityId, performedBy, details) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Version info (written by Dockerfile at build time) ───────────────────────
|
||||
// Falls back to { sha: 'dev' } when running outside a Docker build (local dev).
|
||||
let BUILD_VERSION = { sha: 'dev', shortSha: 'dev', buildTime: null };
|
||||
try {
|
||||
BUILD_VERSION = require('./client/dist/version.json');
|
||||
} catch (_) { /* pre-build or local dev — stub values are fine */ }
|
||||
|
||||
// Health
|
||||
app.get('/api/health', (req, res) => res.json({ status: 'ok', timestamp: new Date().toISOString() }));
|
||||
app.get('/api/health', (req, res) => res.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
version: BUILD_VERSION,
|
||||
}));
|
||||
|
||||
// ── Employees ────────────────────────────────────────────────────────────────
|
||||
app.get('/api/employees', (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user