api-tests-coverage 1.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 +703 -0
- package/config.yaml.example +227 -0
- package/dist/action/src/index.d.ts +2 -0
- package/dist/action/src/index.d.ts.map +1 -0
- package/dist/action/src/index.js +349 -0
- package/dist/action/src/prComment.d.ts +34 -0
- package/dist/action/src/prComment.d.ts.map +1 -0
- package/dist/action/src/prComment.js +146 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
- package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
- package/dist/src/ast/astTypes.d.ts +105 -0
- package/dist/src/ast/astTypes.d.ts.map +1 -0
- package/dist/src/ast/astTypes.js +9 -0
- package/dist/src/ast/languageAnalyzer.d.ts +46 -0
- package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
- package/dist/src/ast/languageAnalyzer.js +9 -0
- package/dist/src/ast/languageCapabilities.d.ts +24 -0
- package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
- package/dist/src/ast/languageCapabilities.js +92 -0
- package/dist/src/ast/parseFile.d.ts +16 -0
- package/dist/src/ast/parseFile.d.ts.map +1 -0
- package/dist/src/ast/parseFile.js +65 -0
- package/dist/src/ast/parserRegistry.d.ts +39 -0
- package/dist/src/ast/parserRegistry.d.ts.map +1 -0
- package/dist/src/ast/parserRegistry.js +66 -0
- package/dist/src/buildSummary.d.ts +26 -0
- package/dist/src/buildSummary.d.ts.map +1 -0
- package/dist/src/buildSummary.js +193 -0
- package/dist/src/businessCoverage.d.ts +68 -0
- package/dist/src/businessCoverage.d.ts.map +1 -0
- package/dist/src/businessCoverage.js +290 -0
- package/dist/src/compatibilityCoverage.d.ts +83 -0
- package/dist/src/compatibilityCoverage.d.ts.map +1 -0
- package/dist/src/compatibilityCoverage.js +501 -0
- package/dist/src/config/defaultConfig.d.ts +9 -0
- package/dist/src/config/defaultConfig.d.ts.map +1 -0
- package/dist/src/config/defaultConfig.js +97 -0
- package/dist/src/config/index.d.ts +12 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +37 -0
- package/dist/src/config/loadConfig.d.ts +29 -0
- package/dist/src/config/loadConfig.d.ts.map +1 -0
- package/dist/src/config/loadConfig.js +135 -0
- package/dist/src/config/mergeConfig.d.ts +15 -0
- package/dist/src/config/mergeConfig.d.ts.map +1 -0
- package/dist/src/config/mergeConfig.js +57 -0
- package/dist/src/config/schema.d.ts +15 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +30 -0
- package/dist/src/config/types.d.ts +175 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config/types.js +9 -0
- package/dist/src/config/validateConfig.d.ts +22 -0
- package/dist/src/config/validateConfig.d.ts.map +1 -0
- package/dist/src/config/validateConfig.js +171 -0
- package/dist/src/config.d.ts +168 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +204 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
- package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
- package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/index.js +63 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
- package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
- package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/types.js +21 -0
- package/dist/src/discovery/fileClassifier.d.ts +50 -0
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
- package/dist/src/discovery/fileClassifier.js +238 -0
- package/dist/src/discovery/projectDiscovery.d.ts +66 -0
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
- package/dist/src/discovery/projectDiscovery.js +287 -0
- package/dist/src/endpointCoverage.d.ts +70 -0
- package/dist/src/endpointCoverage.d.ts.map +1 -0
- package/dist/src/endpointCoverage.js +381 -0
- package/dist/src/errorCoverage.d.ts +93 -0
- package/dist/src/errorCoverage.d.ts.map +1 -0
- package/dist/src/errorCoverage.js +698 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +1441 -0
- package/dist/src/inference/businessRuleInference.d.ts +63 -0
- package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
- package/dist/src/inference/businessRuleInference.js +268 -0
- package/dist/src/inference/integrationFlowInference.d.ts +56 -0
- package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
- package/dist/src/inference/integrationFlowInference.js +266 -0
- package/dist/src/integrationCoverage.d.ts +72 -0
- package/dist/src/integrationCoverage.d.ts.map +1 -0
- package/dist/src/integrationCoverage.js +317 -0
- package/dist/src/intelligence/index.d.ts +20 -0
- package/dist/src/intelligence/index.d.ts.map +1 -0
- package/dist/src/intelligence/index.js +105 -0
- package/dist/src/intelligence/linkageEngine.d.ts +20 -0
- package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
- package/dist/src/intelligence/linkageEngine.js +522 -0
- package/dist/src/intelligence/markdownReporter.d.ts +12 -0
- package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
- package/dist/src/intelligence/markdownReporter.js +265 -0
- package/dist/src/intelligence/riskScoring.d.ts +53 -0
- package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
- package/dist/src/intelligence/riskScoring.js +181 -0
- package/dist/src/intelligence/types.d.ts +121 -0
- package/dist/src/intelligence/types.d.ts.map +1 -0
- package/dist/src/intelligence/types.js +8 -0
- package/dist/src/languageDetection.d.ts +100 -0
- package/dist/src/languageDetection.d.ts.map +1 -0
- package/dist/src/languageDetection.js +349 -0
- package/dist/src/languages/java/index.d.ts +16 -0
- package/dist/src/languages/java/index.d.ts.map +1 -0
- package/dist/src/languages/java/index.js +103 -0
- package/dist/src/languages/java/parser.d.ts +7 -0
- package/dist/src/languages/java/parser.d.ts.map +1 -0
- package/dist/src/languages/java/parser.js +50 -0
- package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
- package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
- package/dist/src/languages/java/semanticBuilder.js +358 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/annotationExtractor.js +94 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/assertionResolver.js +150 -0
- package/dist/src/languages/javascript/callResolver.d.ts +23 -0
- package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/callResolver.js +236 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
- package/dist/src/languages/javascript/index.d.ts +20 -0
- package/dist/src/languages/javascript/index.d.ts.map +1 -0
- package/dist/src/languages/javascript/index.js +136 -0
- package/dist/src/languages/javascript/parser.d.ts +14 -0
- package/dist/src/languages/javascript/parser.d.ts.map +1 -0
- package/dist/src/languages/javascript/parser.js +38 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/symbolResolver.js +183 -0
- package/dist/src/languages/kotlin/index.d.ts +16 -0
- package/dist/src/languages/kotlin/index.d.ts.map +1 -0
- package/dist/src/languages/kotlin/index.js +151 -0
- package/dist/src/languages/kotlin/parser.d.ts +11 -0
- package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
- package/dist/src/languages/kotlin/parser.js +74 -0
- package/dist/src/languages/python/index.d.ts +15 -0
- package/dist/src/languages/python/index.d.ts.map +1 -0
- package/dist/src/languages/python/index.js +293 -0
- package/dist/src/languages/ruby/index.d.ts +15 -0
- package/dist/src/languages/ruby/index.d.ts.map +1 -0
- package/dist/src/languages/ruby/index.js +274 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
- package/dist/src/languages/shared/treeSitterUtils.js +100 -0
- package/dist/src/languages/typescript/index.d.ts +14 -0
- package/dist/src/languages/typescript/index.d.ts.map +1 -0
- package/dist/src/languages/typescript/index.js +25 -0
- package/dist/src/lib/index.d.ts +228 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +486 -0
- package/dist/src/mcp/client/index.d.ts +37 -0
- package/dist/src/mcp/client/index.d.ts.map +1 -0
- package/dist/src/mcp/client/index.js +235 -0
- package/dist/src/mcp/config.d.ts +50 -0
- package/dist/src/mcp/config.d.ts.map +1 -0
- package/dist/src/mcp/config.js +125 -0
- package/dist/src/mcp/events.d.ts +24 -0
- package/dist/src/mcp/events.d.ts.map +1 -0
- package/dist/src/mcp/events.js +48 -0
- package/dist/src/mcp/fallback/index.d.ts +50 -0
- package/dist/src/mcp/fallback/index.d.ts.map +1 -0
- package/dist/src/mcp/fallback/index.js +216 -0
- package/dist/src/mcp/index.d.ts +67 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +212 -0
- package/dist/src/mcp/normalizer.d.ts +21 -0
- package/dist/src/mcp/normalizer.d.ts.map +1 -0
- package/dist/src/mcp/normalizer.js +99 -0
- package/dist/src/mcp/prompts/index.d.ts +86 -0
- package/dist/src/mcp/prompts/index.d.ts.map +1 -0
- package/dist/src/mcp/prompts/index.js +304 -0
- package/dist/src/mcp/templates/index.d.ts +35 -0
- package/dist/src/mcp/templates/index.d.ts.map +1 -0
- package/dist/src/mcp/templates/index.js +143 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
- package/dist/src/mcp/testing/mock-server/index.js +157 -0
- package/dist/src/mcp/types.d.ts +127 -0
- package/dist/src/mcp/types.d.ts.map +1 -0
- package/dist/src/mcp/types.js +8 -0
- package/dist/src/observability.d.ts +138 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +519 -0
- package/dist/src/parameterCoverage.d.ts +75 -0
- package/dist/src/parameterCoverage.d.ts.map +1 -0
- package/dist/src/parameterCoverage.js +629 -0
- package/dist/src/perfResilienceCoverage.d.ts +155 -0
- package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
- package/dist/src/perfResilienceCoverage.js +670 -0
- package/dist/src/pluginLoader.d.ts +51 -0
- package/dist/src/pluginLoader.d.ts.map +1 -0
- package/dist/src/pluginLoader.js +72 -0
- package/dist/src/publishing.d.ts +63 -0
- package/dist/src/publishing.d.ts.map +1 -0
- package/dist/src/publishing.js +379 -0
- package/dist/src/qualityGate.d.ts +58 -0
- package/dist/src/qualityGate.d.ts.map +1 -0
- package/dist/src/qualityGate.js +118 -0
- package/dist/src/reporting.d.ts +41 -0
- package/dist/src/reporting.d.ts.map +1 -0
- package/dist/src/reporting.js +278 -0
- package/dist/src/screenshots.d.ts +71 -0
- package/dist/src/screenshots.d.ts.map +1 -0
- package/dist/src/screenshots.js +141 -0
- package/dist/src/security/gate/index.d.ts +11 -0
- package/dist/src/security/gate/index.d.ts.map +1 -0
- package/dist/src/security/gate/index.js +65 -0
- package/dist/src/security/index.d.ts +30 -0
- package/dist/src/security/index.d.ts.map +1 -0
- package/dist/src/security/index.js +342 -0
- package/dist/src/security/normalizers/semgrep.d.ts +10 -0
- package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
- package/dist/src/security/normalizers/semgrep.js +104 -0
- package/dist/src/security/normalizers/trivy.d.ts +10 -0
- package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
- package/dist/src/security/normalizers/trivy.js +78 -0
- package/dist/src/security/normalizers/zap.d.ts +10 -0
- package/dist/src/security/normalizers/zap.d.ts.map +1 -0
- package/dist/src/security/normalizers/zap.js +104 -0
- package/dist/src/security/scanners/semgrep.d.ts +6 -0
- package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
- package/dist/src/security/scanners/semgrep.js +125 -0
- package/dist/src/security/scanners/trivy.d.ts +6 -0
- package/dist/src/security/scanners/trivy.d.ts.map +1 -0
- package/dist/src/security/scanners/trivy.js +115 -0
- package/dist/src/security/scanners/zap.d.ts +6 -0
- package/dist/src/security/scanners/zap.d.ts.map +1 -0
- package/dist/src/security/scanners/zap.js +135 -0
- package/dist/src/security/types.d.ts +146 -0
- package/dist/src/security/types.d.ts.map +1 -0
- package/dist/src/security/types.js +6 -0
- package/dist/src/securityCoverage.d.ts +116 -0
- package/dist/src/securityCoverage.d.ts.map +1 -0
- package/dist/src/securityCoverage.js +725 -0
- package/dist/src/summary/buildSummary.d.ts +28 -0
- package/dist/src/summary/buildSummary.d.ts.map +1 -0
- package/dist/src/summary/buildSummary.js +257 -0
- package/dist/src/summary/evaluateMetrics.d.ts +31 -0
- package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
- package/dist/src/summary/evaluateMetrics.js +118 -0
- package/dist/src/summary/index.d.ts +10 -0
- package/dist/src/summary/index.d.ts.map +1 -0
- package/dist/src/summary/index.js +22 -0
- package/dist/src/summary/markdownRenderer.d.ts +139 -0
- package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
- package/dist/src/summary/markdownRenderer.js +459 -0
- package/dist/src/summary/prSummary.d.ts +24 -0
- package/dist/src/summary/prSummary.d.ts.map +1 -0
- package/dist/src/summary/prSummary.js +233 -0
- package/dist/src/summary/summaryTypes.d.ts +35 -0
- package/dist/src/summary/summaryTypes.d.ts.map +1 -0
- package/dist/src/summary/summaryTypes.js +27 -0
- package/package.json +84 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# config.yaml.example — Annotated full reference configuration
|
|
3
|
+
#
|
|
4
|
+
# Copy this file to config.yaml and customize for your project.
|
|
5
|
+
# All fields are optional except `version`.
|
|
6
|
+
# When config.yaml is absent, the analyzer runs a full default profile and
|
|
7
|
+
# emits a warning. See docs/guides/configuration.md for the full reference.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
# Required. Config schema version. Must be 1 for this release.
|
|
11
|
+
version: 1
|
|
12
|
+
|
|
13
|
+
# ── Project ──────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
project:
|
|
16
|
+
# Optional. Display name used in reports and summaries.
|
|
17
|
+
# Default: (absent)
|
|
18
|
+
name: my-api-project
|
|
19
|
+
|
|
20
|
+
# ── Analysis mode ─────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
analysis:
|
|
23
|
+
# Optional. 'full' runs every scan type. 'custom' runs only explicitly-enabled types.
|
|
24
|
+
# Default: full
|
|
25
|
+
defaultMode: full
|
|
26
|
+
|
|
27
|
+
# Optional. If true, the analyzer exits non-zero when config.yaml is missing.
|
|
28
|
+
# Default: false
|
|
29
|
+
failOnConfigMissing: false
|
|
30
|
+
|
|
31
|
+
# Optional. If true, a warning is printed when config.yaml is absent.
|
|
32
|
+
# Default: true
|
|
33
|
+
warnOnConfigMissing: true
|
|
34
|
+
|
|
35
|
+
# ── AST-based analysis ──────────────────────────────────────────────────────
|
|
36
|
+
ast:
|
|
37
|
+
# Optional. Master AST switch. When false, all files use the regex pipeline.
|
|
38
|
+
# Default: true
|
|
39
|
+
enabled: true
|
|
40
|
+
|
|
41
|
+
# Optional. When true, if AST parsing succeeds but finds 0 HTTP interactions,
|
|
42
|
+
# the regex fallback runs and tags results with resolutionType:'heuristic' and
|
|
43
|
+
# confidence:'low'. When false, 0 AST results are returned verbatim.
|
|
44
|
+
# Default: true
|
|
45
|
+
fallbackHeuristics: true
|
|
46
|
+
|
|
47
|
+
# Optional. Maximum call-chain depth when tracing wrapper/helper functions.
|
|
48
|
+
# Default: 4
|
|
49
|
+
maxCallDepth: 4
|
|
50
|
+
|
|
51
|
+
# Optional. Link HTTP calls to downstream response assertions.
|
|
52
|
+
# Default: true
|
|
53
|
+
assertionAware: true
|
|
54
|
+
|
|
55
|
+
# Optional. Per-language enable/disable toggles.
|
|
56
|
+
languages:
|
|
57
|
+
javascript: { enabled: true }
|
|
58
|
+
typescript: { enabled: true }
|
|
59
|
+
java: { enabled: true }
|
|
60
|
+
kotlin: { enabled: true }
|
|
61
|
+
python: { enabled: true }
|
|
62
|
+
ruby: { enabled: true }
|
|
63
|
+
cucumber: { enabled: true }
|
|
64
|
+
|
|
65
|
+
# ── Scans ─────────────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
scans:
|
|
68
|
+
|
|
69
|
+
# Coverage scan configuration
|
|
70
|
+
coverage:
|
|
71
|
+
# Optional. Set false to skip all coverage scans.
|
|
72
|
+
# Default: true
|
|
73
|
+
enabled: true
|
|
74
|
+
|
|
75
|
+
# Optional. Which coverage types to run.
|
|
76
|
+
# Valid values: endpoint | parameter | business | integration | error |
|
|
77
|
+
# security | performance | compatibility
|
|
78
|
+
# Default: all types
|
|
79
|
+
types:
|
|
80
|
+
- endpoint
|
|
81
|
+
- parameter
|
|
82
|
+
- business
|
|
83
|
+
- integration
|
|
84
|
+
- error
|
|
85
|
+
- security
|
|
86
|
+
- performance
|
|
87
|
+
- compatibility
|
|
88
|
+
|
|
89
|
+
# Security scanner configuration
|
|
90
|
+
security:
|
|
91
|
+
# Optional. Set false to skip all security scanners.
|
|
92
|
+
# Default: true
|
|
93
|
+
enabled: true
|
|
94
|
+
|
|
95
|
+
# Optional. Which security scanners to run (only runs if scanner is installed).
|
|
96
|
+
# Valid values: semgrep | trivy | zap
|
|
97
|
+
# Default: all scanners
|
|
98
|
+
scanners:
|
|
99
|
+
- semgrep
|
|
100
|
+
- trivy
|
|
101
|
+
- zap
|
|
102
|
+
|
|
103
|
+
# AI and intelligent analysis configuration
|
|
104
|
+
intelligence:
|
|
105
|
+
# Optional. Set false to skip all AI analysis silently.
|
|
106
|
+
# Default: true
|
|
107
|
+
enabled: true
|
|
108
|
+
|
|
109
|
+
# Optional. Which intelligence analysis types to run.
|
|
110
|
+
# Valid values: ai-summary | risk-prioritization | recommendations |
|
|
111
|
+
# scanner-interpretation
|
|
112
|
+
# Default: all types
|
|
113
|
+
types:
|
|
114
|
+
- ai-summary
|
|
115
|
+
- risk-prioritization
|
|
116
|
+
- recommendations
|
|
117
|
+
- scanner-interpretation
|
|
118
|
+
|
|
119
|
+
# ── MCP integration ───────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
mcp:
|
|
122
|
+
# Optional. Set true to enable MCP server integrations.
|
|
123
|
+
# Default: false (disabled when config.yaml is absent to avoid unexpected network calls)
|
|
124
|
+
enabled: false
|
|
125
|
+
|
|
126
|
+
# Optional. Default transport for all servers that do not specify one.
|
|
127
|
+
# Valid values: stdio | http
|
|
128
|
+
# Default: stdio
|
|
129
|
+
defaultTransport: stdio
|
|
130
|
+
|
|
131
|
+
# Optional. Default request timeout in milliseconds.
|
|
132
|
+
# Default: 30000
|
|
133
|
+
timeoutMs: 30000
|
|
134
|
+
|
|
135
|
+
# Optional. Named MCP server definitions.
|
|
136
|
+
servers:
|
|
137
|
+
# Each key is a server ID of your choice.
|
|
138
|
+
# Example: stdio transport (spawns a local process)
|
|
139
|
+
# coverageSummary:
|
|
140
|
+
# enabled: true # Required per-server
|
|
141
|
+
# transport: stdio # Optional; inherits defaultTransport
|
|
142
|
+
# command: node # Required when transport is 'stdio'
|
|
143
|
+
# args: # Optional arguments for the command
|
|
144
|
+
# - ./mcp-servers/coverage-summary.js
|
|
145
|
+
|
|
146
|
+
# Example: HTTP transport (connects to a running HTTP MCP server)
|
|
147
|
+
# securityScan:
|
|
148
|
+
# enabled: true
|
|
149
|
+
# transport: http
|
|
150
|
+
# url: http://localhost:3100/mcp # Required when transport is 'http'
|
|
151
|
+
# headers: # Optional auth headers
|
|
152
|
+
# Authorization: Bearer my-token
|
|
153
|
+
|
|
154
|
+
# ── Thresholds ────────────────────────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
thresholds:
|
|
157
|
+
# Optional. Default threshold applied when no type-specific value is set.
|
|
158
|
+
# Valid range: 0 – 100.
|
|
159
|
+
# Default: 80
|
|
160
|
+
global: 80
|
|
161
|
+
|
|
162
|
+
# Optional per-type thresholds (0–100). Each overrides 'global' for that type.
|
|
163
|
+
endpoint: 80
|
|
164
|
+
parameter: 80
|
|
165
|
+
business: 80
|
|
166
|
+
integration: 80
|
|
167
|
+
error: 80
|
|
168
|
+
security: 80
|
|
169
|
+
performance: 80
|
|
170
|
+
compatibility: 80
|
|
171
|
+
|
|
172
|
+
# ── Quality gate ──────────────────────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
qualityGate:
|
|
175
|
+
# Optional. Enables threshold enforcement.
|
|
176
|
+
# Default: true
|
|
177
|
+
enabled: true
|
|
178
|
+
|
|
179
|
+
# Optional. When true, the analyzer exits non-zero if any threshold is missed.
|
|
180
|
+
# Default: false
|
|
181
|
+
failBuildOnThresholdMiss: false
|
|
182
|
+
|
|
183
|
+
# Optional. 'strict' fails on unknown config keys and any threshold miss.
|
|
184
|
+
# 'warn' logs threshold misses without failing the build.
|
|
185
|
+
# Valid values: strict | warn
|
|
186
|
+
# Default: warn
|
|
187
|
+
mode: warn
|
|
188
|
+
|
|
189
|
+
# ── Reports ───────────────────────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
reports:
|
|
192
|
+
# Optional. Directory where all report files are written.
|
|
193
|
+
# Default: reports
|
|
194
|
+
outputDir: reports
|
|
195
|
+
|
|
196
|
+
# Optional. Which report formats to produce.
|
|
197
|
+
# Valid values: json | html | csv | junit | markdown
|
|
198
|
+
# Default: [json]
|
|
199
|
+
formats:
|
|
200
|
+
- json
|
|
201
|
+
- html
|
|
202
|
+
- csv
|
|
203
|
+
- junit
|
|
204
|
+
|
|
205
|
+
# ── Publishing ────────────────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
publishing:
|
|
208
|
+
# Optional. Set true to enable static site publishing.
|
|
209
|
+
# Default: false
|
|
210
|
+
enabled: false
|
|
211
|
+
|
|
212
|
+
githubPages:
|
|
213
|
+
# Optional. Set true to publish to GitHub Pages via gh-pages branch.
|
|
214
|
+
# Default: false
|
|
215
|
+
enabled: false
|
|
216
|
+
|
|
217
|
+
# ── Dashboard ─────────────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
dashboard:
|
|
220
|
+
aiSummary:
|
|
221
|
+
# Optional. When false, AI summary panels are hidden in the dashboard.
|
|
222
|
+
# Default: true
|
|
223
|
+
enabled: true
|
|
224
|
+
|
|
225
|
+
# Optional. When true, AI summary panels start collapsed in the dashboard.
|
|
226
|
+
# Default: true
|
|
227
|
+
collapsedByDefault: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../action/src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const core = __importStar(require("@actions/core"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const index_1 = require("../../src/lib/index");
|
|
40
|
+
const config_1 = require("../../src/config");
|
|
41
|
+
const buildSummary_1 = require("../../src/buildSummary");
|
|
42
|
+
const prComment_1 = require("./prComment");
|
|
43
|
+
async function run() {
|
|
44
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
45
|
+
try {
|
|
46
|
+
const spec = core.getInput('spec') || 'sample/openapi.yaml';
|
|
47
|
+
const tests = core.getInput('tests') || 'tests/**/*.ts';
|
|
48
|
+
const format = core.getInput('format') || 'json,html';
|
|
49
|
+
const coverageTypesRaw = core.getInput('coverage-types') || 'endpoint';
|
|
50
|
+
const language = core.getInput('language') || 'auto';
|
|
51
|
+
const reportsDirInput = core.getInput('reports-dir') || 'reports';
|
|
52
|
+
const configInput = core.getInput('config') || '';
|
|
53
|
+
const publishPages = core.getInput('publish-pages') === 'true';
|
|
54
|
+
const siteDirInput = core.getInput('site-dir') || 'site';
|
|
55
|
+
const pagesBasePath = core.getInput('pages-base-path') || '/';
|
|
56
|
+
const qualityGateEnabled = core.getInput('quality-gate') !== 'false';
|
|
57
|
+
const qualityGateMode = core.getInput('quality-gate-mode') || 'strict';
|
|
58
|
+
const writeGitHubSummary = core.getInput('write-step-summary') !== 'false';
|
|
59
|
+
const githubToken = core.getInput('github-token') || '';
|
|
60
|
+
const postComment = core.getInput('post-pr-comment') !== 'false';
|
|
61
|
+
// Load config file if specified, merging with CLI inputs
|
|
62
|
+
const fileConfig = configInput
|
|
63
|
+
? (0, config_1.resolveConfig)(configInput)
|
|
64
|
+
: (0, config_1.resolveConfig)();
|
|
65
|
+
const globalThreshold = parseFloat(core.getInput('threshold-global') || '0');
|
|
66
|
+
const cliThresholds = {};
|
|
67
|
+
if (globalThreshold > 0)
|
|
68
|
+
cliThresholds['global'] = globalThreshold;
|
|
69
|
+
const perCategoryThresholds = {
|
|
70
|
+
endpoint: parseFloat(core.getInput('threshold-endpoint') || '0'),
|
|
71
|
+
parameter: parseFloat(core.getInput('threshold-parameter') || '0'),
|
|
72
|
+
business: parseFloat(core.getInput('threshold-business') || '0'),
|
|
73
|
+
integration: parseFloat(core.getInput('threshold-integration') || '0'),
|
|
74
|
+
error: parseFloat(core.getInput('threshold-error') || '0'),
|
|
75
|
+
security: parseFloat(core.getInput('threshold-security') || '0'),
|
|
76
|
+
};
|
|
77
|
+
// Only include non-zero per-category thresholds
|
|
78
|
+
for (const [key, value] of Object.entries(perCategoryThresholds)) {
|
|
79
|
+
if (value > 0)
|
|
80
|
+
cliThresholds[key] = value;
|
|
81
|
+
}
|
|
82
|
+
const mergedConfig = (0, config_1.mergeConfig)(fileConfig, {
|
|
83
|
+
thresholds: Object.keys(cliThresholds).length > 0 ? cliThresholds : fileConfig.thresholds,
|
|
84
|
+
});
|
|
85
|
+
const workspace = (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd();
|
|
86
|
+
const reportsDir = path.isAbsolute(reportsDirInput)
|
|
87
|
+
? reportsDirInput
|
|
88
|
+
: path.join(workspace, reportsDirInput);
|
|
89
|
+
const siteDir = path.isAbsolute(siteDirInput)
|
|
90
|
+
? siteDirInput
|
|
91
|
+
: path.join(workspace, siteDirInput);
|
|
92
|
+
const coverageTypes = coverageTypesRaw
|
|
93
|
+
.split(',')
|
|
94
|
+
.map((t) => t.trim().toLowerCase())
|
|
95
|
+
.filter(Boolean);
|
|
96
|
+
core.info(`Running coverage types: ${coverageTypes.join(', ')}`);
|
|
97
|
+
core.info(`Reports will be written to: ${reportsDir}`);
|
|
98
|
+
if (!fs.existsSync(reportsDir)) {
|
|
99
|
+
fs.mkdirSync(reportsDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
const allResults = [];
|
|
102
|
+
for (const coverageType of coverageTypes) {
|
|
103
|
+
switch (coverageType) {
|
|
104
|
+
case 'endpoint': {
|
|
105
|
+
core.info('Running endpoint coverage analysis...');
|
|
106
|
+
const result = await (0, index_1.analyzeEndpoints)({
|
|
107
|
+
spec,
|
|
108
|
+
tests,
|
|
109
|
+
format,
|
|
110
|
+
language,
|
|
111
|
+
reportsDir,
|
|
112
|
+
});
|
|
113
|
+
allResults.push(result);
|
|
114
|
+
core.setOutput('endpoint-coverage', String(result.coveragePercent));
|
|
115
|
+
core.info(`Endpoint coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'parameter': {
|
|
119
|
+
core.info('Running parameter coverage analysis...');
|
|
120
|
+
const result = await (0, index_1.analyzeParameters)({
|
|
121
|
+
spec,
|
|
122
|
+
tests,
|
|
123
|
+
format,
|
|
124
|
+
reportsDir,
|
|
125
|
+
});
|
|
126
|
+
allResults.push(result);
|
|
127
|
+
core.setOutput('parameter-coverage', String(result.coveragePercent));
|
|
128
|
+
core.info(`Parameter coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case 'business': {
|
|
132
|
+
const rules = core.getInput('rules');
|
|
133
|
+
if (!rules) {
|
|
134
|
+
core.warning('Skipping business coverage: "rules" input is required');
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
core.info('Running business rule coverage analysis...');
|
|
138
|
+
const result = await (0, index_1.analyzeBusinessRules)({
|
|
139
|
+
rules,
|
|
140
|
+
tests,
|
|
141
|
+
format,
|
|
142
|
+
reportsDir,
|
|
143
|
+
});
|
|
144
|
+
allResults.push(result);
|
|
145
|
+
core.setOutput('business-coverage', String(result.coveragePercent));
|
|
146
|
+
core.info(`Business coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case 'integration': {
|
|
150
|
+
const flows = core.getInput('flows');
|
|
151
|
+
if (!flows) {
|
|
152
|
+
core.warning('Skipping integration coverage: "flows" input is required');
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
core.info('Running integration flow coverage analysis...');
|
|
156
|
+
const result = await (0, index_1.analyzeIntegrationFlows)({
|
|
157
|
+
flows,
|
|
158
|
+
tests,
|
|
159
|
+
format,
|
|
160
|
+
reportsDir,
|
|
161
|
+
});
|
|
162
|
+
allResults.push(result);
|
|
163
|
+
core.setOutput('integration-coverage', String(result.coveragePercent));
|
|
164
|
+
core.info(`Integration coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case 'error': {
|
|
168
|
+
core.info('Running error handling coverage analysis...');
|
|
169
|
+
const result = await (0, index_1.analyzeErrorHandling)({
|
|
170
|
+
spec,
|
|
171
|
+
tests,
|
|
172
|
+
format,
|
|
173
|
+
reportsDir,
|
|
174
|
+
});
|
|
175
|
+
allResults.push(result);
|
|
176
|
+
core.setOutput('error-coverage', String(result.coveragePercent));
|
|
177
|
+
core.info(`Error coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case 'security': {
|
|
181
|
+
core.info('Running security coverage analysis...');
|
|
182
|
+
const result = await (0, index_1.analyzeSecurityControls)({
|
|
183
|
+
spec,
|
|
184
|
+
tests,
|
|
185
|
+
format,
|
|
186
|
+
reportsDir,
|
|
187
|
+
});
|
|
188
|
+
allResults.push(result);
|
|
189
|
+
core.setOutput('security-coverage', String(result.coveragePercent));
|
|
190
|
+
core.info(`Security coverage: ${result.coveredItems}/${result.totalItems} (${result.coveragePercent}%)`);
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case 'security-scan': {
|
|
194
|
+
core.info('Running integrated security scan (Semgrep / Trivy / ZAP)...');
|
|
195
|
+
const semgrepReport = core.getInput('semgrep-report') || undefined;
|
|
196
|
+
const trivyReport = core.getInput('trivy-report') || undefined;
|
|
197
|
+
const zapReport = core.getInput('zap-report') || undefined;
|
|
198
|
+
const failOnCritical = core.getInput('fail-on-critical') === 'true';
|
|
199
|
+
const failOnHigh = core.getInput('fail-on-high') === 'true';
|
|
200
|
+
const maxSecretsRaw = core.getInput('max-secrets');
|
|
201
|
+
const maxMediumRaw = core.getInput('max-medium');
|
|
202
|
+
const maxMisconfigHighRaw = core.getInput('max-misconfig-high');
|
|
203
|
+
const maxCriticalVulnsRaw = core.getInput('max-critical-vulns');
|
|
204
|
+
const maxHighVulnsRaw = core.getInput('max-high-vulns');
|
|
205
|
+
const gateConfig = {};
|
|
206
|
+
if (failOnCritical)
|
|
207
|
+
gateConfig['failOnCritical'] = true;
|
|
208
|
+
if (failOnHigh)
|
|
209
|
+
gateConfig['failOnHigh'] = true;
|
|
210
|
+
if (maxSecretsRaw !== '')
|
|
211
|
+
gateConfig['maxSecrets'] = parseInt(maxSecretsRaw, 10);
|
|
212
|
+
if (maxMediumRaw !== '')
|
|
213
|
+
gateConfig['maxMedium'] = parseInt(maxMediumRaw, 10);
|
|
214
|
+
if (maxMisconfigHighRaw !== '')
|
|
215
|
+
gateConfig['maxMisconfigHigh'] = parseInt(maxMisconfigHighRaw, 10);
|
|
216
|
+
if (maxCriticalVulnsRaw !== '')
|
|
217
|
+
gateConfig['maxCriticalVulns'] = parseInt(maxCriticalVulnsRaw, 10);
|
|
218
|
+
if (maxHighVulnsRaw !== '')
|
|
219
|
+
gateConfig['maxHighVulns'] = parseInt(maxHighVulnsRaw, 10);
|
|
220
|
+
const scanners = {};
|
|
221
|
+
if (semgrepReport) {
|
|
222
|
+
scanners['semgrep'] = { enabled: true, mode: 'import', reportPath: semgrepReport };
|
|
223
|
+
}
|
|
224
|
+
if (trivyReport) {
|
|
225
|
+
scanners['trivy'] = { enabled: true, mode: 'import', reportPath: trivyReport };
|
|
226
|
+
}
|
|
227
|
+
if (zapReport) {
|
|
228
|
+
scanners['zap'] = { enabled: true, mode: 'import', reportPath: zapReport };
|
|
229
|
+
}
|
|
230
|
+
const summary = await (0, index_1.runSecurityAnalysis)({
|
|
231
|
+
config: {
|
|
232
|
+
enabled: true,
|
|
233
|
+
workspace,
|
|
234
|
+
scanners: scanners,
|
|
235
|
+
gate: Object.keys(gateConfig).length > 0
|
|
236
|
+
? gateConfig
|
|
237
|
+
: undefined,
|
|
238
|
+
},
|
|
239
|
+
reportsDir,
|
|
240
|
+
});
|
|
241
|
+
core.setOutput('security-scan-findings', String(summary.totalFindings));
|
|
242
|
+
core.setOutput('security-gate-passed', String((_c = (_b = summary.gateResult) === null || _b === void 0 ? void 0 : _b.passed) !== null && _c !== void 0 ? _c : true));
|
|
243
|
+
core.info(`Security scan complete: ${summary.totalFindings} findings`);
|
|
244
|
+
core.info(` CRITICAL: ${summary.bySeverity.CRITICAL}`);
|
|
245
|
+
core.info(` HIGH: ${summary.bySeverity.HIGH}`);
|
|
246
|
+
core.info(` MEDIUM: ${summary.bySeverity.MEDIUM}`);
|
|
247
|
+
core.info(` LOW: ${summary.bySeverity.LOW}`);
|
|
248
|
+
if (summary.gateResult && !summary.gateResult.passed) {
|
|
249
|
+
const msg = summary.gateResult.reasons.join('\n');
|
|
250
|
+
core.setFailed(`Security gate failed:\n${msg}`);
|
|
251
|
+
return; // exit early – gate already failed the action
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
default:
|
|
256
|
+
core.warning(`Unknown coverage type: ${coverageType}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
core.setOutput('reports-dir', reportsDir);
|
|
260
|
+
// Build the effective config for quality gate + publishing
|
|
261
|
+
const effectiveConfig = {
|
|
262
|
+
...mergedConfig,
|
|
263
|
+
publishing: {
|
|
264
|
+
enabled: publishPages,
|
|
265
|
+
outputDir: siteDir,
|
|
266
|
+
buildId: 'run-number',
|
|
267
|
+
githubPages: {
|
|
268
|
+
enabled: publishPages,
|
|
269
|
+
basePath: pagesBasePath,
|
|
270
|
+
},
|
|
271
|
+
...((_d = mergedConfig.publishing) !== null && _d !== void 0 ? _d : {}),
|
|
272
|
+
},
|
|
273
|
+
qualityGate: {
|
|
274
|
+
enabled: qualityGateEnabled,
|
|
275
|
+
failBuildOnThresholdMiss: qualityGateEnabled,
|
|
276
|
+
mode: (qualityGateMode === 'warn' ? 'warn' : 'strict'),
|
|
277
|
+
...((_e = mergedConfig.qualityGate) !== null && _e !== void 0 ? _e : {}),
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
const repoOwner = (_f = process.env['GITHUB_REPOSITORY_OWNER']) !== null && _f !== void 0 ? _f : '';
|
|
281
|
+
const repoName = (_h = (_g = process.env['GITHUB_REPOSITORY']) === null || _g === void 0 ? void 0 : _g.split('/')[1]) !== null && _h !== void 0 ? _h : '';
|
|
282
|
+
const pagesUrl = publishPages && repoOwner && repoName
|
|
283
|
+
? `https://${repoOwner}.github.io/${repoName}${pagesBasePath}`
|
|
284
|
+
: undefined;
|
|
285
|
+
// Run quality gate + publishing (always generates reports, even on failure)
|
|
286
|
+
const { reports, qualityGate, exitCode } = await (0, index_1.runAnalysisAndEnforceQualityGate)({
|
|
287
|
+
results: allResults,
|
|
288
|
+
config: effectiveConfig,
|
|
289
|
+
branch: process.env['GITHUB_REF_NAME'],
|
|
290
|
+
reportsDir,
|
|
291
|
+
writeGitHubSummary,
|
|
292
|
+
pagesUrl,
|
|
293
|
+
});
|
|
294
|
+
if (reports) {
|
|
295
|
+
core.setOutput('site-dir', reports.siteDir);
|
|
296
|
+
core.info(`Static site written to: ${reports.siteDir}`);
|
|
297
|
+
}
|
|
298
|
+
core.setOutput('quality-gate-passed', String(qualityGate.passed));
|
|
299
|
+
// New top-level outputs for consumers
|
|
300
|
+
const overallCoverage = allResults.length > 0
|
|
301
|
+
? (allResults.reduce((sum, r) => sum + r.coveragePercent, 0) / allResults.length).toFixed(2)
|
|
302
|
+
: '0.00';
|
|
303
|
+
const failedGates = qualityGate.failures.map((f) => f.category).join(',');
|
|
304
|
+
const summaryPath = path.join(reportsDir, 'build-summary.md');
|
|
305
|
+
core.setOutput('overallStatus', qualityGate.passed ? 'passed' : 'failed');
|
|
306
|
+
core.setOutput('overallCoverage', overallCoverage);
|
|
307
|
+
core.setOutput('failedGates', failedGates);
|
|
308
|
+
core.setOutput('summaryPath', summaryPath);
|
|
309
|
+
if (exitCode !== 0) {
|
|
310
|
+
const failureMessages = qualityGate.failures.map((f) => `${f.category}: expected ≥ ${f.expected}%, actual ${f.actual}%, gap ${f.gap}%`);
|
|
311
|
+
core.setFailed(`Coverage thresholds not met:\n${failureMessages.join('\n')}`);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
core.info('All coverage thresholds passed.');
|
|
315
|
+
}
|
|
316
|
+
// Post a PR comment with the coverage summary when running on a PR
|
|
317
|
+
if (postComment && (0, prComment_1.isPrContext)()) {
|
|
318
|
+
if (!githubToken) {
|
|
319
|
+
core.warning('post-pr-comment is enabled but github-token is empty. ' +
|
|
320
|
+
'Add `github-token: ${{ secrets.GITHUB_TOKEN }}` to your workflow step to enable PR comments.');
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
// Re-use the pr-summary.md that runAnalysisAndEnforceQualityGate already wrote
|
|
324
|
+
const prSummaryPath = path.join(reportsDir, 'pr-summary.md');
|
|
325
|
+
let commentBody;
|
|
326
|
+
if (fs.existsSync(prSummaryPath)) {
|
|
327
|
+
commentBody = fs.readFileSync(prSummaryPath, 'utf-8');
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// Fallback: generate an inline comment from the results we have
|
|
331
|
+
const { buildBuildMetadata } = await Promise.resolve().then(() => __importStar(require('../../src/publishing')));
|
|
332
|
+
const meta = buildBuildMetadata(allResults, qualityGate, {}, 'action', {});
|
|
333
|
+
commentBody = (0, buildSummary_1.generatePrComment)(allResults, qualityGate, meta, pagesUrl);
|
|
334
|
+
}
|
|
335
|
+
await (0, prComment_1.postPrComment)(githubToken, commentBody);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
core.info(`Reports written to: ${reportsDir}`);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
if (error instanceof Error) {
|
|
342
|
+
core.setFailed(error.message);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
core.setFailed(String(error));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
void run();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR comment helper for the API Test Coverage Analyzer action.
|
|
3
|
+
*
|
|
4
|
+
* Detects when the action is running in a pull-request context and either
|
|
5
|
+
* creates or updates a single "coverage report" comment, keeping the PR
|
|
6
|
+
* timeline clean. The comment is identified by a hidden sentinel marker so
|
|
7
|
+
* subsequent runs update the same comment instead of appending new ones.
|
|
8
|
+
*
|
|
9
|
+
* Public API:
|
|
10
|
+
* postPrComment(token, body)
|
|
11
|
+
* isPrContext()
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Return true when the current workflow run is triggered by a pull-request
|
|
15
|
+
* event and all required env vars are present.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isPrContext(): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Read the PR number from the GitHub event payload JSON file.
|
|
20
|
+
* Returns undefined when the file cannot be read or the number is absent.
|
|
21
|
+
*/
|
|
22
|
+
export declare function readPrNumber(): number | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Post or update a single PR comment containing `body`.
|
|
25
|
+
*
|
|
26
|
+
* If a previous coverage comment (identified by COMMENT_MARKER) already
|
|
27
|
+
* exists it is updated in place; otherwise a new comment is created.
|
|
28
|
+
* Requires a token with `pull-requests: write` permission.
|
|
29
|
+
*
|
|
30
|
+
* @param token GitHub token (e.g. `${{ secrets.GITHUB_TOKEN }}`).
|
|
31
|
+
* @param body Markdown body to post.
|
|
32
|
+
*/
|
|
33
|
+
export declare function postPrComment(token: string, body: string): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=prComment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prComment.d.ts","sourceRoot":"","sources":["../../../action/src/prComment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAQrC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAUjD;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD9E"}
|