fix(workflows): preserve punctuation in filesystem source paths (#521)
* fix(workflows): preserve punctuation in filesystem source paths Signed-off-by: RudyCelekli <47457359+rudycelekli@users.noreply.github.com> * fix(workflows): share scheme URL pattern in path normalization --------- Signed-off-by: RudyCelekli <47457359+rudycelekli@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
parent
056c123759
commit
5b28a8b331
|
|
@ -136,6 +136,86 @@ describe("historical source to bundle comparison", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("source to bundle path syntax", () => {
|
||||
it.each(["src/modified#part.ts", "src/modified?part.ts"])(
|
||||
"preserves literal filesystem punctuation in %s",
|
||||
(path) => {
|
||||
const node = moduleNode("punctuated", { path });
|
||||
const graph = createJavaScriptApplicationGraph({
|
||||
schema: "JavaScriptApplicationGraph",
|
||||
root_node_ids: [node.node_id],
|
||||
nodes: [node],
|
||||
edges: [],
|
||||
coverage: {
|
||||
status: "complete",
|
||||
truncated: false,
|
||||
omitted_count: 0,
|
||||
limits: [],
|
||||
},
|
||||
limitations: [],
|
||||
});
|
||||
const result = compareSourceToBundle({
|
||||
reference: historicalGraph("complete", [path]),
|
||||
application: {
|
||||
evidenceId: EVIDENCE_ID,
|
||||
rootArtifactSha256: HASH.artifact,
|
||||
graph,
|
||||
},
|
||||
});
|
||||
expect(item(result, path)).toMatchObject({
|
||||
status: "unknown",
|
||||
current_node_ids: [node.node_id],
|
||||
candidates: [
|
||||
expect.objectContaining({
|
||||
signals: expect.arrayContaining([
|
||||
expect.objectContaining({ kind: "current-path-exact" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
"https://example.test/src/modified.ts?revision=2#section",
|
||||
"webpack://fixture/./src/modified.ts?revision=2#section",
|
||||
])("still strips URL query and fragment from %s", (path) => {
|
||||
const node = moduleNode("url", { path });
|
||||
const graph = createJavaScriptApplicationGraph({
|
||||
schema: "JavaScriptApplicationGraph",
|
||||
root_node_ids: [node.node_id],
|
||||
nodes: [node],
|
||||
edges: [],
|
||||
coverage: {
|
||||
status: "complete",
|
||||
truncated: false,
|
||||
omitted_count: 0,
|
||||
limits: [],
|
||||
},
|
||||
limitations: [],
|
||||
});
|
||||
const result = compareSourceToBundle({
|
||||
reference: historicalGraph("complete", ["src/modified.ts"]),
|
||||
application: {
|
||||
evidenceId: EVIDENCE_ID,
|
||||
rootArtifactSha256: HASH.artifact,
|
||||
graph,
|
||||
},
|
||||
});
|
||||
expect(item(result, "src/modified.ts")).toMatchObject({
|
||||
status: "unknown",
|
||||
current_node_ids: [node.node_id],
|
||||
candidates: [
|
||||
expect.objectContaining({
|
||||
signals: expect.arrayContaining([
|
||||
expect.objectContaining({ kind: "current-path-suffix" }),
|
||||
]),
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("source to bundle complete metadata", () => {
|
||||
it("accepts long source metadata and all reported limitations", () => {
|
||||
const result = compareSourceToBundle({
|
||||
|
|
|
|||
|
|
@ -268,9 +268,16 @@ const addPath = (
|
|||
if (value !== null) paths.push({ kind, value });
|
||||
};
|
||||
|
||||
/** Matches a `scheme://...` URL prefix; bare filesystem paths keep `?`/`#`. */
|
||||
const SCHEME_URL = /^[a-z][a-z0-9+.-]*:\/\//iu;
|
||||
/** Matches a `scheme://...` URL prefix with any run of slashes, for stripping. */
|
||||
const SCHEME_URL_PREFIX = /^[a-z][a-z0-9+.-]*:\/\/+/iu;
|
||||
|
||||
const normalizeCurrentPath = (raw: string): string | null => {
|
||||
const withoutQuery = raw.split(/[?#]/u, 1)[0] ?? "";
|
||||
const withoutScheme = withoutQuery.replace(/^[a-z][a-z0-9+.-]*:\/\/+/iu, "");
|
||||
const withoutQuery = SCHEME_URL.test(raw)
|
||||
? (raw.split(/[?#]/u, 1)[0] ?? "")
|
||||
: raw;
|
||||
const withoutScheme = withoutQuery.replace(SCHEME_URL_PREFIX, "");
|
||||
const parts = withoutScheme
|
||||
.replaceAll("\\", "/")
|
||||
.split("/")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { analyzeJavaScriptApplication } from "../../../src/application/JavaScriptApplicationService.js";
|
||||
import { parseApplicationGraphEvidence } from "../../../src/application/JavaScriptApplicationEvidenceGraph.js";
|
||||
import { importReferenceSource } from "../../../src/application/ReferenceSourceImport.js";
|
||||
import { compareSourceToBundle } from "../../../src/domain/sourceToBundleComparison.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
it("keeps literal hash characters in historical/current filesystem paths", async () => {
|
||||
const root = await createTestTempDirectory("rea-source-path-");
|
||||
const previous = join(root, "previous");
|
||||
const current = join(root, "current");
|
||||
await Promise.all([mkdir(previous), mkdir(current)]);
|
||||
await Promise.all([
|
||||
writeFile(join(previous, "worker#main.js"), "export const value = 1;"),
|
||||
writeFile(join(current, "worker#main.js"), "export const value = 2;"),
|
||||
]);
|
||||
const reference = await importReferenceSource({
|
||||
root: previous,
|
||||
caller: "source-to-bundle-path-test",
|
||||
policy: { secretPatterns: [] },
|
||||
});
|
||||
if (!reference.ok) throw new Error(reference.error.message);
|
||||
const analyzed = await analyzeJavaScriptApplication({ input_path: current });
|
||||
if (!analyzed.ok) throw analyzed.error;
|
||||
const application = parseApplicationGraphEvidence(analyzed.value);
|
||||
const comparison = compareSourceToBundle({
|
||||
reference: reference.value,
|
||||
application: {
|
||||
evidenceId: application.evidence.evidence_id,
|
||||
rootArtifactSha256: application.rootArtifactSha256,
|
||||
graph: application.graph,
|
||||
},
|
||||
});
|
||||
|
||||
expect(reference.value.entries).toContainEqual(
|
||||
expect.objectContaining({
|
||||
kind: "file",
|
||||
path: "worker#main.js",
|
||||
content_state: "hashed",
|
||||
}),
|
||||
);
|
||||
expect(comparison.items).toContainEqual(
|
||||
expect.objectContaining({
|
||||
source_path: "worker#main.js",
|
||||
candidates: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
signals: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
kind: "current-path-exact",
|
||||
source_value: "worker#main.js",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
);
|
||||
});
|
||||
Loading…
Reference in New Issue