Inspect constructor values and contexts without unrelated derivation closures (#931)
This commit is contained in:
parent
61881f9cda
commit
4f672d027d
@@ -0,0 +1,34 @@
|
|||||||
|
# Read actual constructor attributes as comparison data. Their values AND
|
||||||
|
# dependency contexts remain visible; none is substituted for a build input.
|
||||||
|
derivation:
|
||||||
|
let
|
||||||
|
fields = [
|
||||||
|
"name"
|
||||||
|
"system"
|
||||||
|
"src"
|
||||||
|
"stdenv"
|
||||||
|
"nativeBuildInputs"
|
||||||
|
"buildInputs"
|
||||||
|
"propagatedBuildInputs"
|
||||||
|
"propagatedNativeBuildInputs"
|
||||||
|
"configurePhase"
|
||||||
|
"buildPhase"
|
||||||
|
"checkPhase"
|
||||||
|
"installPhase"
|
||||||
|
"doCheck"
|
||||||
|
"strictDeps"
|
||||||
|
"outputs"
|
||||||
|
"__structuredAttrs"
|
||||||
|
];
|
||||||
|
selected = builtins.intersectAttrs (builtins.listToAttrs (
|
||||||
|
map (name: {
|
||||||
|
inherit name;
|
||||||
|
value = null;
|
||||||
|
}) fields
|
||||||
|
)) derivation;
|
||||||
|
in
|
||||||
|
builtins.mapAttrs (_: value: {
|
||||||
|
type = builtins.typeOf value;
|
||||||
|
value = builtins.unsafeDiscardStringContext (toString value);
|
||||||
|
context = builtins.getContext (toString value);
|
||||||
|
}) selected
|
||||||
+18
-22
@@ -34,6 +34,7 @@ function identity() {
|
|||||||
derivation = compiler.drvPath;
|
derivation = compiler.drvPath;
|
||||||
yarn = compiler.yarn-freestanding.drvPath;
|
yarn = compiler.yarn-freestanding.drvPath;
|
||||||
source = toString compiler.src;
|
source = toString compiler.src;
|
||||||
|
metadata = (import ((/. + ${nixString(source)}) + "/source-qualification-metadata.nix")) compiler;
|
||||||
}`;
|
}`;
|
||||||
const result = spawnSync(
|
const result = spawnSync(
|
||||||
"nix",
|
"nix",
|
||||||
@@ -52,17 +53,6 @@ function identity() {
|
|||||||
assert.equal(result.status, 0, result.error?.message ?? result.stderr);
|
assert.equal(result.status, 0, result.error?.message ?? result.stderr);
|
||||||
return JSON.parse(result.stdout);
|
return JSON.parse(result.stdout);
|
||||||
}
|
}
|
||||||
function derivationData(file) {
|
|
||||||
const result = spawnSync(
|
|
||||||
"nix",
|
|
||||||
["--store", "local?root=" + process.env.QUIXOS_PROTOCOL_EVALUATION_STORE, "derivation", "show", file],
|
|
||||||
{ encoding: "utf8", timeout: 30000, maxBuffer: 2097152 },
|
|
||||||
);
|
|
||||||
assert.equal(result.status, 0, result.error?.message ?? result.stderr);
|
|
||||||
const entries = Object.values(JSON.parse(result.stdout));
|
|
||||||
assert.equal(entries.length, 1);
|
|
||||||
return entries[0];
|
|
||||||
}
|
|
||||||
function summarized(value) {
|
function summarized(value) {
|
||||||
const text = JSON.stringify(value) ?? "undefined";
|
const text = JSON.stringify(value) ?? "undefined";
|
||||||
return text.length < 500
|
return text.length < 500
|
||||||
@@ -74,7 +64,7 @@ function summarized(value) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
function structuralDifferences(actual, expected, field = "", result = []) {
|
function structuralDifferences(actual, expected, field = "", result = []) {
|
||||||
if (field === "outputs" || field === "env.out" || JSON.stringify(actual) === JSON.stringify(expected)) return result;
|
if (JSON.stringify(actual) === JSON.stringify(expected)) return result;
|
||||||
if (
|
if (
|
||||||
Array.isArray(actual) &&
|
Array.isArray(actual) &&
|
||||||
Array.isArray(expected) &&
|
Array.isArray(expected) &&
|
||||||
@@ -99,15 +89,24 @@ function structuralDifferences(actual, expected, field = "", result = []) {
|
|||||||
for (const key of new Set([...Object.keys(actual), ...Object.keys(expected)]))
|
for (const key of new Set([...Object.keys(actual), ...Object.keys(expected)]))
|
||||||
structuralDifferences(actual[key], expected[key], field ? field + "." + key : key, result);
|
structuralDifferences(actual[key], expected[key], field ? field + "." + key : key, result);
|
||||||
} else {
|
} else {
|
||||||
result.push({ field, actual: summarized(actual), expected: summarized(expected) });
|
const difference = { field, actual: summarized(actual), expected: summarized(expected) };
|
||||||
|
if (typeof actual === "string" && typeof expected === "string" && Math.max(actual.length, expected.length) >= 500) {
|
||||||
|
let offset = 0;
|
||||||
|
while (offset < actual.length && offset < expected.length && actual[offset] === expected[offset]) offset++;
|
||||||
|
difference.offset = offset;
|
||||||
|
difference.actualExcerpt = actual.slice(Math.max(0, offset - 80), offset + 200);
|
||||||
|
difference.expectedExcerpt = expected.slice(Math.max(0, offset - 80), offset + 200);
|
||||||
|
}
|
||||||
|
result.push(difference);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
function baselineDifference(baseline) {
|
function baselineDifference(baseline) {
|
||||||
|
const { metadata, ...identities } = baseline;
|
||||||
console.log(
|
console.log(
|
||||||
"PROTOCOL_SOURCE_BASELINE: " +
|
"PROTOCOL_SOURCE_BASELINE: " +
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
actual: baseline,
|
actual: identities,
|
||||||
expected: config.expected,
|
expected: config.expected,
|
||||||
expectedSource: config.expectedSource,
|
expectedSource: config.expectedSource,
|
||||||
evaluatorVersion: config.evaluatorVersion,
|
evaluatorVersion: config.evaluatorVersion,
|
||||||
@@ -115,15 +114,10 @@ function baselineDifference(baseline) {
|
|||||||
narHashContext: config.narHashContext,
|
narHashContext: config.narHashContext,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
try {
|
|
||||||
const actual = derivationData(baseline.derivation);
|
|
||||||
const expected = derivationData(config.productionDerivation);
|
|
||||||
console.log(
|
console.log(
|
||||||
"PROTOCOL_SOURCE_BASELINE_DIFF: " + JSON.stringify(structuralDifferences(actual, expected)).slice(0, 10000),
|
"PROTOCOL_SOURCE_BASELINE_DIFF: " +
|
||||||
|
JSON.stringify(structuralDifferences(metadata, config.expectedMetadata)).slice(0, 10000),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
console.log("PROTOCOL_SOURCE_BASELINE_DIAGNOSTIC_UNAVAILABLE: " + String(error.message).slice(0, 2000));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async function edit(file, mutate, check) {
|
async function edit(file, mutate, check) {
|
||||||
const before = await fs.readFile(file, "utf8");
|
const before = await fs.readFile(file, "utf8");
|
||||||
@@ -244,7 +238,9 @@ try {
|
|||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
{
|
{
|
||||||
codec: "quixos-protocol-source-qualification/1",
|
codec: "quixos-protocol-source-qualification/1",
|
||||||
...baseline,
|
derivation: baseline.derivation,
|
||||||
|
yarn: baseline.yarn,
|
||||||
|
source: baseline.source,
|
||||||
cases,
|
cases,
|
||||||
metadataContext: config.narHashContext,
|
metadataContext: config.narHashContext,
|
||||||
evaluatorVersion: config.evaluatorVersion,
|
evaluatorVersion: config.evaluatorVersion,
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
comparisonIdentity = import ../tools/local-first/derivation-identity.nix;
|
comparisonIdentity = import ../tools/local-first/derivation-identity.nix;
|
||||||
# Inspect the actual .drv as data, without its derivation-deep output context.
|
inspect = import ./source-qualification-metadata.nix;
|
||||||
productionDerivation = builtins.unsafeDiscardOutputDependency library.drvPath;
|
|
||||||
source = pkgs.lib.fileset.toSource {
|
source = pkgs.lib.fileset.toSource {
|
||||||
root = ./.;
|
root = ./.;
|
||||||
fileset = pkgs.lib.fileset.unions [
|
fileset = pkgs.lib.fileset.unions [
|
||||||
@@ -23,6 +22,7 @@ let
|
|||||||
./tsconfig.build.json
|
./tsconfig.build.json
|
||||||
./tsconfig.test.json
|
./tsconfig.test.json
|
||||||
./default.nix
|
./default.nix
|
||||||
|
./source-qualification-metadata.nix
|
||||||
./yarn-project.nix
|
./yarn-project.nix
|
||||||
./flake.nix
|
./flake.nix
|
||||||
./README.md
|
./README.md
|
||||||
@@ -30,23 +30,19 @@ let
|
|||||||
};
|
};
|
||||||
inputs = pkgs.writeText "protocol-source-inputs.json" (
|
inputs = pkgs.writeText "protocol-source-inputs.json" (
|
||||||
builtins.toJSON {
|
builtins.toJSON {
|
||||||
inherit source nixpkgsNarHash productionDerivation;
|
inherit source nixpkgsNarHash;
|
||||||
narHashContext = builtins.getContext nixpkgsNarHash;
|
narHashContext = builtins.getContext nixpkgsNarHash;
|
||||||
evaluatorVersion = builtins.nixVersion;
|
evaluatorVersion = builtins.nixVersion;
|
||||||
pinnedNixVersion = pkgs.nix.version;
|
pinnedNixVersion = pkgs.nix.version;
|
||||||
nixpkgs = pkgs.path;
|
nixpkgs = pkgs.path;
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
expected = comparisonIdentity library;
|
expected = comparisonIdentity library;
|
||||||
|
expectedMetadata = inspect library;
|
||||||
expectedSource = builtins.unsafeDiscardStringContext (toString library.src);
|
expectedSource = builtins.unsafeDiscardStringContext (toString library.src);
|
||||||
yarn = comparisonIdentity library.yarn-freestanding;
|
yarn = comparisonIdentity library.yarn-freestanding;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
closure = pkgs.closureInfo {
|
closure = pkgs.closureInfo { rootPaths = [ pkgs.path ]; };
|
||||||
rootPaths = [
|
|
||||||
pkgs.path
|
|
||||||
productionDerivation
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
pkgs.runCommand "quixos-protocol-source-check"
|
pkgs.runCommand "quixos-protocol-source-check"
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user