pumuki-ast-hooks 5.5.53 → 5.5.54
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 +0 -9
- package/docs/MCP_SERVERS.md +16 -2
- package/docs/RELEASE_NOTES.md +34 -0
- package/package.json +1 -1
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +40 -0
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +9 -205
- package/scripts/hooks-system/application/services/installation/mcp/McpGlobalConfigCleaner.js +49 -0
- package/scripts/hooks-system/application/services/installation/mcp/McpProjectConfigWriter.js +59 -0
- package/scripts/hooks-system/application/services/installation/mcp/McpServerConfigBuilder.js +103 -0
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +13 -8
- package/scripts/hooks-system/infrastructure/ast/common/ast-common.js +15 -8
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDChecks.js +385 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDRules.js +38 -408
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMChecks.js +408 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMRules.js +36 -442
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenExtractor.js +146 -0
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenParser.js +22 -190
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenRunner.js +62 -0
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +27 -9
|
@@ -9,9 +9,23 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
const { pushFinding } = require('../../ast-core');
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const {
|
|
13
|
+
checkFastfileExists,
|
|
14
|
+
checkGitHubActionsWorkflow,
|
|
15
|
+
checkTestFlightConfiguration,
|
|
16
|
+
checkBuildConfiguration,
|
|
17
|
+
checkCertificateManagement,
|
|
18
|
+
checkCodeSigningConfiguration,
|
|
19
|
+
checkAutomatedTesting,
|
|
20
|
+
checkVersionBumping,
|
|
21
|
+
checkReleaseNotes,
|
|
22
|
+
checkSlackNotifications,
|
|
23
|
+
checkMatchConfiguration,
|
|
24
|
+
checkGymConfiguration,
|
|
25
|
+
checkScanConfiguration,
|
|
26
|
+
checkPilotConfiguration,
|
|
27
|
+
checkAppStoreMetadata,
|
|
28
|
+
} = require('./iOSCICDChecks');
|
|
15
29
|
|
|
16
30
|
class iOSCICDRules {
|
|
17
31
|
constructor(findings, projectRoot) {
|
|
@@ -20,411 +34,27 @@ class iOSCICDRules {
|
|
|
20
34
|
}
|
|
21
35
|
|
|
22
36
|
analyze() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
pushFinding(this.findings, {
|
|
45
|
-
ruleId: 'ios.cicd.missing_fastfile',
|
|
46
|
-
severity: 'medium',
|
|
47
|
-
message: 'Proyecto iOS sin Fastfile. Fastlane automatiza builds, tests y deployments.',
|
|
48
|
-
filePath: 'PROJECT_ROOT',
|
|
49
|
-
line: 1,
|
|
50
|
-
suggestion: `Inicializar Fastlane:
|
|
51
|
-
|
|
52
|
-
fastlane init
|
|
53
|
-
|
|
54
|
-
Esto crea:
|
|
55
|
-
- fastlane/Fastfile
|
|
56
|
-
- fastlane/Appfile
|
|
57
|
-
- fastlane/Matchfile`
|
|
58
|
-
});
|
|
59
|
-
} else {
|
|
60
|
-
this.checkFastfileLanes(fastfilePath);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
checkFastfileLanes(fastfilePath) {
|
|
65
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
66
|
-
|
|
67
|
-
const requiredLanes = ['test', 'beta', 'release'];
|
|
68
|
-
const existingLanes = content.match(/lane\s+:(\w+)/g)?.map(l => l.match(/:(\w+)/)?.[1]) || [];
|
|
69
|
-
|
|
70
|
-
const missingLanes = requiredLanes.filter(lane => !existingLanes.includes(lane));
|
|
71
|
-
|
|
72
|
-
if (missingLanes.length > 0) {
|
|
73
|
-
pushFinding(this.findings, {
|
|
74
|
-
ruleId: 'ios.cicd.fastfile_missing_lanes',
|
|
75
|
-
severity: 'medium',
|
|
76
|
-
message: `Fastfile sin lanes esenciales: ${missingLanes.join(', ')}`,
|
|
77
|
-
filePath: fastfilePath,
|
|
78
|
-
line: 1,
|
|
79
|
-
suggestion: `Añadir lanes:
|
|
80
|
-
|
|
81
|
-
lane :test do
|
|
82
|
-
scan
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
lane :beta do
|
|
86
|
-
build_app
|
|
87
|
-
upload_to_testflight
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
lane :release do
|
|
91
|
-
build_app
|
|
92
|
-
upload_to_app_store
|
|
93
|
-
end`
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (!content.includes('increment_build_number') && !content.includes('increment_version_number')) {
|
|
98
|
-
pushFinding(this.findings, {
|
|
99
|
-
ruleId: 'ios.cicd.missing_version_increment',
|
|
100
|
-
severity: 'medium',
|
|
101
|
-
message: 'Fastfile sin incremento automático de versión/build.',
|
|
102
|
-
filePath: fastfilePath,
|
|
103
|
-
line: 1
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
checkGitHubActionsWorkflow() {
|
|
109
|
-
const workflowPath = path.join(this.projectRoot, '.github/workflows');
|
|
110
|
-
|
|
111
|
-
if (!fs.existsSync(workflowPath)) {
|
|
112
|
-
pushFinding(this.findings, {
|
|
113
|
-
ruleId: 'ios.cicd.missing_github_actions',
|
|
114
|
-
severity: 'low',
|
|
115
|
-
message: 'Proyecto sin GitHub Actions workflows. Automatizar CI/CD.',
|
|
116
|
-
filePath: 'PROJECT_ROOT',
|
|
117
|
-
line: 1,
|
|
118
|
-
suggestion: 'Crear .github/workflows/ios-ci.yml para tests automáticos'
|
|
119
|
-
});
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const workflows = glob.sync('*.yml', { cwd: workflowPath, absolute: true });
|
|
124
|
-
const iosWorkflows = workflows.filter(w => {
|
|
125
|
-
const content = fs.readFileSync(w, 'utf-8');
|
|
126
|
-
return content.includes('macos') || content.includes('ios') || content.includes('xcodebuild');
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
if (iosWorkflows.length === 0) {
|
|
130
|
-
pushFinding(this.findings, {
|
|
131
|
-
ruleId: 'ios.cicd.no_ios_workflow',
|
|
132
|
-
severity: 'medium',
|
|
133
|
-
message: 'GitHub Actions sin workflow de iOS.',
|
|
134
|
-
filePath: '.github/workflows/',
|
|
135
|
-
line: 1
|
|
136
|
-
});
|
|
137
|
-
} else {
|
|
138
|
-
iosWorkflows.forEach(workflow => {
|
|
139
|
-
const content = fs.readFileSync(workflow, 'utf-8');
|
|
140
|
-
|
|
141
|
-
if (!content.includes('xcodebuild test')) {
|
|
142
|
-
pushFinding(this.findings, {
|
|
143
|
-
ruleId: 'ios.cicd.workflow_missing_tests',
|
|
144
|
-
severity: 'high',
|
|
145
|
-
message: 'Workflow de iOS sin tests automáticos.',
|
|
146
|
-
filePath: workflow,
|
|
147
|
-
line: 1
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (!content.includes('fastlane')) {
|
|
152
|
-
pushFinding(this.findings, {
|
|
153
|
-
ruleId: 'ios.cicd.workflow_without_fastlane',
|
|
154
|
-
severity: 'low',
|
|
155
|
-
message: 'Workflow sin Fastlane. Considerar para simplificar pipeline.',
|
|
156
|
-
filePath: workflow,
|
|
157
|
-
line: 1
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
checkTestFlightConfiguration() {
|
|
165
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
166
|
-
|
|
167
|
-
if (fs.existsSync(fastfilePath)) {
|
|
168
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
169
|
-
|
|
170
|
-
if (content.includes('beta') && !content.includes('upload_to_testflight')) {
|
|
171
|
-
pushFinding(this.findings, {
|
|
172
|
-
ruleId: 'ios.cicd.beta_without_testflight',
|
|
173
|
-
severity: 'medium',
|
|
174
|
-
message: 'Lane beta sin upload_to_testflight. Automatizar distribución.',
|
|
175
|
-
filePath: fastfilePath,
|
|
176
|
-
line: 1
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (content.includes('upload_to_testflight') && !content.includes('changelog')) {
|
|
181
|
-
pushFinding(this.findings, {
|
|
182
|
-
ruleId: 'ios.cicd.testflight_without_changelog',
|
|
183
|
-
severity: 'low',
|
|
184
|
-
message: 'TestFlight sin changelog. Añadir notas de release.',
|
|
185
|
-
filePath: fastfilePath,
|
|
186
|
-
line: 1
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
checkBuildConfiguration() {
|
|
193
|
-
const projectFiles = glob.sync('**/*.xcodeproj/project.pbxproj', {
|
|
194
|
-
cwd: this.projectRoot,
|
|
195
|
-
absolute: true
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
if (projectFiles.length === 0) return;
|
|
199
|
-
|
|
200
|
-
projectFiles.forEach(projectFile => {
|
|
201
|
-
const content = fs.readFileSync(projectFile, 'utf-8');
|
|
202
|
-
|
|
203
|
-
const configurations = content.match(/buildConfiguration\s*=\s*(\w+)/g) || [];
|
|
204
|
-
const hasDebug = configurations.some(c => c.includes('Debug'));
|
|
205
|
-
const hasRelease = configurations.some(c => c.includes('Release'));
|
|
206
|
-
const hasStaging = configurations.some(c => c.includes('Staging'));
|
|
207
|
-
|
|
208
|
-
if (!hasStaging && (hasDebug && hasRelease)) {
|
|
209
|
-
pushFinding(this.findings, {
|
|
210
|
-
ruleId: 'ios.cicd.missing_staging_config',
|
|
211
|
-
severity: 'low',
|
|
212
|
-
message: 'Sin configuración Staging. Útil para testing pre-production.',
|
|
213
|
-
filePath: projectFile,
|
|
214
|
-
line: 1
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
checkCertificateManagement() {
|
|
221
|
-
const matchfilePath = path.join(this.projectRoot, 'fastlane/Matchfile');
|
|
222
|
-
|
|
223
|
-
if (!fs.existsSync(matchfilePath)) {
|
|
224
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
225
|
-
if (fs.existsSync(fastfilePath)) {
|
|
226
|
-
pushFinding(this.findings, {
|
|
227
|
-
ruleId: 'ios.cicd.missing_match_config',
|
|
228
|
-
severity: 'medium',
|
|
229
|
-
message: 'Fastlane sin Match para gestión de certificados.',
|
|
230
|
-
filePath: 'fastlane/',
|
|
231
|
-
line: 1,
|
|
232
|
-
suggestion: 'fastlane match init para gestionar certificados en equipo'
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
checkCodeSigningConfiguration() {
|
|
239
|
-
const projectFiles = glob.sync('**/*.xcodeproj/project.pbxproj', {
|
|
240
|
-
cwd: this.projectRoot,
|
|
241
|
-
absolute: true
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
projectFiles.forEach(projectFile => {
|
|
245
|
-
const content = fs.readFileSync(projectFile, 'utf-8');
|
|
246
|
-
|
|
247
|
-
if (content.includes('CODE_SIGN_STYLE = Manual')) {
|
|
248
|
-
pushFinding(this.findings, {
|
|
249
|
-
ruleId: 'ios.cicd.manual_code_signing',
|
|
250
|
-
severity: 'low',
|
|
251
|
-
message: 'Code signing manual. Considerar Automatic o Match para CI/CD.',
|
|
252
|
-
filePath: projectFile,
|
|
253
|
-
line: 1
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
checkAutomatedTesting() {
|
|
260
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
261
|
-
|
|
262
|
-
if (fs.existsSync(fastfilePath)) {
|
|
263
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
264
|
-
|
|
265
|
-
if (!content.includes('scan') && !content.includes('run_tests')) {
|
|
266
|
-
pushFinding(this.findings, {
|
|
267
|
-
ruleId: 'ios.cicd.no_automated_tests',
|
|
268
|
-
severity: 'high',
|
|
269
|
-
message: 'Fastlane sin tests automatizados. Añadir scan action.',
|
|
270
|
-
filePath: fastfilePath,
|
|
271
|
-
line: 1,
|
|
272
|
-
suggestion: `lane :test do
|
|
273
|
-
scan(scheme: "MyApp")
|
|
274
|
-
end`
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
checkVersionBumping() {
|
|
281
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
282
|
-
|
|
283
|
-
if (fs.existsSync(fastfilePath)) {
|
|
284
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
285
|
-
|
|
286
|
-
if (content.includes('upload_to') && !content.includes('increment_build_number')) {
|
|
287
|
-
pushFinding(this.findings, {
|
|
288
|
-
ruleId: 'ios.cicd.missing_build_increment',
|
|
289
|
-
severity: 'medium',
|
|
290
|
-
message: 'Deployment sin incremento automático de build number.',
|
|
291
|
-
filePath: fastfilePath,
|
|
292
|
-
line: 1
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
checkReleaseNotes() {
|
|
299
|
-
const changelogPath = path.join(this.projectRoot, 'CHANGELOG.md');
|
|
300
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
301
|
-
|
|
302
|
-
if (!fs.existsSync(changelogPath) && fs.existsSync(fastfilePath)) {
|
|
303
|
-
pushFinding(this.findings, {
|
|
304
|
-
ruleId: 'ios.cicd.missing_changelog',
|
|
305
|
-
severity: 'low',
|
|
306
|
-
message: 'Proyecto sin CHANGELOG.md. Documentar cambios para releases.',
|
|
307
|
-
filePath: 'PROJECT_ROOT',
|
|
308
|
-
line: 1
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
checkSlackNotifications() {
|
|
314
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
315
|
-
|
|
316
|
-
if (fs.existsSync(fastfilePath)) {
|
|
317
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
318
|
-
|
|
319
|
-
if (content.includes('upload_to') && !content.includes('slack')) {
|
|
320
|
-
pushFinding(this.findings, {
|
|
321
|
-
ruleId: 'ios.cicd.missing_notifications',
|
|
322
|
-
severity: 'low',
|
|
323
|
-
message: 'Deployment sin notificaciones. Añadir Slack para avisar al equipo.',
|
|
324
|
-
filePath: fastfilePath,
|
|
325
|
-
line: 1
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
checkMatchConfiguration() {
|
|
332
|
-
const matchfilePath = path.join(this.projectRoot, 'fastlane/Matchfile');
|
|
333
|
-
|
|
334
|
-
if (fs.existsSync(matchfilePath)) {
|
|
335
|
-
const content = fs.readFileSync(matchfilePath, 'utf-8');
|
|
336
|
-
|
|
337
|
-
if (!content.includes('git_url')) {
|
|
338
|
-
pushFinding(this.findings, {
|
|
339
|
-
ruleId: 'ios.cicd.match_missing_git_url',
|
|
340
|
-
severity: 'high',
|
|
341
|
-
message: 'Matchfile sin git_url. Match requiere repositorio para certificados.',
|
|
342
|
-
filePath: matchfilePath,
|
|
343
|
-
line: 1
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
checkGymConfiguration() {
|
|
350
|
-
const gymfilePath = path.join(this.projectRoot, 'fastlane/Gymfile');
|
|
351
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
352
|
-
|
|
353
|
-
if (fs.existsSync(fastfilePath) && !fs.existsSync(gymfilePath)) {
|
|
354
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
355
|
-
|
|
356
|
-
if (content.includes('build_app') || content.includes('gym')) {
|
|
357
|
-
pushFinding(this.findings, {
|
|
358
|
-
ruleId: 'ios.cicd.missing_gymfile',
|
|
359
|
-
severity: 'low',
|
|
360
|
-
message: 'build_app sin Gymfile. Considerar para centralizar configuración de build.',
|
|
361
|
-
filePath: 'fastlane/',
|
|
362
|
-
line: 1
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
checkScanConfiguration() {
|
|
369
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
370
|
-
|
|
371
|
-
if (fs.existsSync(fastfilePath)) {
|
|
372
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
373
|
-
|
|
374
|
-
if (content.includes('scan') && !content.includes('code_coverage')) {
|
|
375
|
-
pushFinding(this.findings, {
|
|
376
|
-
ruleId: 'ios.cicd.scan_without_coverage',
|
|
377
|
-
severity: 'low',
|
|
378
|
-
message: 'scan sin code_coverage: true. Activar para métricas.',
|
|
379
|
-
filePath: fastfilePath,
|
|
380
|
-
line: 1,
|
|
381
|
-
suggestion: 'scan(code_coverage: true, scheme: "MyApp")'
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
checkPilotConfiguration() {
|
|
388
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
389
|
-
|
|
390
|
-
if (fs.existsSync(fastfilePath)) {
|
|
391
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
392
|
-
|
|
393
|
-
if (content.includes('pilot') || content.includes('upload_to_testflight')) {
|
|
394
|
-
if (!content.includes('changelog') && !content.includes('whats_new')) {
|
|
395
|
-
pushFinding(this.findings, {
|
|
396
|
-
ruleId: 'ios.cicd.pilot_missing_changelog',
|
|
397
|
-
severity: 'low',
|
|
398
|
-
message: 'TestFlight upload sin changelog/whats_new.',
|
|
399
|
-
filePath: fastfilePath,
|
|
400
|
-
line: 1
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
checkAppStoreMetadata() {
|
|
408
|
-
const metadataPath = path.join(this.projectRoot, 'fastlane/metadata');
|
|
409
|
-
|
|
410
|
-
if (!fs.existsSync(metadataPath)) {
|
|
411
|
-
const fastfilePath = path.join(this.projectRoot, 'fastlane/Fastfile');
|
|
412
|
-
|
|
413
|
-
if (fs.existsSync(fastfilePath)) {
|
|
414
|
-
const content = fs.readFileSync(fastfilePath, 'utf-8');
|
|
415
|
-
|
|
416
|
-
if (content.includes('upload_to_app_store') || content.includes('deliver')) {
|
|
417
|
-
pushFinding(this.findings, {
|
|
418
|
-
ruleId: 'ios.cicd.missing_metadata',
|
|
419
|
-
severity: 'low',
|
|
420
|
-
message: 'Upload a App Store sin metadata/ folder. Versionar descripciones y screenshots.',
|
|
421
|
-
filePath: 'fastlane/',
|
|
422
|
-
line: 1,
|
|
423
|
-
suggestion: 'fastlane deliver init para crear estructura metadata/'
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
37
|
+
const ctx = {
|
|
38
|
+
findings: this.findings,
|
|
39
|
+
projectRoot: this.projectRoot,
|
|
40
|
+
pushFinding,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
checkFastfileExists(ctx);
|
|
44
|
+
checkGitHubActionsWorkflow(ctx);
|
|
45
|
+
checkTestFlightConfiguration(ctx);
|
|
46
|
+
checkBuildConfiguration(ctx);
|
|
47
|
+
checkCertificateManagement(ctx);
|
|
48
|
+
checkCodeSigningConfiguration(ctx);
|
|
49
|
+
checkAutomatedTesting(ctx);
|
|
50
|
+
checkVersionBumping(ctx);
|
|
51
|
+
checkReleaseNotes(ctx);
|
|
52
|
+
checkSlackNotifications(ctx);
|
|
53
|
+
checkMatchConfiguration(ctx);
|
|
54
|
+
checkGymConfiguration(ctx);
|
|
55
|
+
checkScanConfiguration(ctx);
|
|
56
|
+
checkPilotConfiguration(ctx);
|
|
57
|
+
checkAppStoreMetadata(ctx);
|
|
428
58
|
}
|
|
429
59
|
}
|
|
430
60
|
|