coderifts 1.8.4 → 2.0.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.md +42 -0
- package/bin/coderifts.js +44 -1
- package/dist/cli.js +4292 -48
- package/package.json +6 -3
- package/scripts/assert-publish-gate.sh +42 -0
package/README.md
CHANGED
|
@@ -64,6 +64,48 @@ Interactive configuration generator. Creates a `.coderifts.yml` file with indust
|
|
|
64
64
|
|
|
65
65
|
Save your CodeRifts API key for cloud features. Get a free key at [app.coderifts.com/api/signup](https://app.coderifts.com/api/signup).
|
|
66
66
|
|
|
67
|
+
### `coderifts publish-gate`
|
|
68
|
+
|
|
69
|
+
Gate **npm publish** on the same contract-preflight family as the pre-push hook:
|
|
70
|
+
`before` = last published / merge-base baseline, `after` = working tree. Exit **0**
|
|
71
|
+
only when `execution_action` permits publish; **BLOCK**, resolver errors, empty
|
|
72
|
+
before, and preflight unreachability all exit **1** (fail-closed). Empty `before`
|
|
73
|
+
is **never** treated as a silent NEW_ARTIFACT pass.
|
|
74
|
+
|
|
75
|
+
| Flag | Description | Default |
|
|
76
|
+
|------|-------------|---------|
|
|
77
|
+
| `--spec <path>` | Contract artifact path | `git config coderifts.specPath` or `api/openapi.yaml` |
|
|
78
|
+
| `--json` | Machine-readable result | `false` |
|
|
79
|
+
|
|
80
|
+
**Recommended package.json wiring:**
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"scripts": {
|
|
85
|
+
"prepublishOnly": "coderifts publish-gate"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Before resolution order (fail-closed):**
|
|
91
|
+
1. Git tag of `package.json` version (`vX.Y.Z`, then `X.Y.Z`)
|
|
92
|
+
2. `git merge-base HEAD origin/main` (fallbacks: `origin/master`, `main`, `master`)
|
|
93
|
+
3. Exit 1 with a clear error — never invent an empty baseline
|
|
94
|
+
|
|
95
|
+
On success the command prints a **receipt reference** when the preflight path issues one.
|
|
96
|
+
|
|
97
|
+
### Git hook (`coderifts hook install`)
|
|
98
|
+
|
|
99
|
+
Installs a **pre-push** hook that diffs the configured OpenAPI path against a
|
|
100
|
+
resolved baseline (remote tip, or for new branches a merge-base with the
|
|
101
|
+
default branch). Empty-before allow is not used. The hook prefers closed-set
|
|
102
|
+
`execution_action` from the diff API (legacy `omega_decision` only when action
|
|
103
|
+
is absent). Configure with `git config coderifts.apiKey` and optional
|
|
104
|
+
`git config coderifts.specPath`.
|
|
105
|
+
|
|
106
|
+
After upgrading the `coderifts` CLI, re-run `coderifts hook install` so the
|
|
107
|
+
installed hook matches the package (already-installed hooks are not
|
|
108
|
+
auto-updated).
|
|
67
109
|
## CI/CD Integration
|
|
68
110
|
|
|
69
111
|
### GitHub Actions
|
package/bin/coderifts.js
CHANGED
|
@@ -25,6 +25,40 @@ program
|
|
|
25
25
|
await diff(oldSpec, newSpec, options);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
// ── deploy-gate command (deploy-gate #8, phase-1 ADVISORY) ──
|
|
29
|
+
// Gates a deploy on the current { environment, artifact } via a preflight receipt. Phase 1 is
|
|
30
|
+
// advisory: it reports but exits 0 even on deny unless the step is marked --enforce /
|
|
31
|
+
// CODERIFTS_DEPLOY_ENFORCE=true. Composes the validated pure deployGate (@coderifts/agent-guard).
|
|
32
|
+
program
|
|
33
|
+
.command('deploy-gate')
|
|
34
|
+
.description('Gate a deploy on the current { environment, artifact } using a preflight receipt (phase-1 advisory)')
|
|
35
|
+
.option('--env <environment>', 'Target environment (e.g. production, staging)')
|
|
36
|
+
.option('--artifact <artifact_id>', 'Immutable artifact identity being deployed (content digest or commit SHA)')
|
|
37
|
+
.option('--receipt <file>', 'Path to the deploy-scoped receipt JSON produced by preflight')
|
|
38
|
+
.option('--json', 'Output the binding result as JSON')
|
|
39
|
+
.option('--enforce', 'Treat the step as enforcing: attest ENFORCING and exit non-zero on a gate failure')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const { runDeployGate } = require('../src/commands/deploy-gate');
|
|
42
|
+
await runDeployGate(options);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ── publish-gate — npm prepublishOnly (same decision family as pre-push, fail-closed before) ──
|
|
46
|
+
// Exit status is set only at this command boundary (library never process.exit).
|
|
47
|
+
// program.parse() does not await async actions; process.exit here makes the gate's
|
|
48
|
+
// fail-closed status authoritative for npm prepublishOnly / child_process callers.
|
|
49
|
+
program
|
|
50
|
+
.command('publish-gate')
|
|
51
|
+
.description('Gate npm publish on contract-artifact preflight (before=git baseline, after=working tree)')
|
|
52
|
+
.option('--spec <path>', 'Contract artifact path (default: git config coderifts.specPath or api/openapi.yaml)')
|
|
53
|
+
.option('--json', 'Machine-readable JSON result')
|
|
54
|
+
.action(async (options) => {
|
|
55
|
+
const { runPublishGate } = require('../src/commands/publish-gate');
|
|
56
|
+
const result = await runPublishGate(options);
|
|
57
|
+
const code = result && typeof result.exitCode === 'number' ? result.exitCode : 1;
|
|
58
|
+
process.exitCode = code;
|
|
59
|
+
process.exit(code);
|
|
60
|
+
});
|
|
61
|
+
|
|
28
62
|
// ── init command ──
|
|
29
63
|
program
|
|
30
64
|
.command('init [template]')
|
|
@@ -90,4 +124,13 @@ corpusCmd
|
|
|
90
124
|
corpusVerify(options);
|
|
91
125
|
});
|
|
92
126
|
|
|
93
|
-
|
|
127
|
+
// parseAsync: required so async command actions (publish-gate, diff, deploy-gate, …)
|
|
128
|
+
// complete before the process ends. program.parse() discards the action promise and
|
|
129
|
+
// can leave process.exitCode at the default 0 even after a fail-closed gate printed errors.
|
|
130
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
131
|
+
console.error(err);
|
|
132
|
+
process.exitCode = typeof process.exitCode === 'number' && process.exitCode !== 0
|
|
133
|
+
? process.exitCode
|
|
134
|
+
: 1;
|
|
135
|
+
process.exit(process.exitCode);
|
|
136
|
+
});
|