From f58a10b49f111308915b13de2ab8b6deb0f49778 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Thu, 29 May 2025 19:47:28 -0400 Subject: [PATCH] Set singleplayer gitCommit in the client (#945) ## Description: Set singleplayer gitCommit in the client ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/core/Schemas.ts | 4 +++- src/core/Util.ts | 2 +- src/server/Worker.ts | 20 ++++++++++++++------ webpack.config.js | 7 +++++-- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index fb67b0bad..c7030515d 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -446,10 +446,12 @@ export const GameEndInfoSchema = GameStartInfoSchema.extend({ }); export type GameEndInfo = z.infer; +const GitCommitSchema = z.string().regex(/^[0-9a-fA-F]{40}$/); + export const AnalyticsRecordSchema = z.object({ info: GameEndInfoSchema, version: z.literal("v0.0.2"), - gitCommit: z.string(), + gitCommit: GitCommitSchema, }); export type AnalyticsRecord = z.infer; diff --git a/src/core/Util.ts b/src/core/Util.ts index b518f5f1a..d78f7091d 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -195,7 +195,7 @@ export function createGameRecord( ): GameRecord { const duration = Math.floor((end - start) / 1000); const version = "v0.0.2"; - const gitCommit = ""; + const gitCommit = process.env.GIT_COMMIT ?? "unknown"; const num_turns = allTurns.length; const turns = allTurns.filter( (t) => t.intents.length !== 0 || t.hash !== undefined, diff --git a/src/server/Worker.ts b/src/server/Worker.ts index 5ff087242..e9fb2131a 100644 --- a/src/server/Worker.ts +++ b/src/server/Worker.ts @@ -5,10 +5,16 @@ import ipAnonymize from "ip-anonymize"; import path from "path"; import { fileURLToPath } from "url"; import { WebSocket, WebSocketServer } from "ws"; +import { z } from "zod/v4"; import { GameEnv } from "../core/configuration/Config"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { GameType } from "../core/game/Game"; -import { ClientMessageSchema, GameConfig, GameRecord } from "../core/Schemas"; +import { + ClientMessageSchema, + GameConfig, + GameRecord, + GameRecordSchema, +} from "../core/Schemas"; import { archive, readGameRecord } from "./Archive"; import { Client } from "./Client"; import { GameManager } from "./GameManager"; @@ -241,13 +247,15 @@ export function startWorker() { app.post( "/api/archive_singleplayer_game", gatekeeper.httpHandler(LimiterType.Post, async (req, res) => { - const gameRecord: GameRecord = req.body; - - if (!gameRecord) { - log.info("game record not found in request"); - res.status(404).json({ error: "Game record not found" }); + const result = GameRecordSchema.safeParse(req.body); + if (!result.success) { + const error = z.prettifyError(result.error); + log.info(error); + res.status(400).json({ error }); return; } + + const gameRecord: GameRecord = result.data; archive(gameRecord); res.json({ success: true, diff --git a/webpack.config.js b/webpack.config.js index 4b4096141..3f6d28936 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,4 @@ +import { execSync } from "child_process"; import CopyPlugin from "copy-webpack-plugin"; import ESLintPlugin from "eslint-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; @@ -8,6 +9,9 @@ import webpack from "webpack"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const gitCommit = + process.env.GIT_COMMIT ?? execSync("git rev-parse HEAD").toString().trim(); + export default async (env, argv) => { const isProduction = argv.mode === "production"; @@ -116,9 +120,8 @@ export default async (env, argv) => { "process.env.WEBSOCKET_URL": JSON.stringify( isProduction ? "" : "localhost:3000", ), - }), - new webpack.DefinePlugin({ "process.env.GAME_ENV": JSON.stringify(isProduction ? "prod" : "dev"), + "process.env.GIT_COMMIT": JSON.stringify(gitCommit), }), new CopyPlugin({ patterns: [