@abloh/cli 0.1.2 → 0.1.3-rc.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/index.js +77 -27
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import {
|
|
5
5
|
writeFileSync as writeFileSync11,
|
|
6
|
-
mkdirSync as
|
|
6
|
+
mkdirSync as mkdirSync10,
|
|
7
7
|
mkdtempSync as mkdtempSync10,
|
|
8
8
|
readFileSync as readFileSync23,
|
|
9
9
|
readlinkSync as readlinkSync4,
|
|
@@ -11089,6 +11089,7 @@ async function diagnoseBaselineFailures(input) {
|
|
|
11089
11089
|
import {
|
|
11090
11090
|
existsSync as existsSync9,
|
|
11091
11091
|
lstatSync as lstatSync12,
|
|
11092
|
+
mkdirSync as mkdirSync8,
|
|
11092
11093
|
readFileSync as readFileSync18,
|
|
11093
11094
|
readdirSync as readdirSync7,
|
|
11094
11095
|
rmSync as rmSync9,
|
|
@@ -11182,8 +11183,9 @@ Overrides:
|
|
|
11182
11183
|
|
|
11183
11184
|
--no-prepare skip the automatic vitest coverage-provider staging
|
|
11184
11185
|
|
|
11185
|
-
Writes abloh.yml
|
|
11186
|
-
|
|
11186
|
+
Writes abloh.yml and .github/workflows/abloh-check.yml. An abloh.yml you already have gets the
|
|
11187
|
+
environment block appended and every line already in it left alone; a workflow you already have is
|
|
11188
|
+
never touched. It refuses only when the policy file already configures
|
|
11187
11189
|
environment. It never modifies the repository otherwise \u2014 no dependency, manifest, lockfile, or
|
|
11188
11190
|
source changes, and it never runs tests. For a Vitest repository without @vitest/coverage-v8 it
|
|
11189
11191
|
stages that provider into Abloh's own cache (the one registry access; disable with --no-prepare).
|
|
@@ -11493,13 +11495,6 @@ function standardInstallCommand(packageManager, version, hasLockfile) {
|
|
|
11493
11495
|
}
|
|
11494
11496
|
function renderPolicyDefaults() {
|
|
11495
11497
|
return [
|
|
11496
|
-
"# DATA TIER \u2014 what leaves your CI.",
|
|
11497
|
-
"# 0 counts and locations only. No model calls.",
|
|
11498
|
-
"# 1 the review model runs here, under your credentials. Abloh receives structure only.",
|
|
11499
|
-
"# 2 Abloh also stores the mutated source span of each finding, the model's",
|
|
11500
|
-
"# reasoning and any test it proves. Your code is retained by Abloh.",
|
|
11501
|
-
"tier: 2",
|
|
11502
|
-
"",
|
|
11503
11498
|
"# THRESHOLD \u2014 the catch rate a run has to reach to pass. Abloh plants deliberate",
|
|
11504
11499
|
"# changes in your diff and counts how many your tests notice; 70 means seven in ten.",
|
|
11505
11500
|
"threshold: 70",
|
|
@@ -11554,6 +11549,45 @@ function renderPolicy(input) {
|
|
|
11554
11549
|
function declaresTopLevelKey(document, key) {
|
|
11555
11550
|
return new RegExp(String.raw`^${key}\s*:`, "mu").test(document);
|
|
11556
11551
|
}
|
|
11552
|
+
var WORKFLOW_RELATIVE_PATH = ".github/workflows/abloh-check.yml";
|
|
11553
|
+
var PINNED_ACTION = "Vero-Technology/abloh-action@3f8f0058d1ed1fae11d33a109e7e598bd3450097";
|
|
11554
|
+
function renderWorkflow(input) {
|
|
11555
|
+
const build = input.installCommand === null ? [" # Your normal build and dependency steps go here."] : [
|
|
11556
|
+
` - run: ${input.installCommand}`,
|
|
11557
|
+
...input.installDirectory === "." ? [] : [` working-directory: ${input.installDirectory}`]
|
|
11558
|
+
];
|
|
11559
|
+
return [
|
|
11560
|
+
"name: Abloh",
|
|
11561
|
+
"on:",
|
|
11562
|
+
" pull_request:",
|
|
11563
|
+
"",
|
|
11564
|
+
"jobs:",
|
|
11565
|
+
" abloh:",
|
|
11566
|
+
" runs-on: ubuntu-latest",
|
|
11567
|
+
" permissions:",
|
|
11568
|
+
" contents: read",
|
|
11569
|
+
" id-token: write # short-lived identity for the Abloh model gateway",
|
|
11570
|
+
" steps:",
|
|
11571
|
+
" - uses: actions/checkout@v4",
|
|
11572
|
+
" with:",
|
|
11573
|
+
" ref: ${{ github.event.pull_request.head.sha }}",
|
|
11574
|
+
" fetch-depth: 0 # Abloh diffs against the base ref",
|
|
11575
|
+
" persist-credentials: false",
|
|
11576
|
+
...build,
|
|
11577
|
+
` - uses: ${PINNED_ACTION}`,
|
|
11578
|
+
" with:",
|
|
11579
|
+
" base: ${{ github.event.pull_request.base.sha }}",
|
|
11580
|
+
""
|
|
11581
|
+
].join("\n");
|
|
11582
|
+
}
|
|
11583
|
+
function writeWorkflow(repoDir, input) {
|
|
11584
|
+
const path = join21(repoDir, WORKFLOW_RELATIVE_PATH);
|
|
11585
|
+
const legacy = join21(repoDir, ".github", "workflows", "abloh.yml");
|
|
11586
|
+
if (existsSync9(path) || existsSync9(legacy)) return "exists";
|
|
11587
|
+
mkdirSync8(dirname12(path), { recursive: true });
|
|
11588
|
+
writeFileSync7(path, renderWorkflow(input), { encoding: "utf8", mode: 420, flag: "wx" });
|
|
11589
|
+
return "created";
|
|
11590
|
+
}
|
|
11557
11591
|
function writePolicy(policyPath, input) {
|
|
11558
11592
|
if (!existsSync9(policyPath)) {
|
|
11559
11593
|
writeFileSync7(policyPath, renderPolicy(input), { encoding: "utf8", mode: 420, flag: "wx" });
|
|
@@ -11646,9 +11680,19 @@ async function initRepository(options) {
|
|
|
11646
11680
|
else writeFileSync7(policyPath, previous2, { encoding: "utf8", mode: 420 });
|
|
11647
11681
|
throw error;
|
|
11648
11682
|
}
|
|
11683
|
+
const pythonWorkflow = writeWorkflow(repoDir, {
|
|
11684
|
+
subdir: inferredSubdir,
|
|
11685
|
+
runtimeImage: image2.ref,
|
|
11686
|
+
testCommand: null,
|
|
11687
|
+
installCommand: installCommand2,
|
|
11688
|
+
installDirectory: installDirectory2,
|
|
11689
|
+
identityFiles: identities2
|
|
11690
|
+
});
|
|
11649
11691
|
return {
|
|
11650
11692
|
repoDir,
|
|
11651
11693
|
policyPath,
|
|
11694
|
+
workflowPath: join21(repoDir, WORKFLOW_RELATIVE_PATH),
|
|
11695
|
+
workflowState: pythonWorkflow,
|
|
11652
11696
|
subdir: inferredSubdir,
|
|
11653
11697
|
language: "python",
|
|
11654
11698
|
runner: "pytest",
|
|
@@ -11726,9 +11770,12 @@ async function initRepository(options) {
|
|
|
11726
11770
|
else writeFileSync7(policyPath, previous, { encoding: "utf8", mode: 420 });
|
|
11727
11771
|
throw error;
|
|
11728
11772
|
}
|
|
11773
|
+
const workflowState = writeWorkflow(repoDir, policyInput);
|
|
11729
11774
|
return {
|
|
11730
11775
|
repoDir,
|
|
11731
11776
|
policyPath,
|
|
11777
|
+
workflowPath: join21(repoDir, WORKFLOW_RELATIVE_PATH),
|
|
11778
|
+
workflowState,
|
|
11732
11779
|
subdir: target.subdir,
|
|
11733
11780
|
language: "javascript",
|
|
11734
11781
|
runner: target.runner,
|
|
@@ -11754,7 +11801,10 @@ function renderInitResult(result) {
|
|
|
11754
11801
|
`Layer 0 coverage: @vitest/coverage-v8${provider.vitestVersion === null ? "" : `@${provider.vitestVersion}`} is not available \u2014 after the repository's dependency install, run \`abloh prepare\` (or add it as an exact dev dependency); without it Layer 0 reports cannot-attest.`
|
|
11755
11802
|
],
|
|
11756
11803
|
`Proof image: ${result.runtimeImage} (${result.runtimeImageSource})`,
|
|
11757
|
-
"
|
|
11804
|
+
result.workflowState === "created" ? `Created ${result.workflowPath}` : `Left ${result.workflowPath} alone \u2014 a workflow is already there`,
|
|
11805
|
+
/* Both files, named, because "commit abloh.yml" was the whole instruction when the workflow
|
|
11806
|
+
was the customer's to write and is now half of it. */
|
|
11807
|
+
"Next: review and commit both files. Abloh runs on the pull request that adds them."
|
|
11758
11808
|
].join("\n") + "\n";
|
|
11759
11809
|
}
|
|
11760
11810
|
|
|
@@ -11957,7 +12007,7 @@ import {
|
|
|
11957
12007
|
fsyncSync as fsyncSync2,
|
|
11958
12008
|
fstatSync as fstatSync5,
|
|
11959
12009
|
lstatSync as lstatSync13,
|
|
11960
|
-
mkdirSync as
|
|
12010
|
+
mkdirSync as mkdirSync9,
|
|
11961
12011
|
mkdtempSync as mkdtempSync8,
|
|
11962
12012
|
openSync as openSync6,
|
|
11963
12013
|
readFileSync as readFileSync20,
|
|
@@ -12242,7 +12292,7 @@ function prepareAtomicCopy(source, destination, nonce) {
|
|
|
12242
12292
|
if (identityOf(source).kind !== "file") {
|
|
12243
12293
|
throw new Error(`staged artifact must be a regular file: ${source}`);
|
|
12244
12294
|
}
|
|
12245
|
-
|
|
12295
|
+
mkdirSync9(dirname13(destination), { recursive: true });
|
|
12246
12296
|
assertNoSymlinkComponents(dirname13(destination), destination);
|
|
12247
12297
|
if (existsSync11(destination)) {
|
|
12248
12298
|
const info = lstatSync13(destination);
|
|
@@ -12265,7 +12315,7 @@ function prepareAtomicCopy(source, destination, nonce) {
|
|
|
12265
12315
|
return temporary;
|
|
12266
12316
|
}
|
|
12267
12317
|
function copyDirectory(source, destination) {
|
|
12268
|
-
|
|
12318
|
+
mkdirSync9(destination, { mode: 448 });
|
|
12269
12319
|
for (const entry of readdirSync8(source, { withFileTypes: true })) {
|
|
12270
12320
|
const from = join23(source, entry.name);
|
|
12271
12321
|
const to = join23(destination, entry.name);
|
|
@@ -12287,7 +12337,7 @@ function prepareAtomicDirectory(source, destination, nonce) {
|
|
|
12287
12337
|
if (identityOf(source).kind !== "directory") {
|
|
12288
12338
|
throw new Error(`staged artifact must be a directory: ${source}`);
|
|
12289
12339
|
}
|
|
12290
|
-
|
|
12340
|
+
mkdirSync9(dirname13(destination), { recursive: true });
|
|
12291
12341
|
assertNoSymlinkComponents(dirname13(destination), destination);
|
|
12292
12342
|
const temporary = join23(
|
|
12293
12343
|
dirname13(destination),
|
|
@@ -12551,7 +12601,7 @@ function acquirePublicationLock(controlDestination, allowedDestinations) {
|
|
|
12551
12601
|
const acquired = [];
|
|
12552
12602
|
try {
|
|
12553
12603
|
for (const lockPath of paths.locks) {
|
|
12554
|
-
|
|
12604
|
+
mkdirSync9(dirname13(lockPath), { recursive: true });
|
|
12555
12605
|
const fd = openSync6(
|
|
12556
12606
|
lockPath,
|
|
12557
12607
|
constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY | constants3.O_NOFOLLOW,
|
|
@@ -12724,7 +12774,7 @@ async function createArtifactOutputTransaction(input) {
|
|
|
12724
12774
|
controlDestination: destinations.json,
|
|
12725
12775
|
allowedDestinations
|
|
12726
12776
|
});
|
|
12727
|
-
|
|
12777
|
+
mkdirSync9(dirname13(destinations.json), { recursive: true });
|
|
12728
12778
|
assertNoSymlinkComponents(repoDir, destinations.json);
|
|
12729
12779
|
publicationMetadata = acquirePublicationLock(destinations.json, allowedDestinations);
|
|
12730
12780
|
input.publicationTestHooks?.afterCrashPoint?.({ phase: "locks-acquired" });
|
|
@@ -12736,7 +12786,7 @@ async function createArtifactOutputTransaction(input) {
|
|
|
12736
12786
|
if (operations.some((operation) => operation.destination === destination)) {
|
|
12737
12787
|
throw new Error(`staged artifacts collide at ${destination}`);
|
|
12738
12788
|
}
|
|
12739
|
-
|
|
12789
|
+
mkdirSync9(dirname13(destination), { recursive: true });
|
|
12740
12790
|
assertNoSymlinkComponents(repoDir, destination);
|
|
12741
12791
|
const parent = parentIdentity(destination);
|
|
12742
12792
|
const existingIdentity = existsSync11(destination) ? identityOf(destination) : void 0;
|
|
@@ -13602,7 +13652,7 @@ function writeArtifacts(report, opts) {
|
|
|
13602
13652
|
const patchRevertText = `${JSON.stringify(report.patchRevertLocal, null, 2)}
|
|
13603
13653
|
`;
|
|
13604
13654
|
patchRevertDigest = sha256Hex(patchRevertText);
|
|
13605
|
-
|
|
13655
|
+
mkdirSync10(dirname15(patchRevertOut), { recursive: true });
|
|
13606
13656
|
writeFileSync11(patchRevertOut, patchRevertText, { mode: 384 });
|
|
13607
13657
|
}
|
|
13608
13658
|
const rationalesText = JSON.stringify(buildRationalesFile(report.findings), null, 2) + "\n";
|
|
@@ -13610,7 +13660,7 @@ function writeArtifacts(report, opts) {
|
|
|
13610
13660
|
let rawReportDigest = null;
|
|
13611
13661
|
if (report.rawReportText != null) {
|
|
13612
13662
|
rawReportDigest = sha256Hex(report.rawReportText);
|
|
13613
|
-
|
|
13663
|
+
mkdirSync10(dirname15(rawReportOut), { recursive: true });
|
|
13614
13664
|
writeFileSync11(rawReportOut, report.rawReportText);
|
|
13615
13665
|
} else {
|
|
13616
13666
|
rmSync12(rawReportOut, { force: true });
|
|
@@ -13627,7 +13677,7 @@ function writeArtifacts(report, opts) {
|
|
|
13627
13677
|
const redactedText = `${JSON.stringify(redacted, null, 2)}
|
|
13628
13678
|
`;
|
|
13629
13679
|
redactedReportDigest = sha256Hex(redactedText);
|
|
13630
|
-
|
|
13680
|
+
mkdirSync10(dirname15(redactedReportOut), { recursive: true });
|
|
13631
13681
|
writeFileSync11(redactedReportOut, redactedText, { mode: 384 });
|
|
13632
13682
|
} else {
|
|
13633
13683
|
rmSync12(redactedReportOut, { force: true });
|
|
@@ -13638,7 +13688,7 @@ function writeArtifacts(report, opts) {
|
|
|
13638
13688
|
let rawCoverageDigest = null;
|
|
13639
13689
|
if (report.rawCoverageText != null) {
|
|
13640
13690
|
rawCoverageDigest = sha256Hex(report.rawCoverageText);
|
|
13641
|
-
|
|
13691
|
+
mkdirSync10(dirname15(rawCoverageOut), { recursive: true });
|
|
13642
13692
|
writeFileSync11(rawCoverageOut, report.rawCoverageText);
|
|
13643
13693
|
} else {
|
|
13644
13694
|
rmSync12(rawCoverageOut, { force: true });
|
|
@@ -13647,17 +13697,17 @@ function writeArtifacts(report, opts) {
|
|
|
13647
13697
|
if (report.rawCarrierReports && report.rawCarrierReports.length > 0) {
|
|
13648
13698
|
const text = JSON.stringify({ schema: "attest-raw-carrier-reports/v2", reports: report.rawCarrierReports }, null, 2) + "\n";
|
|
13649
13699
|
rawCarrierDigest = sha256Hex(text);
|
|
13650
|
-
|
|
13700
|
+
mkdirSync10(dirname15(rawCarrierOut), { recursive: true });
|
|
13651
13701
|
writeFileSync11(rawCarrierOut, text);
|
|
13652
13702
|
} else {
|
|
13653
13703
|
rmSync12(rawCarrierOut, { force: true });
|
|
13654
13704
|
}
|
|
13655
13705
|
const artifact = buildArtifact(report, rationalesDigest, rawReportDigest, rawCoverageDigest, rawCarrierDigest, patchRevertDigest, redactedReportDigest);
|
|
13656
|
-
|
|
13706
|
+
mkdirSync10(dirname15(rationalesOut), { recursive: true });
|
|
13657
13707
|
writeFileSync11(rationalesOut, rationalesText);
|
|
13658
|
-
|
|
13708
|
+
mkdirSync10(dirname15(jsonOut), { recursive: true });
|
|
13659
13709
|
writeFileSync11(jsonOut, JSON.stringify(artifact, null, 2) + "\n");
|
|
13660
|
-
|
|
13710
|
+
mkdirSync10(dirname15(mdOut), { recursive: true });
|
|
13661
13711
|
writeFileSync11(mdOut, renderMarkdown(report, rawReportDigest, rawCoverageDigest));
|
|
13662
13712
|
log(`staged ${logical.json} and ${logical.md}`);
|
|
13663
13713
|
log(`rationales (local only): ${logical.rationales} \u2014 sha256 ${rationalesDigest.slice(0, 16)}\u2026 recorded in artifact`);
|
|
@@ -15462,7 +15512,7 @@ Replace each link with a tracked regular file, or point it to a tracked regular
|
|
|
15462
15512
|
null,
|
|
15463
15513
|
2
|
|
15464
15514
|
) + "\n";
|
|
15465
|
-
|
|
15515
|
+
mkdirSync10(dirname15(fixProofsOut), { recursive: true });
|
|
15466
15516
|
writeFileSync11(fixProofsOut, fixProofsText);
|
|
15467
15517
|
if (fixLoopBlock.state === "completed") fixLoopBlock = { ...fixLoopBlock, proofsDigest: sha256Hex(fixProofsText) };
|
|
15468
15518
|
log(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloh/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-rc.1",
|
|
4
4
|
"description": "Abloh CLI: the `abloh run` command. The package will publish under the @abloh scope.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"semver": "7.8.5",
|
|
28
28
|
"yaml": "^2.5.0",
|
|
29
|
+
"@abloh/sandbox": "0.1.2",
|
|
29
30
|
"@abloh/core": "0.1.2",
|
|
30
31
|
"@abloh/engine-python": "0.1.2",
|
|
31
|
-
"@abloh/engine-stryker": "0.1.2",
|
|
32
32
|
"@abloh/triage": "0.1.2",
|
|
33
|
-
"@abloh/
|
|
33
|
+
"@abloh/engine-stryker": "0.1.3-rc.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/semver": "7.7.1",
|