feat(server): expose request.gitStamp and display it in the footer so running Git hash is known@@ -7,6 +7,7 @@ package-lock.json
*.log
# Ignore built public files
+.gitstamp
public/.islands/
public/instant-router.js
public/instant-router.js.map
@@ -39,13 +39,12 @@ RUN yarn test # Test code to ensure it is regression-free (jest)
RUN yarn clean # Cleanup working dir
RUN yarn build:ts # Transpile TypeScript to JavaScript (node)
RUN yarn bundle:islands # Bundle Islands (react-monolith) to ESM/CJS/UMD
+RUN yarn gitstamp # Make gitstamp file with built commit hash
COPY ./public /usr/src/app/public
+COPY ./.gitstamp /usr/src/app/.gitstamp
COPY ./app.manifest.json /usr/src/app/app.manifest.json
-# Issue a git stamp file containing built commit hash
-RUN echo "$(git rev-parse HEAD)" >> .gitstamp
-
FROM node:slim as base
ENV NODE_ENV=production
@@ -72,8 +71,6 @@ COPY --from=builder /usr/src/app/ReadMe.md /app/ReadMe.md
COPY --from=builder /usr/src/app/LICENSE /app/LICENSE
COPY --from=builder /usr/src/app/yarn.lock /app/yarn.lock
-RUN echo "Running from Git commit: $(cat .gitstamp)"
-
EXPOSE ${PORT}
CMD ["node", "app/server.js"]
@@ -21,7 +21,7 @@ function removeCommentsAndSpacing(str = "") {
}
export const Layout: FC<LayoutProps & WithThemeSchemeProp> = (commonProps) => {
- const { appVersion, children, themeScheme } = commonProps;
+ const { appVersion, children, gitStamp, themeScheme } = commonProps;
const sharedProps = {
themeScheme,
@@ -84,7 +84,7 @@ export const Layout: FC<LayoutProps & WithThemeSchemeProp> = (commonProps) => {
<StyledFooterWrapper>
<p>
<a href={"https://gitfoss.io/ethicdevs/gitfoss"}>
- GitFOSS - v{appVersion} - MIT License
+ GitFOSS - v{appVersion} (#{gitStamp.slice(0, 8)}) - MIT License
</a>
</p>
</StyledFooterWrapper>
@@ -33,6 +33,7 @@ import { codeAnalysisPlugin, cryptoPlugin, prismaPlugin } from "./plugins";
import { makeGitServerService } from "./services/gitServer";
import {
getEnv,
+ getGitStamp,
localAppDomainPreHandler,
makeRequestHandler,
} from "./utils/server";
@@ -320,6 +321,13 @@ async function main(): Promise<AppServer> {
},
});
+ const gitStamp = await getGitStamp();
+ console.log(`- Running from Git ref: ${gitStamp}`);
+
+ server.decorateRequest("gitStamp", {
+ getter: () => gitStamp,
+ });
+
await startAppServer(server);
return server;
@@ -31,6 +31,7 @@ export interface CommonViewProps {
currentUserId: string | null;
currentUserRole: GlobalRole | null;
currentUserUsername: string | null;
+ gitStamp: string;
flashMessage: string | null;
themeScheme: AppThemeScheme;
title?: string;
@@ -0,0 +1,16 @@
+import { join, resolve } from "node:path";
+import { readFile } from "node:fs/promises";
+
+export async function getGitStamp() {
+ try {
+ const gitStampFileContents = await readFile(
+ resolve(join(__dirname, "..", "..", "..", ".gitstamp")),
+ {
+ encoding: "utf-8",
+ }
+ );
+ return gitStampFileContents.split("\n")[0];
+ } catch (err) {
+ return "HEAD";
+ }
+}
@@ -3,6 +3,7 @@
export { authenticatedOrLogin } from "./authenticatedOrLogin";
export { authenticatedOrRedirect } from "./authenticatedOrRedirect";
export { getEnv } from "./getEnv";
+export { getGitStamp } from "./getGitStamp";
export { guestOrRedirect } from "./guestOrRedirect";
export { localAppDomainPreHandler } from "./localAppDomainPreHandler";
export { makeRequestHandler } from "./makeRequestHandler";
@@ -45,6 +45,7 @@ export const makeRequestHandler = {
currentUserId: curr_user_uid,
currentUserRole: curr_user_role,
currentUserUsername: curr_user_username,
+ gitStamp: request.gitStamp,
flashMessage: flash_message,
title,
themeScheme,
@@ -12,6 +12,7 @@
"generate": "run-s generate:prisma",
"generate:prisma": "prisma generate",
"generate:prisma-data-proxy": "prisma generate --data-proxy",
+ "gitstamp": "git rev-parse HEAD > .gitstamp",
"db:push": "prisma db push --preview-feature",
"migrate:dev": "prisma migrate dev",
"migrate:deploy": "prisma migrate deploy",
@@ -32,6 +32,8 @@ declare module "fastify" {
codeAnalysisService: CodeAnalysisServiceAPI;
// from crypto plugin
cryptoService: CryptoServiceAPI;
+ // from server file
+ gitStamp: string;
// from react-monolith: request utility that maps a viewName to its routerPath
namedViewsPathMap: Record<string, string>;
// from react-monolith: request utility that maps a routerPath to its viewName