cerber-core 1.1.6 → 1.1.8
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/CHANGELOG.md +111 -0
- package/README.md +157 -1
- package/bin/cerber +14 -1
- package/dev/templates/BACKEND_SCHEMA.ts.tpl +87 -50
- package/dev/templates/cerber-guardian.mjs.tpl +255 -148
- package/dev/templates/cerber.yml.tpl +96 -53
- package/dev/templates/pre-commit.tpl +4 -4
- package/dist/cli/contract-parser.d.ts.map +1 -1
- package/dist/cli/contract-parser.js +47 -20
- package/dist/cli/contract-parser.js.map +1 -1
- package/dist/cli/doctor.d.ts +16 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +140 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +98 -8
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/override-validator.d.ts +27 -0
- package/dist/cli/override-validator.d.ts.map +1 -0
- package/dist/cli/override-validator.js +100 -0
- package/dist/cli/override-validator.js.map +1 -0
- package/dist/cli/template-generator.d.ts.map +1 -1
- package/dist/cli/template-generator.js +71 -16
- package/dist/cli/template-generator.js.map +1 -1
- package/dist/cli/types.d.ts +7 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +117 -117
- package/solo/templates/BACKEND_SCHEMA.ts.tpl +87 -50
- package/solo/templates/cerber-guardian.mjs.tpl +255 -148
- package/solo/templates/cerber.yml.tpl +96 -53
- package/solo/templates/pre-commit.tpl +4 -4
- package/team/templates/BACKEND_SCHEMA.ts.tpl +87 -50
- package/team/templates/CODEOWNERS.tpl +18 -6
- package/team/templates/cerber-guardian.mjs.tpl +255 -148
- package/team/templates/cerber.yml.tpl +96 -53
- package/team/templates/pre-commit.tpl +4 -4
|
@@ -1,148 +1,255 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Generated by Cerber init - DO NOT EDIT MANUALLY
|
|
3
|
-
// To regenerate: npx cerber init --force
|
|
4
|
-
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Generated by Cerber init - DO NOT EDIT MANUALLY
|
|
3
|
+
// To regenerate: npx cerber init --force
|
|
4
|
+
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
|
|
9
|
+
const APPROVALS_TAG = '{{APPROVALS_TAG}}';
|
|
10
|
+
|
|
11
|
+
function readYamlValue(text, key) {
|
|
12
|
+
const re = new RegExp(`^\\s*${key}\\s*:\\s*(.*)\\s*$`, "m");
|
|
13
|
+
const m = text.match(re);
|
|
14
|
+
if (!m) return "";
|
|
15
|
+
let v = (m[1] ?? "").trim();
|
|
16
|
+
|
|
17
|
+
// Remove quotes
|
|
18
|
+
v = v.replace(/^["']/,"").replace(/["']$/,"");
|
|
19
|
+
return v.trim();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function parseOverride(cerberContent) {
|
|
23
|
+
const enabledRaw = readYamlValue(cerberContent, "enabled");
|
|
24
|
+
const enabled = enabledRaw.toLowerCase() === "true";
|
|
25
|
+
|
|
26
|
+
const reason = readYamlValue(cerberContent, "reason");
|
|
27
|
+
const expiresRaw = readYamlValue(cerberContent, "expires");
|
|
28
|
+
const approvedBy = readYamlValue(cerberContent, "approvedBy");
|
|
29
|
+
|
|
30
|
+
if (!enabled) return { state: "DISABLED", reason, expires: expiresRaw, approvedBy };
|
|
31
|
+
|
|
32
|
+
if (!expiresRaw) return { state: "ACTIVE", reason, expires: "", approvedBy };
|
|
33
|
+
|
|
34
|
+
const expiresDate = new Date(expiresRaw);
|
|
35
|
+
if (Number.isNaN(expiresDate.getTime())) {
|
|
36
|
+
return { state: "INVALID", reason, expires: expiresRaw, approvedBy };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (expiresDate.getTime() < Date.now()) {
|
|
40
|
+
return { state: "EXPIRED", reason, expires: expiresRaw, approvedBy };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { state: "ACTIVE", reason, expires: expiresRaw, approvedBy };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function main() {
|
|
47
|
+
console.log('🛡️ Cerber Guardian: Validating staged files...');
|
|
48
|
+
|
|
49
|
+
// Check for emergency override
|
|
50
|
+
const cerberMdPath = join(process.cwd(), 'CERBER.md');
|
|
51
|
+
if (fs.existsSync(cerberMdPath)) {
|
|
52
|
+
const cerberContent = fs.readFileSync(cerberMdPath, 'utf-8');
|
|
53
|
+
const overrideMatch = cerberContent.match(/CERBER_OVERRIDE:\s*\n\s*enabled:\s*(true|false)/);
|
|
54
|
+
|
|
55
|
+
if (overrideMatch && overrideMatch[1] === 'true') {
|
|
56
|
+
const override = parseOverride(cerberContent);
|
|
57
|
+
const { state, reason, expires, approvedBy } = override;
|
|
58
|
+
|
|
59
|
+
if (state === 'ACTIVE') {
|
|
60
|
+
// Override ACTIVE - allow commit with warning
|
|
61
|
+
console.log('');
|
|
62
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
63
|
+
console.log('⚠️ CERBER EMERGENCY OVERRIDE ACTIVE');
|
|
64
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(`Status: ACTIVE`);
|
|
67
|
+
console.log(`Reason: ${reason}`);
|
|
68
|
+
console.log(`Expires: ${expires}`);
|
|
69
|
+
console.log(`Approved By: ${approvedBy}`);
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log('Guardian checks: BYPASSED WITH WARNING');
|
|
72
|
+
console.log('Self-protection: STILL ACTIVE (cerber-integrity runs)');
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log('⚠️ Create follow-up PR to fix properly + disable override');
|
|
75
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
76
|
+
console.log('');
|
|
77
|
+
process.exit(0); // Allow commit
|
|
78
|
+
} else if (state === 'EXPIRED') {
|
|
79
|
+
console.log('⚠️ Override expired - proceeding with normal validation');
|
|
80
|
+
} else {
|
|
81
|
+
console.log('⚠️ Override invalid (missing required fields) - proceeding with normal validation');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Load schema from CERBER.md
|
|
87
|
+
if (!fs.existsSync(cerberMdPath)) {
|
|
88
|
+
console.error('❌ CERBER.md not found');
|
|
89
|
+
console.error('Run: npx cerber init');
|
|
90
|
+
process.exit(5);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const cerberContent = fs.readFileSync(cerberMdPath, 'utf-8');
|
|
94
|
+
|
|
95
|
+
// Parse SCHEMA section
|
|
96
|
+
const schemaMatch = cerberContent.match(/SCHEMA:\s*\n\s*mode:\s*(\w+)/);
|
|
97
|
+
if (!schemaMatch) {
|
|
98
|
+
console.error('❌ SCHEMA section not found in CERBER.md');
|
|
99
|
+
console.error('Add SCHEMA section with mode: required or mode: disabled');
|
|
100
|
+
process.exit(5);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const schemaMode = schemaMatch[1];
|
|
104
|
+
if (schemaMode === 'disabled') {
|
|
105
|
+
console.log('⚠️ Schema validation disabled (SCHEMA.mode: disabled)');
|
|
106
|
+
console.log('✅ Bypassing validation');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Extract forbidden patterns
|
|
111
|
+
const forbiddenPatterns = [];
|
|
112
|
+
const patternsMatch = cerberContent.match(/forbiddenPatterns:\s*\n([\s\S]*?)(?=\n\w|\nSCHEMA:|$)/);
|
|
113
|
+
if (patternsMatch) {
|
|
114
|
+
const patternLines = patternsMatch[1].match(/- "([^"]+)"/g);
|
|
115
|
+
if (patternLines) {
|
|
116
|
+
patternLines.forEach(line => {
|
|
117
|
+
const pattern = line.match(/- "([^"]+)"/)?.[1];
|
|
118
|
+
if (pattern) {
|
|
119
|
+
forbiddenPatterns.push({
|
|
120
|
+
pattern: pattern,
|
|
121
|
+
name: `Forbidden: ${pattern}`,
|
|
122
|
+
severity: 'error'
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (schemaMode === 'required' && forbiddenPatterns.length === 0) {
|
|
130
|
+
console.error('❌ SCHEMA.mode: required but no rules defined');
|
|
131
|
+
console.error('Add forbiddenPatterns to SCHEMA section in CERBER.md');
|
|
132
|
+
process.exit(5);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const schema = {
|
|
136
|
+
forbiddenPatterns: forbiddenPatterns,
|
|
137
|
+
rules: []
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Get staged files
|
|
141
|
+
let stagedFiles;
|
|
142
|
+
try {
|
|
143
|
+
stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf-8' })
|
|
144
|
+
.trim()
|
|
145
|
+
.split('\n')
|
|
146
|
+
.filter(Boolean);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error('❌ Failed to get staged files');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (stagedFiles.length === 0) {
|
|
153
|
+
console.log('✅ No files staged for commit');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log(`Checking ${stagedFiles.length} file(s)...`);
|
|
158
|
+
|
|
159
|
+
const violations = [];
|
|
160
|
+
|
|
161
|
+
// Validate each staged file
|
|
162
|
+
for (const file of stagedFiles) {
|
|
163
|
+
if (!fs.existsSync(file)) continue;
|
|
164
|
+
|
|
165
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
166
|
+
|
|
167
|
+
// Check forbidden patterns
|
|
168
|
+
if (schema.forbiddenPatterns && Array.isArray(schema.forbiddenPatterns)) {
|
|
169
|
+
for (const rule of schema.forbiddenPatterns) {
|
|
170
|
+
if (!rule.pattern) continue;
|
|
171
|
+
|
|
172
|
+
const pattern = typeof rule.pattern === 'string'
|
|
173
|
+
? new RegExp(rule.pattern, rule.flags || 'i')
|
|
174
|
+
: rule.pattern;
|
|
175
|
+
|
|
176
|
+
// Check if file is in exceptions
|
|
177
|
+
if (rule.exceptions && rule.exceptions.some(ex => file.includes(ex))) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (pattern.test(content)) {
|
|
182
|
+
// Check for architect approval
|
|
183
|
+
const hasApproval = content.includes(APPROVALS_TAG);
|
|
184
|
+
|
|
185
|
+
if (!hasApproval) {
|
|
186
|
+
violations.push({
|
|
187
|
+
file,
|
|
188
|
+
rule: rule.name || 'Unnamed rule',
|
|
189
|
+
severity: rule.severity || 'error'
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check required imports (rules)
|
|
197
|
+
if (schema.rules && Array.isArray(schema.rules)) {
|
|
198
|
+
for (const rule of schema.rules) {
|
|
199
|
+
if (!rule.pattern || !rule.requiredImports) continue;
|
|
200
|
+
|
|
201
|
+
const filePattern = typeof rule.pattern === 'string' ? new RegExp(rule.pattern) : rule.pattern;
|
|
202
|
+
|
|
203
|
+
if (!filePattern.test(file)) continue;
|
|
204
|
+
|
|
205
|
+
// Check if file is in exceptions
|
|
206
|
+
if (rule.exceptions && rule.exceptions.some(ex => file.includes(ex))) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Check each required import
|
|
211
|
+
for (const requiredImport of rule.requiredImports) {
|
|
212
|
+
const importPattern = new RegExp(`import.*${requiredImport}`, 'i');
|
|
213
|
+
|
|
214
|
+
if (!importPattern.test(content)) {
|
|
215
|
+
// Check for architect approval
|
|
216
|
+
const hasApproval = content.includes(APPROVALS_TAG);
|
|
217
|
+
|
|
218
|
+
if (!hasApproval) {
|
|
219
|
+
violations.push({
|
|
220
|
+
file,
|
|
221
|
+
rule: `${rule.name || 'Unnamed rule'}: missing import '${requiredImport}'`,
|
|
222
|
+
severity: rule.severity || 'error'
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Report violations
|
|
232
|
+
if (violations.length > 0) {
|
|
233
|
+
console.error('\n❌ Architecture violations detected:\n');
|
|
234
|
+
|
|
235
|
+
for (const v of violations) {
|
|
236
|
+
const icon = v.severity === 'error' ? '🔴' : '⚠️';
|
|
237
|
+
console.error(`${icon} [${v.severity.toUpperCase()}] ${v.file}`);
|
|
238
|
+
console.error(` ${v.rule}`);
|
|
239
|
+
console.error(` Add ${APPROVALS_TAG} comment to override\n`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const errorCount = violations.filter(v => v.severity === 'error').length;
|
|
243
|
+
if (errorCount > 0) {
|
|
244
|
+
console.error(`\n❌ Commit blocked: ${errorCount} error(s) found`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
console.log('✅ All checks passed');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
main().catch(err => {
|
|
253
|
+
console.error('❌ Guardian check failed:', err?.message || err);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
});
|
|
@@ -1,53 +1,96 @@
|
|
|
1
|
-
# Generated by Cerber init
|
|
2
|
-
name: Cerber CI
|
|
3
|
-
|
|
4
|
-
on:
|
|
5
|
-
push:
|
|
6
|
-
branches: {{CI_BRANCHES}}
|
|
7
|
-
pull_request:
|
|
8
|
-
branches: {{CI_BRANCHES}}
|
|
9
|
-
workflow_dispatch:
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
cerber-
|
|
13
|
-
name: Cerber
|
|
14
|
-
runs-on: ubuntu-latest
|
|
15
|
-
|
|
16
|
-
steps:
|
|
17
|
-
- name: Checkout code
|
|
18
|
-
uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- name:
|
|
46
|
-
run: |
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
# Generated by Cerber init
|
|
2
|
+
name: Cerber CI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: {{CI_BRANCHES}}
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: {{CI_BRANCHES}}
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
cerber-integrity:
|
|
13
|
+
name: Cerber Self-Protection
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout code
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Verify protected files exist
|
|
21
|
+
run: |
|
|
22
|
+
echo "🛡️ Cerber Integrity Check"
|
|
23
|
+
MISSING=0
|
|
24
|
+
|
|
25
|
+
# Check core files
|
|
26
|
+
[ ! -f "CERBER.md" ] && echo "❌ CERBER.md missing" && MISSING=1
|
|
27
|
+
[ ! -f ".github/workflows/cerber.yml" ] && echo "❌ cerber.yml missing" && MISSING=1
|
|
28
|
+
[ ! -f "scripts/cerber-guardian.mjs" ] && echo "❌ cerber-guardian.mjs missing" && MISSING=1
|
|
29
|
+
[ ! -f ".husky/pre-commit" ] && echo "❌ pre-commit hook missing" && MISSING=1
|
|
30
|
+
|
|
31
|
+
# Check schema file (strict mode only)
|
|
32
|
+
SCHEMA_MODE=$(grep -A 10 "^schema:" CERBER.md | grep "mode:" | awk '{print $2}' | head -1)
|
|
33
|
+
if [ "$SCHEMA_MODE" = "strict" ]; then
|
|
34
|
+
SCHEMA_FILE=$(grep -A 10 "^schema:" CERBER.md | grep "file:" | awk '{print $2}' | head -1)
|
|
35
|
+
[ ! -f "$SCHEMA_FILE" ] && echo "❌ Schema file $SCHEMA_FILE missing (strict mode)" && MISSING=1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if [ $MISSING -eq 1 ]; then
|
|
39
|
+
echo "🚨 Protected files missing. Cerber self-protection compromised."
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo "✅ All protected files present"
|
|
44
|
+
|
|
45
|
+
- name: Verify cerber-ci job exists
|
|
46
|
+
run: |
|
|
47
|
+
if ! grep -q "cerber-ci:" .github/workflows/cerber.yml; then
|
|
48
|
+
echo "🚨 Job 'cerber-ci' not found in cerber.yml"
|
|
49
|
+
echo "Never rename or remove the cerber-ci job ID"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
echo "✅ cerber-ci job ID intact"
|
|
53
|
+
|
|
54
|
+
cerber-ci:
|
|
55
|
+
name: Cerber CI
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
needs: [cerber-integrity]
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- name: Checkout code
|
|
61
|
+
uses: actions/checkout@v4
|
|
62
|
+
|
|
63
|
+
- name: Setup Node.js
|
|
64
|
+
uses: actions/setup-node@v4
|
|
65
|
+
with:
|
|
66
|
+
node-version: '20'
|
|
67
|
+
cache: 'npm'
|
|
68
|
+
|
|
69
|
+
- name: Install dependencies
|
|
70
|
+
run: npm ci
|
|
71
|
+
|
|
72
|
+
- name: Build (if script exists)
|
|
73
|
+
run: |
|
|
74
|
+
if npm run | grep -q "build"; then
|
|
75
|
+
npm run build
|
|
76
|
+
else
|
|
77
|
+
echo "No build script defined; skipping"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
- name: Test (if script exists)
|
|
81
|
+
run: |
|
|
82
|
+
if npm run | grep -q "test"; then
|
|
83
|
+
npm test
|
|
84
|
+
else
|
|
85
|
+
echo "No test script defined; skipping"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
- name: Run Guardian
|
|
89
|
+
run: |
|
|
90
|
+
if npm run | grep -q "cerber:guardian"; then
|
|
91
|
+
npm run cerber:guardian
|
|
92
|
+
else
|
|
93
|
+
node scripts/cerber-guardian.mjs
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
{{POST_DEPLOY_BLOCK}}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
# Generated by Cerber init
|
|
3
|
-
|
|
4
|
-
npm run cerber:guardian
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Generated by Cerber init
|
|
3
|
+
|
|
4
|
+
npm run cerber:guardian
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-parser.d.ts","sourceRoot":"","sources":["../../src/cli/contract-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMjE,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAU3F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"contract-parser.d.ts","sourceRoot":"","sources":["../../src/cli/contract-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMjE,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAU3F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CA4HpE;AA+HD,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAM,GAAG,KAAK,GAAG,MAAc,GAAG,cAAc,CAqCxF"}
|