executable-stories-formatters 0.11.0 → 0.11.1
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/cli.js +722 -193
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +245 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -2
- package/dist/index.d.ts +88 -2
- package/dist/index.js +237 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import "fs";
|
|
3
|
-
import * as
|
|
3
|
+
import * as path11 from "path";
|
|
4
4
|
import * as fsPromises from "fs/promises";
|
|
5
5
|
|
|
6
6
|
// src/converters/acl/status.ts
|
|
@@ -889,23 +889,23 @@ function buildFeature(relSourceFile, group) {
|
|
|
889
889
|
function ensureUniqueFeatureIds(features) {
|
|
890
890
|
const seen = /* @__PURE__ */ new Map();
|
|
891
891
|
for (const f of features) {
|
|
892
|
-
const
|
|
893
|
-
if (
|
|
894
|
-
seen.set(f.id,
|
|
892
|
+
const count2 = seen.get(f.id) ?? 0;
|
|
893
|
+
if (count2 > 0) f.id = `${f.id}-${count2 + 1}`;
|
|
894
|
+
seen.set(f.id, count2 + 1);
|
|
895
895
|
}
|
|
896
896
|
}
|
|
897
897
|
function ensureUniqueScenarioIds(feature) {
|
|
898
898
|
const seen = /* @__PURE__ */ new Map();
|
|
899
899
|
for (const s of feature.scenarios) {
|
|
900
|
-
const
|
|
901
|
-
if (
|
|
902
|
-
const newId = `${s.id}-${
|
|
900
|
+
const count2 = seen.get(s.id) ?? 0;
|
|
901
|
+
if (count2 > 0) {
|
|
902
|
+
const newId = `${s.id}-${count2 + 1}`;
|
|
903
903
|
for (const step of s.steps) {
|
|
904
904
|
step.id = step.id.replace(s.id, newId);
|
|
905
905
|
}
|
|
906
906
|
s.id = newId;
|
|
907
907
|
}
|
|
908
|
-
seen.set(s.id,
|
|
908
|
+
seen.set(s.id, count2 + 1);
|
|
909
909
|
}
|
|
910
910
|
}
|
|
911
911
|
function toStoryReport(run) {
|
|
@@ -15437,6 +15437,88 @@ function groupBy6(items, keyFn) {
|
|
|
15437
15437
|
return map;
|
|
15438
15438
|
}
|
|
15439
15439
|
|
|
15440
|
+
// src/formatters/release-manifest.ts
|
|
15441
|
+
import { createHash as createHash2 } from "crypto";
|
|
15442
|
+
var ReleaseManifestFormatter = class {
|
|
15443
|
+
format(run) {
|
|
15444
|
+
const manifest = toReleaseManifest(run);
|
|
15445
|
+
const lines = [];
|
|
15446
|
+
lines.push("# Release Manifest");
|
|
15447
|
+
lines.push("");
|
|
15448
|
+
lines.push(`Generated: ${manifest.generatedAt}`);
|
|
15449
|
+
lines.push(`Run: ${manifest.run.startedAt} to ${manifest.run.finishedAt}`);
|
|
15450
|
+
if (manifest.run.branch) lines.push(`Branch: ${manifest.run.branch}`);
|
|
15451
|
+
if (manifest.run.gitSha) lines.push(`Commit: ${manifest.run.gitSha}`);
|
|
15452
|
+
lines.push(`Tested-together hash: \`${manifest.testedTogetherHash}\``);
|
|
15453
|
+
lines.push("");
|
|
15454
|
+
lines.push("| Scenarios | Passed | Failed | Skipped | Pending |");
|
|
15455
|
+
lines.push("| ---: | ---: | ---: | ---: | ---: |");
|
|
15456
|
+
lines.push(`| ${manifest.run.total} | ${manifest.run.passed} | ${manifest.run.failed} | ${manifest.run.skipped} | ${manifest.run.pending} |`);
|
|
15457
|
+
lines.push("");
|
|
15458
|
+
lines.push("## Scenarios");
|
|
15459
|
+
lines.push("");
|
|
15460
|
+
lines.push("| Status | Scenario | Source | Tags |");
|
|
15461
|
+
lines.push("| --- | --- | --- | --- |");
|
|
15462
|
+
for (const scenario of manifest.scenarios) {
|
|
15463
|
+
const source = `${scenario.sourceFile}:${scenario.sourceLine}`;
|
|
15464
|
+
const tags = scenario.tags.length > 0 ? scenario.tags.map((tag) => `\`${tag}\``).join(", ") : "";
|
|
15465
|
+
lines.push(`| ${renderStatus(scenario.status)} | ${escapePipe(scenario.title)} | \`${source}\` | ${tags} |`);
|
|
15466
|
+
}
|
|
15467
|
+
return lines.join("\n");
|
|
15468
|
+
}
|
|
15469
|
+
};
|
|
15470
|
+
function toReleaseManifest(run) {
|
|
15471
|
+
const scenarios = [...run.testCases].sort((a, b) => a.id.localeCompare(b.id)).map((tc) => ({
|
|
15472
|
+
id: tc.id,
|
|
15473
|
+
title: tc.story.scenario,
|
|
15474
|
+
status: tc.status,
|
|
15475
|
+
sourceFile: tc.sourceFile,
|
|
15476
|
+
sourceLine: tc.sourceLine,
|
|
15477
|
+
tags: tc.tags
|
|
15478
|
+
}));
|
|
15479
|
+
const fingerprint = scenarios.map((scenario) => `${scenario.id}:${scenario.status}`).join("\n");
|
|
15480
|
+
return {
|
|
15481
|
+
schemaVersion: "1.0",
|
|
15482
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15483
|
+
run: {
|
|
15484
|
+
startedAt: new Date(run.startedAtMs).toISOString(),
|
|
15485
|
+
finishedAt: new Date(run.finishedAtMs).toISOString(),
|
|
15486
|
+
gitSha: run.gitSha,
|
|
15487
|
+
branch: getBranch(run),
|
|
15488
|
+
total: run.testCases.length,
|
|
15489
|
+
passed: count(run.testCases, "passed"),
|
|
15490
|
+
failed: count(run.testCases, "failed"),
|
|
15491
|
+
skipped: count(run.testCases, "skipped"),
|
|
15492
|
+
pending: count(run.testCases, "pending")
|
|
15493
|
+
},
|
|
15494
|
+
testedTogetherHash: createHash2("sha256").update(fingerprint).digest("hex"),
|
|
15495
|
+
scenarios
|
|
15496
|
+
};
|
|
15497
|
+
}
|
|
15498
|
+
function getBranch(run) {
|
|
15499
|
+
return run.ci?.branch;
|
|
15500
|
+
}
|
|
15501
|
+
function count(testCases, status) {
|
|
15502
|
+
return testCases.filter((tc) => tc.status === status).length;
|
|
15503
|
+
}
|
|
15504
|
+
function renderStatus(status) {
|
|
15505
|
+
switch (status) {
|
|
15506
|
+
case "passed":
|
|
15507
|
+
return "passed";
|
|
15508
|
+
case "failed":
|
|
15509
|
+
return "failed";
|
|
15510
|
+
case "skipped":
|
|
15511
|
+
return "skipped";
|
|
15512
|
+
case "pending":
|
|
15513
|
+
return "pending";
|
|
15514
|
+
default:
|
|
15515
|
+
return status;
|
|
15516
|
+
}
|
|
15517
|
+
}
|
|
15518
|
+
function escapePipe(value) {
|
|
15519
|
+
return value.replace(/\|/g, "\\|");
|
|
15520
|
+
}
|
|
15521
|
+
|
|
15440
15522
|
// src/formatters/cucumber-messages/synthesize-feature.ts
|
|
15441
15523
|
function extractFeatureName(testCases, uri) {
|
|
15442
15524
|
for (const tc of testCases) {
|
|
@@ -15503,7 +15585,7 @@ function synthesizeFeature(uri, testCases) {
|
|
|
15503
15585
|
}
|
|
15504
15586
|
|
|
15505
15587
|
// src/utils/cucumber-messages.ts
|
|
15506
|
-
import { createHash as
|
|
15588
|
+
import { createHash as createHash3 } from "crypto";
|
|
15507
15589
|
function msToTimestamp(ms) {
|
|
15508
15590
|
const seconds = Math.floor(ms / 1e3);
|
|
15509
15591
|
const nanos = Math.round(ms % 1e3 * 1e6);
|
|
@@ -15569,7 +15651,7 @@ function statusToCucumberStatus(status) {
|
|
|
15569
15651
|
}
|
|
15570
15652
|
function deterministicId(kind, salt, ...parts) {
|
|
15571
15653
|
const input = [salt, kind, ...parts].join("::");
|
|
15572
|
-
return
|
|
15654
|
+
return createHash3("sha1").update(input).digest("hex").slice(0, 36);
|
|
15573
15655
|
}
|
|
15574
15656
|
|
|
15575
15657
|
// src/formatters/cucumber-messages/build-gherkin-document.ts
|
|
@@ -16057,8 +16139,8 @@ function extractDocAttachments(step) {
|
|
|
16057
16139
|
}
|
|
16058
16140
|
return attachments;
|
|
16059
16141
|
}
|
|
16060
|
-
function guessMediaType(
|
|
16061
|
-
const lower =
|
|
16142
|
+
function guessMediaType(path12) {
|
|
16143
|
+
const lower = path12.toLowerCase();
|
|
16062
16144
|
if (lower.endsWith(".png")) return "image/png";
|
|
16063
16145
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
16064
16146
|
if (lower.endsWith(".gif")) return "image/gif";
|
|
@@ -16199,11 +16281,11 @@ var CucumberHtmlFormatter = class {
|
|
|
16199
16281
|
for (const envelope of envelopes) {
|
|
16200
16282
|
const accepted = htmlStream.write(envelope);
|
|
16201
16283
|
if (!accepted) {
|
|
16202
|
-
await new Promise((
|
|
16284
|
+
await new Promise((resolve9) => htmlStream.once("drain", resolve9));
|
|
16203
16285
|
}
|
|
16204
16286
|
}
|
|
16205
|
-
await new Promise((
|
|
16206
|
-
collector.on("finish",
|
|
16287
|
+
await new Promise((resolve9, reject) => {
|
|
16288
|
+
collector.on("finish", resolve9);
|
|
16207
16289
|
collector.on("error", reject);
|
|
16208
16290
|
htmlStream.end();
|
|
16209
16291
|
});
|
|
@@ -17267,8 +17349,8 @@ ${body}`;
|
|
|
17267
17349
|
}
|
|
17268
17350
|
buildFrontmatter(run) {
|
|
17269
17351
|
const badge = _AstroFormatter.computeBadge(run.testCases);
|
|
17270
|
-
const
|
|
17271
|
-
const description = `${
|
|
17352
|
+
const count2 = run.testCases.length;
|
|
17353
|
+
const description = `${count2} scenario${count2 !== 1 ? "s" : ""} \u2014 ${badge.text.toLowerCase()}`;
|
|
17272
17354
|
const lines = [
|
|
17273
17355
|
"---",
|
|
17274
17356
|
`title: ${yamlScalar(this.deriveTitle(run))}`,
|
|
@@ -18266,14 +18348,14 @@ ${result.errors.join("\n")}`);
|
|
|
18266
18348
|
}
|
|
18267
18349
|
|
|
18268
18350
|
// src/coverage-index.ts
|
|
18269
|
-
function normalizePath(
|
|
18270
|
-
return
|
|
18351
|
+
function normalizePath(path12) {
|
|
18352
|
+
return path12.replace(/^\.\//, "");
|
|
18271
18353
|
}
|
|
18272
18354
|
function scenariosCoveringPaths(index, paths) {
|
|
18273
18355
|
const queries = paths.map(normalizePath);
|
|
18274
18356
|
return index.scenarios.filter(
|
|
18275
18357
|
(scenario) => scenario.covers.some(
|
|
18276
|
-
(glob) => queries.some((
|
|
18358
|
+
(glob) => queries.some((path12) => matchesPattern(normalizePath(glob), path12))
|
|
18277
18359
|
)
|
|
18278
18360
|
);
|
|
18279
18361
|
}
|
|
@@ -20190,18 +20272,18 @@ function deriveChangeType(tags) {
|
|
|
20190
20272
|
}
|
|
20191
20273
|
return "unknown";
|
|
20192
20274
|
}
|
|
20193
|
-
function extensionOf(
|
|
20194
|
-
const base =
|
|
20275
|
+
function extensionOf(path12) {
|
|
20276
|
+
const base = path12.split("/").pop() ?? path12;
|
|
20195
20277
|
const dot = base.lastIndexOf(".");
|
|
20196
20278
|
return dot === -1 ? "" : base.slice(dot + 1).toLowerCase();
|
|
20197
20279
|
}
|
|
20198
|
-
function isTestFile(
|
|
20199
|
-
return TEST_INFIX.test(
|
|
20280
|
+
function isTestFile(path12) {
|
|
20281
|
+
return TEST_INFIX.test(path12);
|
|
20200
20282
|
}
|
|
20201
|
-
function isReviewableSource(
|
|
20202
|
-
if (isTestFile(
|
|
20203
|
-
if (
|
|
20204
|
-
return CODE_EXTENSIONS.has(extensionOf(
|
|
20283
|
+
function isReviewableSource(path12) {
|
|
20284
|
+
if (isTestFile(path12)) return false;
|
|
20285
|
+
if (path12.endsWith(".d.ts")) return false;
|
|
20286
|
+
return CODE_EXTENSIONS.has(extensionOf(path12));
|
|
20205
20287
|
}
|
|
20206
20288
|
function testBaseKey(testFile) {
|
|
20207
20289
|
return testFile.replace(TEST_INFIX, "");
|
|
@@ -20305,7 +20387,7 @@ function toClaim(testCase, changedSourcePaths) {
|
|
|
20305
20387
|
const { strength, reasons } = gradeEvidence(testCase, audience);
|
|
20306
20388
|
const key = testBaseKey(testCase.sourceFile);
|
|
20307
20389
|
const coversFiles = changedSourcePaths.filter(
|
|
20308
|
-
(
|
|
20390
|
+
(path12) => sourceBaseKey(path12) === key
|
|
20309
20391
|
);
|
|
20310
20392
|
return {
|
|
20311
20393
|
id: testCase.id,
|
|
@@ -20835,11 +20917,116 @@ applyTheme(getEffectiveTheme());` : "";
|
|
|
20835
20917
|
}
|
|
20836
20918
|
};
|
|
20837
20919
|
|
|
20920
|
+
// src/deploy/ledger.ts
|
|
20921
|
+
import * as fs9 from "fs";
|
|
20922
|
+
import * as path10 from "path";
|
|
20923
|
+
function createEmptyLedger() {
|
|
20924
|
+
return {
|
|
20925
|
+
deployments: [],
|
|
20926
|
+
schemaVersion: 1
|
|
20927
|
+
};
|
|
20928
|
+
}
|
|
20929
|
+
function loadLedger(ledgerPath) {
|
|
20930
|
+
const resolved = path10.resolve(ledgerPath);
|
|
20931
|
+
if (!fs9.existsSync(resolved)) {
|
|
20932
|
+
return createEmptyLedger();
|
|
20933
|
+
}
|
|
20934
|
+
try {
|
|
20935
|
+
const raw = JSON.parse(fs9.readFileSync(resolved, "utf8"));
|
|
20936
|
+
if (raw.schemaVersion !== 1) {
|
|
20937
|
+
throw new Error(`Unsupported ledger schemaVersion: ${raw.schemaVersion}`);
|
|
20938
|
+
}
|
|
20939
|
+
return raw;
|
|
20940
|
+
} catch (err) {
|
|
20941
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20942
|
+
throw new Error(`Failed to load deployment ledger at ${resolved}: ${msg}`);
|
|
20943
|
+
}
|
|
20944
|
+
}
|
|
20945
|
+
function saveLedger(ledger, ledgerPath) {
|
|
20946
|
+
const resolved = path10.resolve(ledgerPath);
|
|
20947
|
+
const dir = path10.dirname(resolved);
|
|
20948
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
20949
|
+
fs9.writeFileSync(resolved, JSON.stringify(ledger, null, 2), "utf8");
|
|
20950
|
+
}
|
|
20951
|
+
function getLatestDeployment(ledger, environment) {
|
|
20952
|
+
return [...ledger.deployments].reverse().find((d) => d.environment === environment);
|
|
20953
|
+
}
|
|
20954
|
+
|
|
20955
|
+
// src/deploy/index.ts
|
|
20956
|
+
function recordDeployment(args) {
|
|
20957
|
+
const ledger = loadLedger(args.ledgerPath);
|
|
20958
|
+
const previous = getLatestDeployment(ledger, args.environment);
|
|
20959
|
+
const entry = {
|
|
20960
|
+
environment: args.environment,
|
|
20961
|
+
tag: args.tag,
|
|
20962
|
+
sha: args.run.gitSha,
|
|
20963
|
+
runFile: args.runFilePath,
|
|
20964
|
+
scenarioIds: args.run.testCases.map((tc) => tc.id),
|
|
20965
|
+
scenarioStatuses: Object.fromEntries(args.run.testCases.map((tc) => [tc.id, tc.status])),
|
|
20966
|
+
timestamp: new Date(args.run.finishedAtMs).toISOString(),
|
|
20967
|
+
summary: countStatuses(args.run)
|
|
20968
|
+
};
|
|
20969
|
+
ledger.deployments.push(entry);
|
|
20970
|
+
if (previous) {
|
|
20971
|
+
const previousIds = new Set(previous.scenarioIds);
|
|
20972
|
+
const added = entry.scenarioIds.filter((id) => !previousIds.has(id)).length;
|
|
20973
|
+
const removed = previous.scenarioIds.filter((id) => !entry.scenarioIds.includes(id)).length;
|
|
20974
|
+
if (added > 0 || removed > 0) {
|
|
20975
|
+
}
|
|
20976
|
+
}
|
|
20977
|
+
saveLedger(ledger, args.ledgerPath);
|
|
20978
|
+
return { entry, ledgerPath: args.ledgerPath };
|
|
20979
|
+
}
|
|
20980
|
+
function getDeploymentStatus(ledgerPath) {
|
|
20981
|
+
const ledger = loadLedger(ledgerPath);
|
|
20982
|
+
const environments = {};
|
|
20983
|
+
for (const entry of ledger.deployments) {
|
|
20984
|
+
environments[entry.environment] = {
|
|
20985
|
+
latest: entry,
|
|
20986
|
+
previousDeployment: environments[entry.environment]?.latest
|
|
20987
|
+
};
|
|
20988
|
+
}
|
|
20989
|
+
return { environments, ledgerPath };
|
|
20990
|
+
}
|
|
20991
|
+
function getEnvironmentDrift(ledgerPath, envA, envB) {
|
|
20992
|
+
const ledger = loadLedger(ledgerPath);
|
|
20993
|
+
const aEntry = getLatestDeployment(ledger, envA);
|
|
20994
|
+
const bEntry = getLatestDeployment(ledger, envB);
|
|
20995
|
+
if (!aEntry) {
|
|
20996
|
+
throw new Error(`No deployment found for environment "${envA}"`);
|
|
20997
|
+
}
|
|
20998
|
+
if (!bEntry) {
|
|
20999
|
+
throw new Error(`No deployment found for environment "${envB}"`);
|
|
21000
|
+
}
|
|
21001
|
+
const aIds = new Set(aEntry.scenarioIds);
|
|
21002
|
+
const bIds = new Set(bEntry.scenarioIds);
|
|
21003
|
+
const onlyInA = aEntry.scenarioIds.filter((id) => !bIds.has(id));
|
|
21004
|
+
const onlyInB = bEntry.scenarioIds.filter((id) => !aIds.has(id));
|
|
21005
|
+
const inBoth = aEntry.scenarioIds.filter((id) => bIds.has(id));
|
|
21006
|
+
const statusChanged = inBoth.map((id) => ({
|
|
21007
|
+
id,
|
|
21008
|
+
statusA: aEntry.scenarioStatuses?.[id] ?? "unknown",
|
|
21009
|
+
statusB: bEntry.scenarioStatuses?.[id] ?? "unknown"
|
|
21010
|
+
})).filter((item) => item.statusA !== item.statusB);
|
|
21011
|
+
return { environmentA: envA, environmentB: envB, onlyInA, onlyInB, inBoth, statusChanged, aEntry, bEntry };
|
|
21012
|
+
}
|
|
21013
|
+
function countStatuses(run) {
|
|
21014
|
+
const summary = { total: 0, passed: 0, failed: 0, skipped: 0, pending: 0 };
|
|
21015
|
+
for (const tc of run.testCases) {
|
|
21016
|
+
summary.total++;
|
|
21017
|
+
if (tc.status in summary) {
|
|
21018
|
+
summary[tc.status]++;
|
|
21019
|
+
}
|
|
21020
|
+
}
|
|
21021
|
+
return summary;
|
|
21022
|
+
}
|
|
21023
|
+
|
|
20838
21024
|
// src/index.ts
|
|
20839
21025
|
var FORMAT_EXTENSIONS = {
|
|
20840
21026
|
astro: ".md",
|
|
20841
21027
|
"behavior-manifest-json": ".behavior-manifest.json",
|
|
20842
21028
|
markdown: ".md",
|
|
21029
|
+
"release-manifest": ".release-manifest.md",
|
|
20843
21030
|
html: ".html",
|
|
20844
21031
|
"cucumber-html": ".cucumber.html",
|
|
20845
21032
|
junit: ".junit.xml",
|
|
@@ -20878,11 +21065,11 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
20878
21065
|
const ext = FORMAT_EXTENSIONS[format];
|
|
20879
21066
|
const effectiveName = outputName + (outputNameSuffix ?? "");
|
|
20880
21067
|
if (mode === "aggregated") {
|
|
20881
|
-
return toPosix(
|
|
21068
|
+
return toPosix(path11.join(baseOutputDir, joinNameAndExt(effectiveName, ext)));
|
|
20882
21069
|
}
|
|
20883
21070
|
const normalizedSource = toPosix(sourceFile);
|
|
20884
|
-
const dirOfSource =
|
|
20885
|
-
let baseName =
|
|
21071
|
+
const dirOfSource = path11.posix.dirname(normalizedSource);
|
|
21072
|
+
let baseName = path11.posix.basename(normalizedSource);
|
|
20886
21073
|
for (const testExt of TEST_EXTENSIONS) {
|
|
20887
21074
|
if (baseName.endsWith(testExt)) {
|
|
20888
21075
|
baseName = baseName.slice(0, -testExt.length);
|
|
@@ -20891,12 +21078,12 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
20891
21078
|
}
|
|
20892
21079
|
const fileName = `${baseName}.${effectiveName}${ext}`;
|
|
20893
21080
|
if (colocatedStyle === "adjacent") {
|
|
20894
|
-
return toPosix(
|
|
21081
|
+
return toPosix(path11.posix.join(dirOfSource, fileName));
|
|
20895
21082
|
}
|
|
20896
21083
|
if (colocatedStyle === "flat") {
|
|
20897
|
-
return toPosix(
|
|
21084
|
+
return toPosix(path11.posix.join(baseOutputDir, `${cleanTestStem(normalizedSource)}${ext}`));
|
|
20898
21085
|
}
|
|
20899
|
-
return toPosix(
|
|
21086
|
+
return toPosix(path11.posix.join(baseOutputDir, dirOfSource, fileName));
|
|
20900
21087
|
}
|
|
20901
21088
|
function groupTestCasesByOutput(testCases, format, options, logger, outputNameSuffix) {
|
|
20902
21089
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -21103,8 +21290,8 @@ var ReportGenerator = class {
|
|
|
21103
21290
|
if (astroPaths) {
|
|
21104
21291
|
for (const mdPath of astroPaths) {
|
|
21105
21292
|
const content = await fsPromises.readFile(mdPath, "utf8");
|
|
21106
|
-
const mdDir =
|
|
21107
|
-
const assetsDir =
|
|
21293
|
+
const mdDir = path11.dirname(mdPath);
|
|
21294
|
+
const assetsDir = path11.resolve(this.options.astro.assetsDir);
|
|
21108
21295
|
const result = copyMarkdownAssets({
|
|
21109
21296
|
markdown: content,
|
|
21110
21297
|
markdownDir: mdDir,
|
|
@@ -21135,9 +21322,9 @@ var ReportGenerator = class {
|
|
|
21135
21322
|
if (groups.size === 0 && this.options.output.mode === "aggregated") {
|
|
21136
21323
|
const ext = FORMAT_EXTENSIONS[format];
|
|
21137
21324
|
const effectiveName = this.options.outputName + (outputNameSuffix ?? "");
|
|
21138
|
-
const outputPath = toPosix(
|
|
21325
|
+
const outputPath = toPosix(path11.join(this.options.outputDir, joinNameAndExt(effectiveName, ext)));
|
|
21139
21326
|
const content = await this.formatContent(run, format);
|
|
21140
|
-
const dir =
|
|
21327
|
+
const dir = path11.dirname(outputPath);
|
|
21141
21328
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
21142
21329
|
await this.deps.writeFile(outputPath, content);
|
|
21143
21330
|
return [outputPath];
|
|
@@ -21149,7 +21336,7 @@ var ReportGenerator = class {
|
|
|
21149
21336
|
testCases
|
|
21150
21337
|
};
|
|
21151
21338
|
const content = await this.formatContent(groupRun, format);
|
|
21152
|
-
const dir =
|
|
21339
|
+
const dir = path11.dirname(outputPath);
|
|
21153
21340
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
21154
21341
|
await this.deps.writeFile(outputPath, content);
|
|
21155
21342
|
writtenPaths.push(outputPath);
|
|
@@ -21258,6 +21445,10 @@ var ReportGenerator = class {
|
|
|
21258
21445
|
});
|
|
21259
21446
|
return formatter.format(run);
|
|
21260
21447
|
}
|
|
21448
|
+
case "release-manifest": {
|
|
21449
|
+
const formatter = new ReleaseManifestFormatter();
|
|
21450
|
+
return formatter.format(run);
|
|
21451
|
+
}
|
|
21261
21452
|
case "story-report-json": {
|
|
21262
21453
|
const formatter = new StoryReportJsonFormatter({
|
|
21263
21454
|
pretty: this.options.storyReportJson.pretty
|
|
@@ -21292,7 +21483,7 @@ async function generateRunComparison(args) {
|
|
|
21292
21483
|
await fsPromises.mkdir(outputDir, { recursive: true });
|
|
21293
21484
|
for (const format of args.formats) {
|
|
21294
21485
|
const ext = format === "html" ? ".html" : ".md";
|
|
21295
|
-
const outputPath = toPosix(
|
|
21486
|
+
const outputPath = toPosix(path11.join(outputDir, `${outputName}${ext}`));
|
|
21296
21487
|
const content = format === "html" ? new RunDiffHtmlFormatter({ title: args.title }).format(diff) : new RunDiffMarkdownFormatter({ title: args.title }).format(diff);
|
|
21297
21488
|
await fsPromises.writeFile(outputPath, content, "utf8");
|
|
21298
21489
|
files.push(outputPath);
|
|
@@ -21326,6 +21517,7 @@ export {
|
|
|
21326
21517
|
MIN_METRIC_SAMPLES,
|
|
21327
21518
|
MIN_PERF_SAMPLES,
|
|
21328
21519
|
MarkdownFormatter,
|
|
21520
|
+
ReleaseManifestFormatter,
|
|
21329
21521
|
ReportGenerator,
|
|
21330
21522
|
ReviewHtmlFormatter,
|
|
21331
21523
|
ReviewMarkdownFormatter,
|
|
@@ -21365,6 +21557,8 @@ export {
|
|
|
21365
21557
|
generateTestCaseId,
|
|
21366
21558
|
getAvailableThemes,
|
|
21367
21559
|
getCssOnlyThemes,
|
|
21560
|
+
getDeploymentStatus,
|
|
21561
|
+
getEnvironmentDrift,
|
|
21368
21562
|
gradeEvidence,
|
|
21369
21563
|
hasSufficientHistory,
|
|
21370
21564
|
isReviewableSource,
|
|
@@ -21386,6 +21580,7 @@ export {
|
|
|
21386
21580
|
readBranchName,
|
|
21387
21581
|
readGitSha,
|
|
21388
21582
|
readPackageVersion,
|
|
21583
|
+
recordDeployment,
|
|
21389
21584
|
regenerateArtifacts,
|
|
21390
21585
|
resolveAttachment,
|
|
21391
21586
|
resolveAttachments,
|
|
@@ -21405,6 +21600,7 @@ export {
|
|
|
21405
21600
|
toBehaviorManifest,
|
|
21406
21601
|
toCIInfo,
|
|
21407
21602
|
toRawCIInfo,
|
|
21603
|
+
toReleaseManifest,
|
|
21408
21604
|
toScenarioIndex,
|
|
21409
21605
|
toStoryReport,
|
|
21410
21606
|
tryGetActiveOtelContext,
|