From f6bf6a7abe3c0be30949b0e64154e2719df7cbf1 Mon Sep 17 00:00:00 2001 From: Jonathan Baldie Date: Thu, 23 Jul 2026 10:51:52 +0100 Subject: [PATCH 1/2] chore: add pinned messcript quality gate --- .serena/project.yml | 77 +++++++++++---------- README.md | 29 ++++++++ package.json | 12 ++++ scripts/messcript.mjs | 153 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 236 insertions(+), 35 deletions(-) create mode 100644 package.json create mode 100644 scripts/messcript.mjs diff --git a/.serena/project.yml b/.serena/project.yml index 208ffdb..c264f02 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -1,41 +1,6 @@ # the name by which the project can be referenced within Serena/when chatting with the LLM. project_name: "queue" -# list of languages for which language servers are started (LSP backend only); choose from: -# ada al angular ansible bash -# bsl clojure cpp cpp_ccls crystal -# csharp csharp_omnisharp cue dart elixir -# elm erlang fortran fsharp gdscript -# go groovy haskell haxe hlsl -# html java json julia kotlin -# latex lean4 lua luau markdown -# matlab msl nix ocaml pascal -# perl php php_phpactor php_phpantom powershell -# python python_jedi python_pyrefly python_ty r -# rego ruby ruby_solargraph rust scala -# scss solidity svelte swift systemverilog -# terraform toml typescript typescript_vts vue -# yaml zig -# (This list may be outdated; generated with scripts/print_language_list.py; -# For the current list, see values of Language enum here: -# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py) -# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) -# Note: -# - For C, use cpp -# - For JavaScript, use typescript -# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root) -# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm) -# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three) -# - For Free Pascal/Lazarus, use pascal -# Special requirements: -# Some languages require additional setup/installations. -# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers -# When using multiple languages, the first language server that supports a given file will be used for that file. -# The first language is the default language and the respective language server will be used as a fallback. -# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. -languages: -- typescript - # the encoding used by text files in the project # For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings encoding: "utf-8" @@ -63,6 +28,13 @@ ls_specific_settings: {} # list of additional paths to ignore in this project. # Same syntax as gitignore, so you can use * and **. +# Important: quote patterns that start with `*`, otherwise YAML treats them as aliases. +# Example: +# ignored_paths: +# - "examples/**" +# - ".worktrees/**" +# - "**/bin/**" +# - "**/obj/**" # Note: global ignored_paths from serena_config.yml are also applied additively. ignored_paths: [] @@ -158,3 +130,38 @@ ls_additional_workspace_folders: [] # - "./subproject2" ls_workspace_folders: - . + +# list of language servers to start when using the LSP backend; choose from: +# ada al angular ansible bash +# bsl clojure cpp cpp_ccls crystal +# csharp csharp_omnisharp cue dart elixir +# elm erlang fortran fsharp gdscript +# go groovy haskell haxe hlsl +# html java json julia kotlin +# latex lean4 lua luau markdown +# matlab msl nix ocaml pascal +# perl php php_phpactor php_phpantom powershell +# python python_jedi python_pyrefly python_ty r +# rego ruby ruby_solargraph rust scala +# scss solidity svelte swift systemverilog +# terraform toml typescript typescript_vts vue +# yaml zig +# (This list may be outdated; generated with scripts/print_language_list.py; +# For the current list, see values of Language enum here: +# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py) +# For some languages, there are several alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) +# Note: +# - For C, use cpp +# - For JavaScript, use typescript +# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root) +# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm) +# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three) +# - For Free Pascal/Lazarus, use pascal +# Special requirements: +# Some language servers require additional setup/installations. +# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers +# When using multiple language servers, the first language server that supports a given file will be used for that file. +# The first language server is the default language and the respective language server will be used as a fallback. +# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. +language_servers: +- typescript diff --git a/README.md b/README.md index 16aa4e8..65ae2b4 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,35 @@ This returns the oldest added payload on queue `foo` and removes it, guaranteein That's all you need to get started! 😎 +## Production quality gate + +The production TypeScript quality gate uses messcript at the pinned commit +`4fe47bd0f15675206aedd0f22ae5eff7aeb01707`. The Node wrapper checks out that +revision into the ignored `node_modules/.cache/queue-messcript` directory, +installs its locked dependencies, builds it, and then runs the CLI. It does not +affect the Deno service or its dependencies. + +Run a named production unit with Node 20.11 or newer: + +``` +npm run quality:unit -- configuration +``` + +The available units are `configuration`, `router`, `middleware`, +`rate-limiter`, `queue-manager`, `persist-engine`, `http-handler`, and +`entrypoint`. Run the complete production gate with: + +``` +npm run quality:production +``` + +Both commands use messcript's recommended `typescript` policy, including its +default `CyclomaticComplexity` and `NPathComplexity` rules and thresholds. The +aggregate scope is explicit: it includes only the eight production units above +and excludes tests, mutation infrastructure, documentation, CI configuration, +generated output, and development tooling. Findings and processing errors +retain messcript's normal non-zero exit status. + To get the number of payloads pending on a queue, send a get request to `/length/:queue` ``` diff --git a/package.json b/package.json new file mode 100644 index 0000000..7e9cf72 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "queue-quality-gate", + "private": true, + "type": "module", + "engines": { + "node": ">=20.11.0" + }, + "scripts": { + "quality:unit": "node scripts/messcript.mjs", + "quality:production": "node scripts/messcript.mjs all" + } +} diff --git a/scripts/messcript.mjs b/scripts/messcript.mjs new file mode 100644 index 0000000..45fb6d2 --- /dev/null +++ b/scripts/messcript.mjs @@ -0,0 +1,153 @@ +import { spawnSync } from "node:child_process"; +import { existsSync, mkdirSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import process from "node:process"; +import { fileURLToPath } from "node:url"; + +const projectRoot = join(dirname(fileURLToPath(import.meta.url)), ".."); +const messcriptRepository = "https://github.com/quality-gates/messcript.git"; +const messcriptCommit = "4fe47bd0f15675206aedd0f22ae5eff7aeb01707"; +const toolRoot = join(projectRoot, "node_modules", ".cache", "queue-messcript"); +const buildMarker = join(toolRoot, `.built-${messcriptCommit}`); +const messcriptCli = join(toolRoot, "dist", "cli.js"); + +const productionUnits = new Map([ + ["configuration", ["src/config.ts"]], + ["router", ["src/router.ts"]], + ["middleware", ["src/middleware.ts"]], + ["rate-limiter", ["src/rate_limiter.ts"]], + ["queue-manager", ["src/manager.ts"]], + ["persist-engine", ["src/persist.ts"]], + ["http-handler", ["src/handler.ts"]], + ["entrypoint", ["main.ts"]], +]); + +function run(command, args, cwd) { + const result = spawnSync(command, args, { + cwd, + stdio: "inherit", + }); + + if (result.error) { + console.error(`Unable to run ${command}: ${result.error.message}`); + return 1; + } + + return result.status ?? 1; +} + +function capture(command, args, cwd) { + const result = spawnSync(command, args, { + cwd, + encoding: "utf8", + }); + + if (result.error || result.status !== 0) { + return undefined; + } + + return result.stdout.trim(); +} + +function acquireMesscript() { + mkdirSync(dirname(toolRoot), { recursive: true }); + + if (!existsSync(join(toolRoot, ".git"))) { + if (existsSync(toolRoot)) { + throw new Error(`${toolRoot} exists but is not a Git checkout`); + } + + const cloneExit = run("git", [ + "clone", + "--quiet", + messcriptRepository, + toolRoot, + ], projectRoot); + if (cloneExit !== 0) { + return cloneExit; + } + } + + const fetchExit = run( + "git", + ["fetch", "--quiet", "origin", messcriptCommit], + toolRoot, + ); + if (fetchExit !== 0) { + return fetchExit; + } + + const checkoutExit = run("git", [ + "checkout", + "--quiet", + "--detach", + messcriptCommit, + ], toolRoot); + if (checkoutExit !== 0) { + return checkoutExit; + } + + const checkedOutCommit = capture("git", ["rev-parse", "HEAD"], toolRoot); + if (checkedOutCommit !== messcriptCommit) { + throw new Error( + `messcript checkout is ${ + checkedOutCommit ?? "unknown" + }, expected ${messcriptCommit}`, + ); + } + + if (!existsSync(buildMarker) || !existsSync(messcriptCli)) { + const installExit = run("npm", [ + "ci", + "--ignore-scripts", + "--no-audit", + "--no-fund", + ], toolRoot); + if (installExit !== 0) { + return installExit; + } + + const buildExit = run("npm", ["run", "build"], toolRoot); + if (buildExit !== 0) { + return buildExit; + } + + writeFileSync(buildMarker, `${messcriptCommit}\n`); + } + + return 0; +} + +function requestedPaths(unitName) { + if (unitName === "all") { + return [...productionUnits.values()].flat(); + } + + const paths = productionUnits.get(unitName); + if (!paths) { + const names = [...productionUnits.keys(), "all"].join(", "); + throw new Error( + `Unknown production unit '${unitName}'. Choose one of: ${names}`, + ); + } + return paths; +} + +const unitName = process.argv[2] ?? "all"; + +try { + const paths = requestedPaths(unitName); + const acquireExit = acquireMesscript(); + if (acquireExit !== 0) { + process.exitCode = acquireExit; + } else { + process.exitCode = run( + "node", + [messcriptCli, paths.join(","), "text", "typescript", "--color=never"], + projectRoot, + ); + } +} catch (error) { + console.error(error instanceof Error ? error.message : error); + process.exitCode = 1; +} From 1095cca28625ce09b9ba1b23a98069a4a980738b Mon Sep 17 00:00:00 2001 From: Jonathan Baldie Date: Thu, 23 Jul 2026 11:06:02 +0100 Subject: [PATCH 2/2] fix: preserve existing Node script semantics --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 7e9cf72..5ab1960 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "name": "queue-quality-gate", "private": true, - "type": "module", "engines": { "node": ">=20.11.0" },