shipproof 0.1.0 → 0.2.0
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/README.es.md +31 -1
- package/README.md +26 -1
- package/dist/src/action.d.ts +2 -0
- package/dist/src/action.d.ts.map +1 -0
- package/dist/src/action.js +55 -0
- package/dist/src/action.js.map +1 -0
- package/dist/src/analyze.d.ts +1 -1
- package/dist/src/analyze.js +1 -1
- package/dist/src/reporters/github.d.ts +3 -0
- package/dist/src/reporters/github.d.ts.map +1 -0
- package/dist/src/reporters/github.js +35 -0
- package/dist/src/reporters/github.js.map +1 -0
- package/package.json +2 -2
package/README.es.md
CHANGED
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
Comprobaciones sin configuración para saber si un proyecto creado con ayuda de IA está listo para publicarse.
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml/badge.svg"></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/shipproof"><img alt="versión en npm" src="https://img.shields.io/npm/v/shipproof?logo=npm&color=cb3837"></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/shipproof"><img alt="descargas en npm" src="https://img.shields.io/npm/dm/shipproof?logo=npm"></a>
|
|
13
|
+
<a href="LICENSE"><img alt="Licencia MIT" src="https://img.shields.io/badge/license-MIT-22c55e"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
9
16
|
<p align="center">
|
|
10
17
|
<a href="README.md">English</a> · Español
|
|
11
18
|
</p>
|
|
@@ -62,6 +69,29 @@ npx shipproof --no-fail
|
|
|
62
69
|
|
|
63
70
|
Por defecto, ShipProof termina con código `1` si encuentra al menos un problema bloqueante y con código `2` cuando la entrada no es válida. Los avisos reducen la puntuación, pero no cambian el código de salida.
|
|
64
71
|
|
|
72
|
+
## GitHub Action
|
|
73
|
+
|
|
74
|
+
Añade ShipProof a tus pull requests sin instalar ni configurar nada en el repositorio:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
name: ShipProof
|
|
78
|
+
|
|
79
|
+
on: pull_request
|
|
80
|
+
|
|
81
|
+
permissions:
|
|
82
|
+
contents: read
|
|
83
|
+
|
|
84
|
+
jobs:
|
|
85
|
+
readiness:
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@v7
|
|
89
|
+
- uses: CalvaryBloom/shipproof@v0.2.0
|
|
90
|
+
id: shipproof
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
La acción añade al resumen del workflow la puntuación y los hallazgos que requieren atención. Por defecto falla si encuentra un problema bloqueante; usa `fail-on-issues: false` para obtener solo un informe. Los pasos posteriores pueden consultar los outputs `score`, `readiness`, `warnings` y `failed`.
|
|
94
|
+
|
|
65
95
|
## Puntuación
|
|
66
96
|
|
|
67
97
|
Cada comprobación aplicable tiene un peso explícito. Un resultado correcto obtiene todo el peso, un aviso obtiene la mitad y un fallo no obtiene puntos.
|
|
@@ -89,10 +119,10 @@ ShipProof no tiene dependencias en tiempo de ejecución. TypeScript y las declar
|
|
|
89
119
|
|
|
90
120
|
## Próximos objetivos
|
|
91
121
|
|
|
92
|
-
- Acción de GitHub con un resumen compacto para cada pull request.
|
|
93
122
|
- Umbrales configurables mediante `shipproof.config.json`.
|
|
94
123
|
- Comprobaciones más profundas para Python, Rust y Go.
|
|
95
124
|
- Salida SARIF compatible con el análisis de código de GitHub.
|
|
125
|
+
- Comentarios opcionales en pull requests con la evolución de la puntuación.
|
|
96
126
|
- Catálogo público de comprobaciones y falsos positivos conocidos.
|
|
97
127
|
- Publicación automatizada y con procedencia verificable para las próximas versiones.
|
|
98
128
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml/badge.svg"></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/shipproof"><img alt="npm version" src="https://img.shields.io/npm/v/shipproof?logo=npm&color=cb3837"></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/shipproof"><img alt="npm downloads" src="https://img.shields.io/npm/dm/shipproof?logo=npm"></a>
|
|
11
13
|
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-22c55e"></a>
|
|
12
14
|
<img alt="Node 22.13+" src="https://img.shields.io/badge/node-%3E%3D22.13-339933">
|
|
13
15
|
</p>
|
|
@@ -81,6 +83,29 @@ shipproof [path] [options]
|
|
|
81
83
|
|
|
82
84
|
By default, ShipProof exits with code `1` when at least one blocking issue is found and `2` for invalid input. This makes it useful in continuous integration. Warnings lower the score but do not change the exit code.
|
|
83
85
|
|
|
86
|
+
## GitHub Action
|
|
87
|
+
|
|
88
|
+
Add ShipProof to pull requests without installing or configuring anything in the repository:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
name: ShipProof
|
|
92
|
+
|
|
93
|
+
on: pull_request
|
|
94
|
+
|
|
95
|
+
permissions:
|
|
96
|
+
contents: read
|
|
97
|
+
|
|
98
|
+
jobs:
|
|
99
|
+
readiness:
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v7
|
|
103
|
+
- uses: CalvaryBloom/shipproof@v0.2.0
|
|
104
|
+
id: shipproof
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The action writes a compact score and its actionable findings to the workflow summary. It fails the job when a blocking issue is found; set `fail-on-issues: false` to use it as an advisory check. The outputs `score`, `readiness`, `warnings`, and `failed` are available to later steps.
|
|
108
|
+
|
|
84
109
|
## Scoring
|
|
85
110
|
|
|
86
111
|
Each applicable check has an explicit weight. Passing earns the full weight, a warning earns half, and a failure earns none.
|
|
@@ -108,10 +133,10 @@ ShipProof has no runtime dependencies. TypeScript and its Node.js declarations a
|
|
|
108
133
|
|
|
109
134
|
## Roadmap
|
|
110
135
|
|
|
111
|
-
- GitHub Action with a compact pull-request summary.
|
|
112
136
|
- Configurable thresholds through `shipproof.config.json`.
|
|
113
137
|
- Deeper Python, Rust, and Go checks.
|
|
114
138
|
- SARIF output for GitHub code scanning.
|
|
139
|
+
- Optional pull-request comments with score changes.
|
|
115
140
|
- A public check catalog with evidence and false-positive guidance.
|
|
116
141
|
- Automated trusted publishing with provenance for future releases.
|
|
117
142
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/action.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { appendFileSync, statSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { analyzeProject } from "./analyze.js";
|
|
4
|
+
import { renderGitHubSummary } from "./reporters/github.js";
|
|
5
|
+
import { renderTerminal } from "./reporters/terminal.js";
|
|
6
|
+
function input(name, fallback) {
|
|
7
|
+
const value = process.env[`INPUT_${name.toUpperCase()}`]?.trim();
|
|
8
|
+
return value ? value : fallback;
|
|
9
|
+
}
|
|
10
|
+
function booleanInput(name, fallback) {
|
|
11
|
+
const value = input(name, String(fallback)).toLowerCase();
|
|
12
|
+
if (value !== "true" && value !== "false") {
|
|
13
|
+
throw new Error(`Input '${name}' must be either 'true' or 'false'.`);
|
|
14
|
+
}
|
|
15
|
+
return value === "true";
|
|
16
|
+
}
|
|
17
|
+
function appendEnvironmentFile(path, values) {
|
|
18
|
+
if (!path)
|
|
19
|
+
return;
|
|
20
|
+
const content = Object.entries(values)
|
|
21
|
+
.map(([name, value]) => `${name}=${value}`)
|
|
22
|
+
.join("\n");
|
|
23
|
+
appendFileSync(path, `${content}\n`, "utf8");
|
|
24
|
+
}
|
|
25
|
+
function main() {
|
|
26
|
+
const workspace = process.env.GITHUB_WORKSPACE ?? process.cwd();
|
|
27
|
+
const targetInput = input("PATH", ".");
|
|
28
|
+
const failOnIssues = booleanInput("FAIL-ON-ISSUES", true);
|
|
29
|
+
const target = resolve(workspace, targetInput);
|
|
30
|
+
if (!statSync(target).isDirectory()) {
|
|
31
|
+
throw new Error(`Cannot analyze '${targetInput}': the target is not a directory.`);
|
|
32
|
+
}
|
|
33
|
+
const result = analyzeProject(target);
|
|
34
|
+
process.stdout.write(renderTerminal(result, false));
|
|
35
|
+
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
|
|
36
|
+
if (summaryPath)
|
|
37
|
+
appendFileSync(summaryPath, `${renderGitHubSummary(result)}\n`, "utf8");
|
|
38
|
+
appendEnvironmentFile(process.env.GITHUB_OUTPUT, {
|
|
39
|
+
score: result.score,
|
|
40
|
+
readiness: result.readiness,
|
|
41
|
+
warnings: result.summary.warnings,
|
|
42
|
+
failed: result.summary.failed,
|
|
43
|
+
});
|
|
44
|
+
if (failOnIssues && result.summary.failed > 0)
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
main();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const message = error instanceof Error ? error.message : "Unexpected action failure.";
|
|
52
|
+
process.stderr.write(`ShipProof action: ${message}\n`);
|
|
53
|
+
process.exitCode = 2;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../../src/action.ts"],"names":[],"mappings":"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"}
|
package/dist/src/analyze.d.ts
CHANGED
package/dist/src/analyze.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../../src/reporters/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA0B,MAAM,aAAa,CAAC;AAoB1E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAuBlE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const statusLabels = {
|
|
2
|
+
pass: "Pass",
|
|
3
|
+
warn: "Warning",
|
|
4
|
+
fail: "Failed",
|
|
5
|
+
info: "Info",
|
|
6
|
+
};
|
|
7
|
+
const readinessLabels = {
|
|
8
|
+
ready: "Ready to ship",
|
|
9
|
+
close: "Almost ready",
|
|
10
|
+
"work-needed": "Needs work",
|
|
11
|
+
"not-ready": "Not ready",
|
|
12
|
+
};
|
|
13
|
+
function markdownCell(value) {
|
|
14
|
+
return value.replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r?\n/g, " ");
|
|
15
|
+
}
|
|
16
|
+
export function renderGitHubSummary(result) {
|
|
17
|
+
const findings = result.checks.filter((check) => check.status === "warn" || check.status === "fail");
|
|
18
|
+
const lines = [
|
|
19
|
+
`## ShipProof: ${result.score}/100`,
|
|
20
|
+
"",
|
|
21
|
+
`**${readinessLabels[result.readiness]}** · ${result.summary.passed} passed · ${result.summary.warnings} warnings · ${result.summary.failed} failed`,
|
|
22
|
+
"",
|
|
23
|
+
];
|
|
24
|
+
if (findings.length === 0) {
|
|
25
|
+
lines.push("No blocking issues or warnings were found.");
|
|
26
|
+
return lines.join("\n");
|
|
27
|
+
}
|
|
28
|
+
lines.push("| Status | Check | Finding |", "| --- | --- | --- |");
|
|
29
|
+
for (const check of findings) {
|
|
30
|
+
const finding = check.suggestion ? `${check.message} Suggested fix: ${check.suggestion}` : check.message;
|
|
31
|
+
lines.push(`| ${statusLabels[check.status]} | ${markdownCell(check.title)} | ${markdownCell(finding)} |`);
|
|
32
|
+
}
|
|
33
|
+
return lines.join("\n");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/reporters/github.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAgC;IAChD,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,eAAe,GAA8B;IACjD,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,cAAc;IACrB,aAAa,EAAE,YAAY;IAC3B,WAAW,EAAE,WAAW;CACzB,CAAC;AAEF,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACrG,MAAM,KAAK,GAAG;QACZ,iBAAiB,MAAM,CAAC,KAAK,MAAM;QACnC,EAAE;QACF,KAAK,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,MAAM,CAAC,OAAO,CAAC,MAAM,aAAa,MAAM,CAAC,OAAO,CAAC,QAAQ,eAAe,MAAM,CAAC,OAAO,CAAC,MAAM,SAAS;QACpJ,EAAE;KACH,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,8BAA8B,EAAE,qBAAqB,CAAC,CAAC;IAClE,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,mBAAmB,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QACzG,KAAK,CAAC,IAAI,CACR,KAAK,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAC9F,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipproof",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Zero-config release readiness checks for AI-assisted projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"build": "tsc -p tsconfig.json",
|
|
46
46
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
47
47
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
48
|
-
"test": "pnpm build && node --test dist/test/analyze.test.js",
|
|
48
|
+
"test": "pnpm build && node --test dist/test/analyze.test.js dist/test/github-action.test.js",
|
|
49
49
|
"start": "node dist/src/cli.js"
|
|
50
50
|
}
|
|
51
51
|
}
|