@metasession.co/devaudit-cli 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -54,7 +54,7 @@ function emitJsonResult(payload) {
54
54
 
55
55
  // package.json
56
56
  var package_default = {
57
- version: "0.1.13"};
57
+ version: "0.1.15"};
58
58
 
59
59
  // src/lib/version.ts
60
60
  var CLI_VERSION = package_default.version;
@@ -235,6 +235,57 @@ async function checkNodeVersion() {
235
235
  const ok2 = major >= 22;
236
236
  return { name: "node", ok: ok2, detail: `v${version} (require >=22)` };
237
237
  }
238
+ async function checkReleaseCloseoutDrift() {
239
+ const name = "releases";
240
+ let cfg;
241
+ try {
242
+ cfg = JSON.parse(await promises.readFile("sdlc-config.json", "utf-8"));
243
+ } catch {
244
+ return { name, ok: true, detail: "skipped (not a consumer project)" };
245
+ }
246
+ let entries;
247
+ try {
248
+ entries = await promises.readdir("compliance/pending-releases");
249
+ } catch {
250
+ return { name, ok: true, detail: "no pending-releases/" };
251
+ }
252
+ const reqs = entries.filter((f) => /^RELEASE-TICKET-REQ-\d+\.md$/.test(f)).map((f) => f.replace(/^RELEASE-TICKET-/, "").replace(/\.md$/, ""));
253
+ if (reqs.length === 0) return { name, ok: true, detail: "no pending release tickets" };
254
+ const slug = cfg.devaudit?.project_slug ?? cfg.project_slug;
255
+ const base = (cfg.devaudit?.base_url ?? "").replace(/\/$/, "");
256
+ const apiKey = process.env["DEVAUDIT_API_KEY"];
257
+ if (!slug || !base || !apiKey) {
258
+ return {
259
+ name,
260
+ ok: true,
261
+ detail: `${reqs.length} pending ticket(s); portal drift check skipped (set DEVAUDIT_API_KEY + devaudit.base_url)`
262
+ };
263
+ }
264
+ const drifted = [];
265
+ for (const req of reqs) {
266
+ try {
267
+ const ctrl = new AbortController();
268
+ const timer = setTimeout(() => ctrl.abort(), 1e4);
269
+ const res = await fetch(
270
+ `${base}/api/ci/releases/resolve?projectSlug=${encodeURIComponent(slug)}&versionPrefix=${encodeURIComponent(req)}`,
271
+ { headers: { Authorization: `Bearer ${apiKey}` }, signal: ctrl.signal }
272
+ );
273
+ clearTimeout(timer);
274
+ if (!res.ok) continue;
275
+ const body = await res.json();
276
+ if (body.latest?.status === "released") drifted.push(req);
277
+ } catch {
278
+ }
279
+ }
280
+ if (drifted.length > 0) {
281
+ return {
282
+ name,
283
+ ok: false,
284
+ detail: `released on the portal but still in pending-releases/: ${drifted.join(", ")} \u2014 run ./scripts/close-out-release.sh <REQ>`
285
+ };
286
+ }
287
+ return { name, ok: true, detail: `${reqs.length} pending ticket(s); none released on the portal` };
288
+ }
238
289
  async function runDoctor(options = {}) {
239
290
  const log = logger();
240
291
  log.info("Running devaudit doctor \u2014 checking required tools...\n");
@@ -251,7 +302,13 @@ async function runDoctor(options = {}) {
251
302
  if (!check.ok) allOk = false;
252
303
  log.log(` ${marker} ${check.name.padEnd(8)} ${check.detail}`);
253
304
  }
305
+ const closeout = await checkReleaseCloseoutDrift();
306
+ const closeoutMarker = closeout.ok ? "\u2713" : "\u26A0";
307
+ log.log(` ${closeoutMarker} ${closeout.name.padEnd(8)} ${closeout.detail}`);
254
308
  log.log("");
309
+ if (!closeout.ok) {
310
+ log.warn("Release close-out drift detected \u2014 see above. (Does not affect the tool check.)");
311
+ }
255
312
  const plugins = options.plugins ?? (await discoverPlugins()).loaded;
256
313
  if (plugins.length > 0) {
257
314
  const ctx = await buildPluginContext({ projectPath: resolve(process.cwd()) });
@@ -1741,7 +1798,8 @@ var CI_TEMPLATES = [
1741
1798
  "compliance-validation.yml.template",
1742
1799
  "check-release-approval.yml.template",
1743
1800
  "post-deploy-prod.yml.template",
1744
- "compliance-evidence.yml.template"
1801
+ "compliance-evidence.yml.template",
1802
+ "close-out-release.yml.template"
1745
1803
  ];
1746
1804
  var OLD_WORKFLOWS_TO_REMOVE = ["test-on-pr.yml", "check-uat-approval.yml"];
1747
1805
  function indentEnvBlock(env, indent) {