refactor(builds): refactored how the builds works to include the build number now

this will be for the new lst - ccc
This commit is contained in:
2026-06-17 10:34:53 -05:00
parent 4ff10dfcb2
commit 1b1918dcd0
8 changed files with 192 additions and 152 deletions

View File

@@ -9,6 +9,7 @@ import { routeHitMiddleware } from "./middleware/routeHit.middleware.js";
import { setupRoutes } from "./routeHandler.routes.js";
import { auth } from "./utils/auth.utils.js";
import { lstCors } from "./utils/cors.utils.js";
import { getAppVersion } from "./utils/version.utils.js";
const createApp = async () => {
const log = createLogger({ module: "system", subModule: "main start" });
@@ -35,6 +36,7 @@ const createApp = async () => {
app.all(`${baseUrl}/api/auth/*splat`, toNodeHandler(auth));
app.use(express.json());
const version = await getAppVersion();
app.get(`${baseUrl}/api/lst-config.js`, (_, res) => {
res.type("application/javascript");
res.setHeader("Cache-Control", "no-store");
@@ -47,7 +49,9 @@ const createApp = async () => {
appVersion: ${JSON.stringify(umamiConfig.appVersion ?? "dev")},
umamiHost: ${JSON.stringify(umamiConfig.umamiHost ?? "")},
umamiWebsiteId: ${JSON.stringify(umamiConfig.umamiWebsiteId ?? "")},
timezone: ${JSON.stringify(process.env.TIMEZONE ?? "America/Chicago")}
timezone: ${JSON.stringify(process.env.TIMEZONE ?? "America/Chicago")},
version: ${JSON.stringify(version.version)},
lastBuildTIme: ${JSON.stringify(version.lastBuildTime)}
};
`);
});

View File

@@ -17,12 +17,13 @@ import { prodStopSpec } from "../scaler/prodSqlStop.spec.js";
import { prodRegisterSpec } from "../scaler/register.spec.js";
// all the specs
import { statusSpec } from "../scaler/stats.spec.js";
import { getAppVersion } from "../utils/version.utils.js";
export const openApiBase: OpenAPIV3_1.Document = {
openapi: "3.1.0",
info: {
title: "LST API",
version: "3.0.0",
version: (await getAppVersion()).version ?? "",
description: "Label System Tracking API",
},
servers: [

View File

@@ -1,5 +1,6 @@
import { createServer } from "node:http";
import os from "node:os";
import createApp from "./app.js";
import { db } from "./db/db.controller.js";
import { startDbNotificationListener } from "./db/db.listener.js";
@@ -32,6 +33,7 @@ import { ppooMonitoring } from "./warehousing/warehousing.ppooMonitor.js";
const port = Number(process.env.PORT) || 3000;
export let systemSettings: Setting[] = [];
const start = async () => {
const { app, baseUrl } = await createApp();

View File

@@ -6,12 +6,15 @@ import {
type SqlQuery,
sqlQuerySelector,
} from "../prodSql/prodSqlQuerySelector.utils.js";
import { isServerRunning } from "../tcpServer/tcp.server.js";
import { getAppVersion } from "../utils/version.utils.js";
const router = Router();
router.get("/", async (_, res) => {
const used = process.memoryUsage();
const version = await getAppVersion();
const query = sqlQuerySelector("prodSqlStats") as SqlQuery;
@@ -20,6 +23,8 @@ router.get("/", async (_, res) => {
status: "ok",
uptime: process.uptime(),
nodeVersion: process.version,
appVersion: version.version ?? "",
lastBuildDate: version.lastBuildTime ?? "",
memoryUsage: `Heap: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB / RSS: ${(
used.rss / 1024 / 1024
).toFixed(2)} MB`,

View File

@@ -0,0 +1,16 @@
import fsp from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
export const getAppVersion = async () => {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const version = path.join(__dirname, "../../package.json");
const raw = await fsp.readFile(`${version}`, "utf8");
const config = JSON.parse(raw);
return {
version: `${config.version}.${parseInt((config.build as string) ?? "1", 0) - 1}`,
lastBuildTime: config.lastBuildDate,
};
};

View File

@@ -2,6 +2,7 @@ import fs from "node:fs";
import fsp from "node:fs/promises";
import path from "node:path";
import archiver from "archiver";
import { format } from "date-fns";
import { createLogger } from "../logger/logger.controller.js";
import { emitBuildLog } from "./build.utils.js";
import { updateAppStats } from "./updateAppStats.utils.js";
@@ -17,33 +18,31 @@ const exists = async (target: string) => {
}
};
const getNextBuildNumber = async (buildNumberFile: string) => {
if (!(await exists(buildNumberFile))) {
await fsp.writeFile(buildNumberFile, "1", "utf8");
return 1;
}
const raw = await fsp.readFile(buildNumberFile, "utf8");
const current = Number.parseInt(raw.trim(), 10);
const getNextBuildNumber = async (versionPath: string) => {
const raw = await fsp.readFile(versionPath, "utf8");
const config = JSON.parse(raw);
const current = Number.parseInt(config.build.trim(), 10);
let nextBuild: string;
if (Number.isNaN(current) || current < 1) {
await fsp.writeFile(buildNumberFile, "1", "utf8");
return 1;
nextBuild = "1";
} else {
nextBuild = String(current + 1); // Incrementing the build number
}
const next = current + 1;
const updatedConfig = {
...config,
build: nextBuild,
lastBuildDate: format(new Date(Date.now()), "M/d/yyyy HH:mm"),
};
await fsp.writeFile(buildNumberFile, String(next), "utf8");
await fsp.writeFile(
versionPath,
JSON.stringify(updatedConfig, null, 4) + "\n",
"utf8",
);
// update the server with the next build number
await updateAppStats({
currentBuild: next,
lastBuildAt: new Date(),
building: true,
});
return next;
return { version: config.version, build: config.build };
};
const cleanupOldBuilds = async (buildFolder: string, maxBuilds: number) => {
@@ -53,7 +52,8 @@ const cleanupOldBuilds = async (buildFolder: string, maxBuilds: number) => {
for (const entry of entries) {
if (!entry.isFile()) continue;
if (!/^LSTV3-\d+\.zip$/i.test(entry.name)) continue;
//if (!/^LSTV3-\d+\.zip$/i.test(entry.name)) continue;
if (!entry.name.includes("LSTV3")) continue;
const fullPath = path.join(buildFolder, entry.name);
const stat = await fsp.stat(fullPath);
@@ -85,7 +85,7 @@ export const zipBuild = async () => {
}
const includesFile = path.join(appDir, ".includes");
const buildNumberFile = path.join(appDir, ".buildNumber");
const version = path.join(appDir, "package.json");
const buildFolder = path.join(appDir, "builds");
const tempFolder = path.join(appDir, "temp", "zip-temp");
if (!(await exists(includesFile))) {
@@ -95,11 +95,13 @@ export const zipBuild = async () => {
await fsp.mkdir(buildFolder, { recursive: true });
const buildNumber = await getNextBuildNumber(buildNumberFile);
const zipFileName = `LSTV3-${buildNumber}.zip`;
const lstVersion = await getNextBuildNumber(version);
const zipFileName = `LSTV3-${lstVersion.version}.${lstVersion.build}.zip`;
const zipFile = path.join(buildFolder, zipFileName);
// make the folders in case they are not created already
emitBuildLog(`Using build number: ${buildNumber}`);
emitBuildLog(
`Using version, build number: ${lstVersion.version}.${lstVersion.build}`,
);
if (await exists(tempFolder)) {
await fsp.rm(tempFolder, { recursive: true, force: true });
@@ -170,7 +172,7 @@ export const zipBuild = async () => {
return {
success: true,
buildNumber,
build: lstVersion.build,
zipFile,
zipFileName,
};

View File

@@ -1,113 +1,115 @@
{
"name": "lst_v3",
"version": "0.1.0-alpha.3",
"description": "The tool that supports us in our everyday alplaprod",
"main": "index.js",
"scripts": {
"test": "dotenvx run -f .env -- vitest",
"test:run": "dotenvx run -f .env -- vitest run",
"dev": "concurrently -n \"server,frontend\" -c \"#007755, #1F73D1\" \"npm run dev:app\" \"npm run dev:frontend\"",
"dev:app": "dotenvx run -f .env -- tsx watch backend/server.ts",
"dev:frontend": "cd frontend && npm run dev",
"dev:db:migrate": "npx drizzle-kit push",
"dev:db:generate": "tsc && npx drizzle-kit generate --config=drizzle.config.ts",
"build": "rimraf dist && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate && cd frontend && npm run build",
"build:app": "tsc",
"agent": "powershell -ExecutionPolicy Bypass -File scripts/agentController.ps1",
"build:docker": "rimraf dist && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate",
"build:emailTemplate": "cpy \"backend/utils/mailViews/**/*\" dist/utils/mailViews --parents",
"build:copyGpSql": "cpy \"backend/gpSql/queries/**/*\" dist/gpSql/queries --parents",
"build:copySql": "cpy \"backend/prodSql/queries/**/*\" dist/prodSql/queries --parents",
"lint": "tsc && biome lint",
"start": "npm run start:server",
"start:server": "dotenvx run -f .env -- node dist/server.js",
"start:docker": "node dist/server.js",
"version": "changeset version",
"specCheck": "node scripts/check-route-specs.mjs",
"commit": "cz",
"release": "npm run build && commit-and-tag-version",
"build:apk": "cd lstMobile && expo prebuild --clean && cd android && gradlew.bat assembleRelease "
},
"repository": {
"type": "git",
"url": "https://git.tuffraid.net/cowch/lst_v3.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"devDependencies": {
"@biomejs/biome": "2.4.8",
"@commitlint/cli": "^20.5.0",
"@commitlint/config-conventional": "^20.5.0",
"@types/archiver": "^7.0.0",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/morgan": "^1.9.10",
"@types/mssql": "^9.1.9",
"@types/multer": "^2.1.0",
"@types/net-snmp": "^3.23.0",
"@types/node": "^25.5.0",
"@types/nodemailer": "^7.0.11",
"@types/nodemailer-express-handlebars": "^4.0.6",
"@types/pg": "^8.18.0",
"@types/supertest": "^7.2.0",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.8",
"commit-and-tag-version": "^12.7.1",
"commitizen": "^4.3.1",
"cpy-cli": "^7.0.0",
"cz-conventional-changelog": "^3.3.0",
"npm-check-updates": "^19.6.5",
"openapi-types": "^12.1.3",
"supertest": "^7.2.2",
"ts-node-dev": "^2.0.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vitest": "^4.1.8"
},
"dependencies": {
"@dotenvx/dotenvx": "^1.57.0",
"@scalar/express-api-reference": "^0.9.20",
"@socket.io/admin-ui": "^0.5.1",
"archiver": "^7.0.1",
"axios": "^1.13.6",
"bcryptjs": "^3.0.3",
"better-auth": "^1.5.5",
"chokidar": "^5.0.0",
"concurrently": "^9.2.1",
"cors": "^2.8.6",
"croner": "^10.0.1",
"date-fns": "^4.1.0",
"date-fns-tz": "^3.2.0",
"drizzle-kit": "^0.31.10",
"drizzle-orm": "^0.45.1",
"drizzle-zod": "^0.8.3",
"excel-date-to-js": "^1.1.5",
"express": "^5.2.1",
"husky": "^9.1.7",
"ldapts": "^8.1.7",
"modbus-serial": "^8.0.25",
"morgan": "^1.10.1",
"mssql": "^12.2.1",
"multer": "^2.1.1",
"net-snmp": "^3.26.1",
"nodemailer": "^8.0.3",
"nodemailer-express-handlebars": "^7.0.0",
"pg": "^8.20.0",
"pino": "^10.3.1",
"pino-pretty": "^13.1.3",
"postgres": "^3.4.8",
"powershell": "^2.3.3",
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"xlsx": "^0.18.5",
"zod": "^4.3.6",
"zod-openapi": "^6.0.0"
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
"name": "lst_v3",
"version": "0.1.0-alpha.3",
"build": "175",
"lastBuildDate": "6/17/2026 10:26",
"description": "The tool that supports us in our everyday alplaprod",
"main": "index.js",
"scripts": {
"test": "dotenvx run -f .env -- vitest",
"test:run": "dotenvx run -f .env -- vitest run",
"dev": "concurrently -n \"server,frontend\" -c \"#007755, #1F73D1\" \"npm run dev:app\" \"npm run dev:frontend\"",
"dev:app": "dotenvx run -f .env -- tsx watch backend/server.ts",
"dev:frontend": "cd frontend && npm run dev",
"dev:db:migrate": "npx drizzle-kit push",
"dev:db:generate": "tsc && npx drizzle-kit generate --config=drizzle.config.ts",
"build": "rimraf dist && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate && cd frontend && npm run build",
"build:app": "tsc",
"agent": "powershell -ExecutionPolicy Bypass -File scripts/agentController.ps1",
"build:docker": "rimraf dist && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate",
"build:emailTemplate": "cpy \"backend/utils/mailViews/**/*\" dist/utils/mailViews --parents",
"build:copyGpSql": "cpy \"backend/gpSql/queries/**/*\" dist/gpSql/queries --parents",
"build:copySql": "cpy \"backend/prodSql/queries/**/*\" dist/prodSql/queries --parents",
"lint": "tsc && biome lint",
"start": "npm run start:server",
"start:server": "dotenvx run -f .env -- node dist/server.js",
"start:docker": "node dist/server.js",
"version": "changeset version",
"specCheck": "node scripts/check-route-specs.mjs",
"commit": "cz",
"release": "npm run build && commit-and-tag-version",
"build:apk": "cd lstMobile && expo prebuild --clean && cd android && gradlew.bat assembleRelease "
},
"repository": {
"type": "git",
"url": "https://git.tuffraid.net/cowch/lst_v3.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"devDependencies": {
"@biomejs/biome": "2.4.8",
"@commitlint/cli": "^20.5.0",
"@commitlint/config-conventional": "^20.5.0",
"@types/archiver": "^7.0.0",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/morgan": "^1.9.10",
"@types/mssql": "^9.1.9",
"@types/multer": "^2.1.0",
"@types/net-snmp": "^3.23.0",
"@types/node": "^25.5.0",
"@types/nodemailer": "^7.0.11",
"@types/nodemailer-express-handlebars": "^4.0.6",
"@types/pg": "^8.18.0",
"@types/supertest": "^7.2.0",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.8",
"commit-and-tag-version": "^12.7.1",
"commitizen": "^4.3.1",
"cpy-cli": "^7.0.0",
"cz-conventional-changelog": "^3.3.0",
"npm-check-updates": "^19.6.5",
"openapi-types": "^12.1.3",
"supertest": "^7.2.2",
"ts-node-dev": "^2.0.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vitest": "^4.1.8"
},
"dependencies": {
"@dotenvx/dotenvx": "^1.57.0",
"@scalar/express-api-reference": "^0.9.20",
"@socket.io/admin-ui": "^0.5.1",
"archiver": "^7.0.1",
"axios": "^1.13.6",
"bcryptjs": "^3.0.3",
"better-auth": "^1.5.5",
"chokidar": "^5.0.0",
"concurrently": "^9.2.1",
"cors": "^2.8.6",
"croner": "^10.0.1",
"date-fns": "^4.1.0",
"date-fns-tz": "^3.2.0",
"drizzle-kit": "^0.31.10",
"drizzle-orm": "^0.45.1",
"drizzle-zod": "^0.8.3",
"excel-date-to-js": "^1.1.5",
"express": "^5.2.1",
"husky": "^9.1.7",
"ldapts": "^8.1.7",
"modbus-serial": "^8.0.25",
"morgan": "^1.10.1",
"mssql": "^12.2.1",
"multer": "^2.1.1",
"net-snmp": "^3.26.1",
"nodemailer": "^8.0.3",
"nodemailer-express-handlebars": "^7.0.0",
"pg": "^8.20.0",
"pino": "^10.3.1",
"pino-pretty": "^13.1.3",
"postgres": "^3.4.8",
"powershell": "^2.3.3",
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"xlsx": "^0.18.5",
"zod": "^4.3.6",
"zod-openapi": "^6.0.0"
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
}

View File

@@ -31,24 +31,32 @@ function Update-Server {
[string]$Server,
[string]$Token
)
$buildFile = Join-Path $AppDir ".buildNumber"
$buildFile = Join-Path $AppDir "package.json"
$BuildNumber = 1
$BuildFolder = Join-Path $AppDir "builds"
if (Test-Path $BuildFile) {
$content = Get-Content $BuildFile | Select-Object -First 1
$num = $content.Trim() -as [int] # safe cast
$packageJson = Get-Content $buildFile -Raw | ConvertFrom-Json
# Extract the .build property and cast it safely to an integer
$num = "$($packageJson.version).$(([int]$packageJson.build) -1)"
# if (Test-Path $BuildFile) {
# # Parse the entire JSON file into a PowerShell object
# $packageJson = Get-Content $buildFile -Raw | ConvertFrom-Json
# # Extract the .build property and cast it safely to an integer
# $num = "($packageJson.version).($packageJson.build)"
if ($num) {
$BuildNumber = $num + 1
}
else {
$BuildNumber = 1
}
}
# if ($null -ne $num) {
# $BuildNumber = $num + 1
# }
# else {
# $BuildNumber = 1
# }
# }
# Get The current Build we have zipped up
$BuildNumber = ([int]$BuildNumber - 1).ToString()
$BuildNumber = $num
# copy the latest build over