@fabasoad/sarif-to-slack 0.2.4 → 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.
Files changed (193) hide show
  1. package/.github/workflows/release.yml +1 -1
  2. package/.github/workflows/security.yml +0 -1
  3. package/.github/workflows/send-sarif-to-slack.yml +148 -76
  4. package/.gitleaksignore +8 -0
  5. package/.pre-commit-config.yaml +3 -3
  6. package/.tool-versions +1 -1
  7. package/dist/Logger.js +4 -1
  8. package/dist/SarifToSlackClient.d.ts +33 -0
  9. package/dist/SarifToSlackClient.d.ts.map +1 -0
  10. package/dist/SarifToSlackClient.js +178 -0
  11. package/dist/SlackMessageBuilder.js +34 -82
  12. package/dist/System.d.ts +2 -0
  13. package/dist/System.d.ts.map +1 -0
  14. package/dist/System.js +15 -0
  15. package/dist/index.cjs +843 -467
  16. package/dist/index.d.ts +35 -12
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +36 -12
  19. package/dist/model/Color.d.ts +70 -0
  20. package/dist/model/Color.d.ts.map +1 -0
  21. package/dist/model/Color.js +119 -0
  22. package/dist/model/Finding.d.ts +2 -0
  23. package/dist/model/Finding.d.ts.map +1 -0
  24. package/dist/model/Finding.js +93 -0
  25. package/dist/model/FindingsArray.d.ts +2 -0
  26. package/dist/model/FindingsArray.d.ts.map +1 -0
  27. package/dist/model/FindingsArray.js +24 -0
  28. package/dist/processors/CodeQLProcessor.d.ts +2 -0
  29. package/dist/processors/CodeQLProcessor.d.ts.map +1 -0
  30. package/dist/processors/CodeQLProcessor.js +17 -0
  31. package/dist/processors/CommonProcessor.d.ts +2 -0
  32. package/dist/processors/CommonProcessor.d.ts.map +1 -0
  33. package/dist/processors/CommonProcessor.js +84 -0
  34. package/dist/processors/ProcessorFactory.d.ts +2 -0
  35. package/dist/processors/ProcessorFactory.d.ts.map +1 -0
  36. package/dist/processors/ProcessorFactory.js +22 -0
  37. package/dist/processors/SnykProcessor.d.ts +2 -0
  38. package/dist/processors/SnykProcessor.d.ts.map +1 -0
  39. package/dist/processors/SnykProcessor.js +18 -0
  40. package/dist/representations/CompactGroupByRepresentation.d.ts +2 -0
  41. package/dist/representations/CompactGroupByRepresentation.d.ts.map +1 -0
  42. package/dist/representations/CompactGroupByRepresentation.js +58 -0
  43. package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts +2 -0
  44. package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts.map +1 -0
  45. package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +13 -0
  46. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts +2 -0
  47. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts.map +1 -0
  48. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +13 -0
  49. package/dist/representations/CompactGroupByRunRepresentation.d.ts +2 -0
  50. package/dist/representations/CompactGroupByRunRepresentation.d.ts.map +1 -0
  51. package/dist/representations/CompactGroupByRunRepresentation.js +39 -0
  52. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts +2 -0
  53. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts.map +1 -0
  54. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +13 -0
  55. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts +2 -0
  56. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts.map +1 -0
  57. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +13 -0
  58. package/dist/representations/CompactGroupBySarifRepresentation.d.ts +2 -0
  59. package/dist/representations/CompactGroupBySarifRepresentation.d.ts.map +1 -0
  60. package/dist/representations/CompactGroupBySarifRepresentation.js +40 -0
  61. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts +2 -0
  62. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts.map +1 -0
  63. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +13 -0
  64. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts +2 -0
  65. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -0
  66. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +13 -0
  67. package/dist/representations/CompactGroupByToolNameRepresentation.d.ts +2 -0
  68. package/dist/representations/CompactGroupByToolNameRepresentation.d.ts.map +1 -0
  69. package/dist/representations/CompactGroupByToolNameRepresentation.js +39 -0
  70. package/dist/representations/CompactTotalPerLevelRepresentation.d.ts +2 -0
  71. package/dist/representations/CompactTotalPerLevelRepresentation.d.ts.map +1 -0
  72. package/dist/representations/CompactTotalPerLevelRepresentation.js +13 -0
  73. package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts +2 -0
  74. package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts.map +1 -0
  75. package/dist/representations/CompactTotalPerSeverityRepresentation.js +13 -0
  76. package/dist/representations/CompactTotalRepresentation.d.ts +2 -0
  77. package/dist/representations/CompactTotalRepresentation.d.ts.map +1 -0
  78. package/dist/representations/CompactTotalRepresentation.js +25 -0
  79. package/dist/representations/Representation.d.ts +2 -0
  80. package/dist/representations/Representation.d.ts.map +1 -0
  81. package/dist/representations/Representation.js +28 -0
  82. package/dist/representations/RepresentationFactory.d.ts +2 -0
  83. package/dist/representations/RepresentationFactory.d.ts.map +1 -0
  84. package/dist/representations/RepresentationFactory.js +37 -0
  85. package/dist/sarif-to-slack.d.ts +337 -85
  86. package/dist/tsdoc-metadata.json +1 -1
  87. package/dist/types.d.ts +215 -51
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/types.js +225 -33
  90. package/dist/utils/Comparators.d.ts +2 -0
  91. package/dist/utils/Comparators.d.ts.map +1 -0
  92. package/dist/utils/Comparators.js +18 -0
  93. package/dist/utils/ExtendedArray.d.ts +2 -0
  94. package/dist/utils/ExtendedArray.d.ts.map +1 -0
  95. package/dist/utils/ExtendedArray.js +11 -0
  96. package/dist/utils/FileUtils.d.ts +2 -0
  97. package/dist/utils/FileUtils.d.ts.map +1 -0
  98. package/dist/utils/FileUtils.js +51 -0
  99. package/dist/utils/SarifUtils.js +19 -53
  100. package/etc/sarif-to-slack.api.md +161 -99
  101. package/jest.config.json +2 -2
  102. package/package.json +9 -9
  103. package/scripts/save-metadata.sh +15 -0
  104. package/src/Logger.ts +4 -0
  105. package/src/SarifToSlackClient.ts +202 -0
  106. package/src/SlackMessageBuilder.ts +35 -115
  107. package/src/System.ts +16 -0
  108. package/src/index.ts +47 -20
  109. package/src/model/Color.ts +201 -0
  110. package/src/model/Finding.ts +137 -0
  111. package/src/model/FindingsArray.ts +27 -0
  112. package/src/processors/CodeQLProcessor.ts +19 -0
  113. package/src/processors/CommonProcessor.ts +103 -0
  114. package/src/processors/ProcessorFactory.ts +23 -0
  115. package/src/processors/SnykProcessor.ts +19 -0
  116. package/src/representations/CompactGroupByRepresentation.ts +67 -0
  117. package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +14 -0
  118. package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +14 -0
  119. package/src/representations/CompactGroupByRunRepresentation.ts +44 -0
  120. package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +15 -0
  121. package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +15 -0
  122. package/src/representations/CompactGroupBySarifRepresentation.ts +45 -0
  123. package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +15 -0
  124. package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +15 -0
  125. package/src/representations/CompactGroupByToolNameRepresentation.ts +44 -0
  126. package/src/representations/CompactTotalPerLevelRepresentation.ts +14 -0
  127. package/src/representations/CompactTotalPerSeverityRepresentation.ts +14 -0
  128. package/src/representations/CompactTotalRepresentation.ts +27 -0
  129. package/src/representations/Representation.ts +35 -0
  130. package/src/representations/RepresentationFactory.ts +49 -0
  131. package/src/types.ts +270 -53
  132. package/src/utils/Comparators.ts +19 -0
  133. package/src/utils/ExtendedArray.ts +11 -0
  134. package/src/utils/FileUtils.ts +60 -0
  135. package/src/utils/SarifUtils.ts +19 -71
  136. package/test-data/sarif/codeql-python.sarif +1448 -1
  137. package/test-data/sarif/codeql-typescript.sarif +3474 -1
  138. package/test-data/sarif/grype-github-actions.sarif +65 -0
  139. package/test-data/sarif/osv-scanner-composer.sarif +972 -0
  140. package/test-data/sarif/osv-scanner-container.sarif +2278 -0
  141. package/test-data/sarif/osv-scanner-gomodules.sarif +813 -0
  142. package/test-data/sarif/osv-scanner-hex.sarif +147 -0
  143. package/test-data/sarif/osv-scanner-maven.sarif +171 -0
  144. package/test-data/sarif/osv-scanner-npm.sarif +627 -0
  145. package/test-data/sarif/osv-scanner-pip.sarif +206 -0
  146. package/test-data/sarif/osv-scanner-pipenv.sarif +243 -0
  147. package/test-data/sarif/osv-scanner-pnpm.sarif +174 -0
  148. package/test-data/sarif/osv-scanner-poetry.sarif +1893 -0
  149. package/test-data/sarif/osv-scanner-rubygems.sarif +402 -0
  150. package/test-data/sarif/osv-scanner-uv.sarif +206 -0
  151. package/test-data/sarif/osv-scanner-yarn.sarif +5207 -0
  152. package/test-data/sarif/runs-0.sarif +5 -0
  153. package/test-data/sarif/runs-2-tools-2-results-0.sarif +1 -1
  154. package/test-data/sarif/runs-2-tools-2.sarif +1 -1
  155. package/test-data/sarif/runs-3-tools-2-results-0.sarif +1 -1
  156. package/test-data/sarif/runs-3-tools-2.sarif +1 -1
  157. package/test-data/sarif/tmp/codeql-csharp.sarif +1 -0
  158. package/test-data/sarif/tmp/grype-container.sarif +1774 -0
  159. package/test-data/sarif/tmp/runs-1-tools-1-results-0.sarif +18 -0
  160. package/test-data/sarif/tmp/runs-2-tools-2.sarif +686 -0
  161. package/test-data/sarif/trivy-iac.sarif +1 -1
  162. package/tests/integration/SendSarifToSlack.spec.ts +95 -27
  163. package/tsconfig.json +2 -0
  164. package/dist/Processors.d.ts +0 -2
  165. package/dist/Processors.d.ts.map +0 -1
  166. package/dist/Processors.js +0 -61
  167. package/dist/SarifToSlackService.d.ts +0 -39
  168. package/dist/SarifToSlackService.d.ts.map +0 -1
  169. package/dist/SarifToSlackService.js +0 -102
  170. package/dist/model/SarifModelPerRun.d.ts +0 -2
  171. package/dist/model/SarifModelPerRun.d.ts.map +0 -1
  172. package/dist/model/SarifModelPerRun.js +0 -90
  173. package/dist/model/SarifModelPerSarif.d.ts +0 -2
  174. package/dist/model/SarifModelPerSarif.d.ts.map +0 -1
  175. package/dist/model/SarifModelPerSarif.js +0 -102
  176. package/dist/model/types.d.ts +0 -2
  177. package/dist/model/types.d.ts.map +0 -1
  178. package/dist/model/types.js +0 -49
  179. package/dist/utils/SortUtils.d.ts +0 -2
  180. package/dist/utils/SortUtils.d.ts.map +0 -1
  181. package/dist/utils/SortUtils.js +0 -20
  182. package/dist/version.d.ts +0 -2
  183. package/dist/version.d.ts.map +0 -1
  184. package/dist/version.js +0 -11
  185. package/scripts/save-version.sh +0 -13
  186. package/src/Processors.ts +0 -68
  187. package/src/SarifToSlackService.ts +0 -115
  188. package/src/model/SarifModelPerRun.ts +0 -123
  189. package/src/model/SarifModelPerSarif.ts +0 -126
  190. package/src/model/types.ts +0 -50
  191. package/src/utils/SortUtils.ts +0 -33
  192. package/src/version.ts +0 -10
  193. package/tests/Processors.spec.ts +0 -76
@@ -1,49 +0,0 @@
1
- /**
2
- * Enum of security severity.
3
- * @internal
4
- */
5
- export var SecuritySeverity;
6
- (function (SecuritySeverity) {
7
- SecuritySeverity["Unknown"] = "Unknown";
8
- SecuritySeverity["None"] = "None";
9
- SecuritySeverity["Low"] = "Low";
10
- SecuritySeverity["Medium"] = "Medium";
11
- SecuritySeverity["High"] = "High";
12
- SecuritySeverity["Critical"] = "Critical";
13
- })(SecuritySeverity || (SecuritySeverity = {}));
14
- /**
15
- * Ordering of security severity values. It is used for sorting purposes, so that
16
- * Slack message shows issues in the correct order.
17
- * @internal
18
- */
19
- export const SecuritySeverityOrder = [
20
- SecuritySeverity.Critical,
21
- SecuritySeverity.High,
22
- SecuritySeverity.Medium,
23
- SecuritySeverity.Low,
24
- SecuritySeverity.None,
25
- SecuritySeverity.Unknown
26
- ];
27
- /**
28
- * Enum of security level.
29
- * @internal
30
- */
31
- export var SecurityLevel;
32
- (function (SecurityLevel) {
33
- SecurityLevel["Unknown"] = "Unknown";
34
- SecurityLevel["Note"] = "Note";
35
- SecurityLevel["Warning"] = "Warning";
36
- SecurityLevel["Error"] = "Error";
37
- })(SecurityLevel || (SecurityLevel = {}));
38
- /**
39
- * Ordering of security level values. It is used for sorting purposes, so that
40
- * Slack message shows issues in the correct order.
41
- * @internal
42
- */
43
- export const SecurityLevelOrder = [
44
- SecurityLevel.Error,
45
- SecurityLevel.Warning,
46
- SecurityLevel.Note,
47
- SecurityLevel.Unknown
48
- ];
49
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kZWwvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxDQUFOLElBQVksZ0JBT1g7QUFQRCxXQUFZLGdCQUFnQjtJQUMxQix1Q0FBbUIsQ0FBQTtJQUNuQixpQ0FBYSxDQUFBO0lBQ2IsK0JBQVcsQ0FBQTtJQUNYLHFDQUFpQixDQUFBO0lBQ2pCLGlDQUFhLENBQUE7SUFDYix5Q0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBUFcsZ0JBQWdCLEtBQWhCLGdCQUFnQixRQU8zQjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBdUI7SUFDdkQsZ0JBQWdCLENBQUMsUUFBUTtJQUN6QixnQkFBZ0IsQ0FBQyxJQUFJO0lBQ3JCLGdCQUFnQixDQUFDLE1BQU07SUFDdkIsZ0JBQWdCLENBQUMsR0FBRztJQUNwQixnQkFBZ0IsQ0FBQyxJQUFJO0lBQ3JCLGdCQUFnQixDQUFDLE9BQU87Q0FDekIsQ0FBQTtBQUVEOzs7R0FHRztBQUNILE1BQU0sQ0FBTixJQUFZLGFBS1g7QUFMRCxXQUFZLGFBQWE7SUFDdkIsb0NBQW1CLENBQUE7SUFDbkIsOEJBQWEsQ0FBQTtJQUNiLG9DQUFtQixDQUFBO0lBQ25CLGdDQUFlLENBQUE7QUFDakIsQ0FBQyxFQUxXLGFBQWEsS0FBYixhQUFhLFFBS3hCO0FBR0Q7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFvQjtJQUNqRCxhQUFhLENBQUMsS0FBSztJQUNuQixhQUFhLENBQUMsT0FBTztJQUNyQixhQUFhLENBQUMsSUFBSTtJQUNsQixhQUFhLENBQUMsT0FBTztDQUN0QixDQUFBIn0=
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=SortUtils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SortUtils.d.ts","sourceRoot":"","sources":["../../src/utils/SortUtils.ts"],"names":[],"mappings":""}
@@ -1,20 +0,0 @@
1
- import { SecurityLevelOrder, SecuritySeverityOrder } from '../model/types';
2
- /**
3
- * This function sorts the given map by security level.
4
- * See {@link SecurityLevelOrder}.
5
- * @param map A map that you need to sort.
6
- * @internal
7
- */
8
- export function sortSecurityLevelMap(map) {
9
- return map.sortBy((_, level) => level, (a, b) => SecurityLevelOrder.indexOf(a) - SecurityLevelOrder.indexOf(b)).asImmutable();
10
- }
11
- /**
12
- * This function sorts the given map by security severity.
13
- * See {@link SecuritySeverityOrder}.
14
- * @param map A map that you need to sort.
15
- * @internal
16
- */
17
- export function sortSecuritySeverityMap(map) {
18
- return map.sortBy((_, severity) => severity, (a, b) => SecuritySeverityOrder.indexOf(a) - SecuritySeverityOrder.indexOf(b)).asImmutable();
19
- }
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU29ydFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL1NvcnRVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBRUwsa0JBQWtCLEVBRWxCLHFCQUFxQixFQUN0QixNQUFNLGdCQUFnQixDQUFBO0FBRXZCOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEdBQXdDO0lBQzNFLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FDZixDQUFDLENBQVMsRUFBRSxLQUFvQixFQUFpQixFQUFFLENBQUMsS0FBSyxFQUN6RCxDQUFDLENBQWdCLEVBQUUsQ0FBZ0IsRUFBVSxFQUFFLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FDOUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtBQUNqQixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQUMsR0FBMkM7SUFDakYsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUNmLENBQUMsQ0FBUyxFQUFFLFFBQTBCLEVBQW9CLEVBQUUsQ0FBQyxRQUFRLEVBQ3JFLENBQUMsQ0FBbUIsRUFBRSxDQUFtQixFQUFVLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUMxSCxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ2pCLENBQUMifQ==
package/dist/version.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=version.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":""}
package/dist/version.js DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * This value is used for the default footer in Slack message.
3
- *
4
- * @privateRemarks
5
- * This file is autogenerated by scripts/save-version.sh
6
- * Do not edit it manually!
7
- *
8
- * @internal
9
- */
10
- export const LIB_VERSION = '0.2.4';
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQSJ9
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env sh
2
-
3
- version=$(jq -r '.version' package.json)
4
- echo "/**" > src/version.ts
5
- echo " * This value is used for the default footer in Slack message." >> src/version.ts
6
- echo " *" >> src/version.ts
7
- echo " * @privateRemarks" >> src/version.ts
8
- echo " * This file is autogenerated by scripts/save-version.sh" >> src/version.ts
9
- echo " * Do not edit it manually!" >> src/version.ts
10
- echo " *" >> src/version.ts
11
- echo " * @internal" >> src/version.ts
12
- echo " */" >> src/version.ts
13
- echo "export const LIB_VERSION = '${version}'" >> src/version.ts
package/src/Processors.ts DELETED
@@ -1,68 +0,0 @@
1
- import * as fs from 'fs'
2
- import * as path from 'path'
3
- import Logger from './Logger'
4
-
5
- /**
6
- * Processes a color string and converts it to a specific hex code if it matches
7
- * a CI status identifier.
8
- * @param color - The color string to process, which can be a CI status identifier
9
- * or a custom color.
10
- * @returns The processed color as a hex string or undefined if the input is not
11
- * a recognized CI status identifier.
12
- * @internal
13
- */
14
- export function processColor(color?: string): string | undefined {
15
- switch (color) {
16
- case 'success':
17
- Logger.info(`Converting "${color}" to #008000`)
18
- return '#008000'
19
- case 'failure':
20
- Logger.info(`Converting "${color}" to #ff0000`)
21
- return '#ff0000'
22
- case 'cancelled':
23
- Logger.info(`Converting "${color}" to #0047ab`)
24
- return '#0047ab'
25
- case 'skipped':
26
- Logger.info(`Converting "${color}" to #808080`)
27
- return '#808080'
28
- default:
29
- Logger.debug(`"${color}" color is not a CI status identifier. Returning as is.`)
30
- return color
31
- }
32
- }
33
-
34
- /**
35
- * Processes the SARIF path, which can be a file or a directory. If it's a
36
- * directory, it returns an array of paths to all `.sarif` files, otherwise it
37
- * returns an array with a single path to the file.
38
- * @param sarifPath - The path to the SARIF file or directory.
39
- * @returns An array of strings representing the paths to the SARIF files.
40
- * @throws Error If the path does not exist, or if it is neither a file nor a
41
- * directory.
42
- * @internal
43
- */
44
- export function processSarifPath(sarifPath: string): string[] {
45
- if (!fs.existsSync(sarifPath)) {
46
- throw new Error(`"sarif-path" does not exist: ${sarifPath}`)
47
- }
48
-
49
- const sarifStats: fs.Stats = fs.statSync(sarifPath)
50
-
51
- if (sarifStats.isDirectory()) {
52
- Logger.info(`"sarif-path" is a directory: ${sarifPath}`)
53
- const files: string[] = fs.readdirSync(sarifPath)
54
- const filteredFiles: string[] = files.filter((file: string) =>
55
- path.extname(file).toLowerCase() === '.sarif'
56
- )
57
- Logger.info(`Found ${filteredFiles.length} SARIF files in ${sarifPath} directory`)
58
- Logger.debug(`Filtered SARIF files: ${filteredFiles.join(', ')}`)
59
- return filteredFiles.map((file: string) => path.join(sarifPath, file))
60
- }
61
-
62
- if (sarifStats.isFile()) {
63
- Logger.info(`"sarif-path" is a file: ${sarifPath}`)
64
- return [sarifPath]
65
- }
66
-
67
- throw new Error(`"sarif-path" is neither a file nor a directory: ${sarifPath}`)
68
- }
@@ -1,115 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import Logger from './Logger'
3
- import { processColor, processSarifPath } from './Processors'
4
- import { SlackMessageBuilder } from './SlackMessageBuilder'
5
- import {
6
- SarifLog,
7
- SarifToSlackServiceOptions,
8
- SlackMessage
9
- } from './types'
10
-
11
- /**
12
- * The main function to initialize a list of {@link SlackMessage} objects based
13
- * on the given SARIF file(s).
14
- * @param opts An instance of {@link SarifToSlackServiceOptions} object.
15
- * @returns A map where key is the SARIF file and value is an instance of
16
- * {@link SlackMessage} object
17
- * @private
18
- */
19
- async function initialize(opts: SarifToSlackServiceOptions): Promise<Map<string, SlackMessage>> {
20
- const slackMessages = new Map<string, SlackMessage>();
21
- const sarifFiles: string[] = processSarifPath(opts.sarifPath)
22
- if (sarifFiles.length === 0) {
23
- throw new Error(`No SARIF files found at the provided path: ${opts.sarifPath}`)
24
- }
25
-
26
- for (const sarifFile of sarifFiles) {
27
- const jsonString: string = await fs.readFile(sarifFile, 'utf8')
28
-
29
- const messageBuilder = new SlackMessageBuilder(opts.webhookUrl, {
30
- username: opts.username,
31
- iconUrl: opts.iconUrl,
32
- color: processColor(opts.color),
33
- sarif: JSON.parse(jsonString) as SarifLog,
34
- output: opts.output,
35
- })
36
- if (opts.header?.include) {
37
- messageBuilder.withHeader(opts.header?.value)
38
- }
39
- if (opts.footer?.include) {
40
- messageBuilder.withFooter(opts.footer?.value, opts.footer?.type)
41
- }
42
- if (opts.actor?.include) {
43
- messageBuilder.withActor(opts.actor?.value)
44
- }
45
- if (opts.run?.include) {
46
- messageBuilder.withRun()
47
- }
48
- slackMessages.set(sarifFile, messageBuilder)
49
- }
50
- return slackMessages;
51
- }
52
-
53
- /**
54
- * Service to convert SARIF files to Slack messages and send them.
55
- * @public
56
- */
57
- export class SarifToSlackService {
58
- private readonly _slackMessages: Map<string, SlackMessage>;
59
-
60
- private constructor() {
61
- this._slackMessages = new Map<string, SlackMessage>();
62
- }
63
-
64
- /**
65
- * Gets the Slack messages prepared for each SARIF file.
66
- * @returns A read-only map where keys are SARIF file paths and values are SlackMessage instances.
67
- * @public
68
- */
69
- public get slackMessages(): ReadonlyMap<string, SlackMessage> {
70
- return this._slackMessages;
71
- }
72
-
73
- /**
74
- * Creates an instance of SarifToSlackService.
75
- * @param opts - Options for the service, including webhook URL, SARIF path, and other configurations.
76
- * @returns A promise that resolves to an instance of SarifToSlackService.
77
- * @throws Error if no SARIF files are found at the provided path.
78
- * @public
79
- */
80
- public static async create(opts: SarifToSlackServiceOptions): Promise<SarifToSlackService> {
81
- Logger.initialize(opts.log)
82
- const instance: SarifToSlackService = new SarifToSlackService()
83
- const map: Map<string, SlackMessage> = await initialize(opts)
84
- map.forEach((val: SlackMessage, key: string) => instance._slackMessages.set(key, val))
85
- return instance
86
- }
87
-
88
- /**
89
- * Sends all prepared Slack messages.
90
- * @returns A promise that resolves when all messages have been sent.
91
- * @throws Error if a Slack message was not prepared for a SARIF path.
92
- * @public
93
- */
94
- public async sendAll(): Promise<void> {
95
- for (const sarifPath of this._slackMessages.keys()) {
96
- await this.send(sarifPath);
97
- }
98
- }
99
-
100
- /**
101
- * Sends a Slack message for a specific SARIF path.
102
- * @param sarifPath - The path of the SARIF file for which the message should be sent.
103
- * @returns A promise that resolves when the message has been sent.
104
- * @throws Error if a Slack message was not prepared for the given SARIF path.
105
- * @public
106
- */
107
- public async send(sarifPath: string): Promise<void> {
108
- const message: SlackMessage | undefined = this._slackMessages.get(sarifPath)
109
- if (!message) {
110
- throw new Error(`Slack message was not prepared for SARIF path: ${sarifPath}.`)
111
- }
112
- const text: string = await message.send()
113
- Logger.info(`Message sent for ${sarifPath} file. Status:`, text)
114
- }
115
- }
@@ -1,123 +0,0 @@
1
- import type { Result, Run } from 'sarif';
2
- import {
3
- findToolComponentByResult,
4
- tryGetRulePropertyByResult
5
- } from '../utils/SarifUtils'
6
- import { SecurityLevel, SecuritySeverity } from './types'
7
- import Logger from '../Logger'
8
- import { Map as ImmutableMap } from 'immutable'
9
- import {
10
- sortSecurityLevelMap,
11
- sortSecuritySeverityMap
12
- } from '../utils/SortUtils';
13
-
14
- /**
15
- * This class keeps information about results per run. It has 2 hash maps:
16
- * - severity to number: the amount of results for each severity
17
- * - level to number: the amount of results for each level
18
- * @internal
19
- */
20
- export class SarifModelPerRun {
21
- public readonly toolName: string
22
-
23
- private readonly _securitySeverityMap: ImmutableMap<SecuritySeverity, number>
24
- private readonly _securityLevelMap: ImmutableMap<SecurityLevel, number>
25
-
26
- constructor(run: Run) {
27
- this.toolName = findToolComponentByResult(run, run.results?.[0]).name
28
-
29
- this._securitySeverityMap = ImmutableMap<SecuritySeverity, number>().asMutable()
30
- this._securityLevelMap = ImmutableMap<SecurityLevel, number>().asMutable()
31
-
32
- this.buildSecuritySeverityMap(run)
33
- this.buildSecurityLevelMap(run)
34
- }
35
-
36
- private identifySecuritySeverity(score?: number): SecuritySeverity {
37
- if (score === undefined) {
38
- return SecuritySeverity.Unknown
39
- }
40
-
41
- if (score >= 9 && score <= 10) {
42
- return SecuritySeverity.Critical
43
- }
44
-
45
- if (score >= 7) {
46
- return SecuritySeverity.High
47
- }
48
-
49
- if (score >= 4) {
50
- return SecuritySeverity.Medium
51
- }
52
-
53
- if (score >= 0.1) {
54
- return SecuritySeverity.Low
55
- }
56
-
57
- if (score == 0) {
58
- return SecuritySeverity.None
59
- }
60
-
61
- Logger.warn(`Unsupported "${score}" security severity. Saving as "Unknown".`)
62
- return SecuritySeverity.Unknown
63
- }
64
-
65
- private identifySecurityLevel(level?: string): SecurityLevel {
66
- if (level === undefined) {
67
- return SecurityLevel.Unknown
68
- }
69
-
70
- if (level.toLowerCase() === 'error') {
71
- return SecurityLevel.Error
72
- }
73
-
74
- if (level.toLowerCase() === 'warning') {
75
- return SecurityLevel.Warning
76
- }
77
-
78
- if (level.toLowerCase() === 'note') {
79
- return SecurityLevel.Note
80
- }
81
-
82
- Logger.warn(`Unsupported ${level} security level. Saving as "Unknown".`)
83
- return SecurityLevel.Unknown
84
- }
85
-
86
- private buildSecuritySeverityMap(run: Run): void {
87
- const results: Result[] = run.results ?? []
88
- for (const result of results) {
89
- const severity: SecuritySeverity = this.identifySecuritySeverity(
90
- tryGetRulePropertyByResult(run, result, 'security-severity')
91
- )
92
- const count: number = this._securitySeverityMap.get(severity) || 0
93
- this._securitySeverityMap.set(severity, count + 1)
94
- }
95
- }
96
-
97
- private tryGetSecurityLevel(run: Run, result: Result): string | undefined {
98
- if (result.level) {
99
- return result.level
100
- }
101
-
102
- return tryGetRulePropertyByResult(run, result, 'problem.severity')
103
- }
104
-
105
- private buildSecurityLevelMap(run: Run): void {
106
- const results: Result[] = run.results ?? []
107
- for (const result of results) {
108
- const level: SecurityLevel = this.identifySecurityLevel(
109
- this.tryGetSecurityLevel(run, result)
110
- )
111
- const count: number = this._securityLevelMap.get(level) || 0
112
- this._securityLevelMap.set(level, count + 1)
113
- }
114
- }
115
-
116
- public get securitySeverityMap(): ImmutableMap<SecuritySeverity, number> {
117
- return sortSecuritySeverityMap(this._securitySeverityMap)
118
- }
119
-
120
- public get securityLevelMap(): ImmutableMap<SecurityLevel, number> {
121
- return sortSecurityLevelMap(this._securityLevelMap)
122
- }
123
- }
@@ -1,126 +0,0 @@
1
- import type { SarifLog } from '../types'
2
- import { Map as ImmutableMap } from 'immutable'
3
- import { SarifModelPerRun } from './SarifModelPerRun'
4
- import { SecurityLevel, SecuritySeverity } from './types'
5
- import {
6
- sortSecurityLevelMap,
7
- sortSecuritySeverityMap
8
- } from '../utils/SortUtils';
9
-
10
- /**
11
- * A data type that has a hash map with the amount of <severity|level> results
12
- * and tool name.
13
- * @internal
14
- */
15
- export type DataGroupedByRun<T> = {
16
- toolName: string,
17
- data: ImmutableMap<T, number>
18
- }
19
-
20
- /**
21
- * This class is used to group results by different fields, such as grouping by
22
- * tool name, runs, etc.
23
- * @internal
24
- */
25
- export class SarifModelPerSarif {
26
- private readonly sarifModelPerRunList: Array<SarifModelPerRun>;
27
-
28
- constructor(sarif: SarifLog) {
29
- this.sarifModelPerRunList = new Array<SarifModelPerRun>()
30
- this.buildRunsList(sarif)
31
- }
32
-
33
- private buildRunsList(sarif: SarifLog): void {
34
- for (const run of sarif.runs) {
35
- this.sarifModelPerRunList.push(new SarifModelPerRun(run))
36
- }
37
- }
38
-
39
- public groupByToolNameWithSecurityLevel(): Map<string, ImmutableMap<SecurityLevel, number>> {
40
- const result = new Map<string, ImmutableMap<SecurityLevel, number>>()
41
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
42
- if (!result.has(sarifModelPerRun.toolName)) {
43
- result.set(sarifModelPerRun.toolName, ImmutableMap<SecurityLevel, number>().asMutable())
44
- }
45
- for (const [k, v] of sarifModelPerRun.securityLevelMap.entries()) {
46
- const count: number = result.get(sarifModelPerRun.toolName)?.get(k) || 0
47
- result.get(sarifModelPerRun.toolName)?.set(k, count + v)
48
- }
49
- }
50
- // Sort
51
- for (const [k, v] of result) {
52
- result.set(k, sortSecurityLevelMap(v))
53
- }
54
- return result
55
- }
56
-
57
- public groupByRunWithSecurityLevel(): DataGroupedByRun<SecurityLevel>[] {
58
- const result = new Array<DataGroupedByRun<SecurityLevel>>()
59
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
60
- result.push({
61
- toolName: sarifModelPerRun.toolName,
62
- data: sarifModelPerRun.securityLevelMap,
63
- })
64
- }
65
- return result
66
- }
67
-
68
- public groupByTotalWithSecurityLevel(): ImmutableMap<SecurityLevel, number> {
69
- const result = ImmutableMap<SecurityLevel, number>().asMutable()
70
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
71
- for (const [k, v] of sarifModelPerRun.securityLevelMap.entries()) {
72
- const count: number = result.get(k) || 0
73
- result.set(k, count + v)
74
- }
75
- }
76
- return sortSecurityLevelMap(result)
77
- }
78
-
79
- public groupByToolNameWithSecuritySeverity(): Map<string, ImmutableMap<SecuritySeverity, number>> {
80
- const result = new Map<string, ImmutableMap<SecuritySeverity, number>>()
81
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
82
- if (!result.has(sarifModelPerRun.toolName)) {
83
- result.set(sarifModelPerRun.toolName, ImmutableMap<SecuritySeverity, number>().asMutable())
84
- }
85
- for (const [k, v] of sarifModelPerRun.securitySeverityMap.entries()) {
86
- const count: number = result.get(sarifModelPerRun.toolName)?.get(k) || 0
87
- result.get(sarifModelPerRun.toolName)?.set(k, count + v)
88
- }
89
- }
90
- // Sort
91
- for (const [k, v] of result.entries()) {
92
- result.set(k, sortSecuritySeverityMap(v))
93
- }
94
- return result
95
- }
96
-
97
- public groupByRunWithSecuritySeverity(): DataGroupedByRun<SecuritySeverity>[] {
98
- const result = new Array<DataGroupedByRun<SecuritySeverity>>()
99
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
100
- result.push({
101
- toolName: sarifModelPerRun.toolName,
102
- data: sarifModelPerRun.securitySeverityMap,
103
- })
104
- }
105
- return result
106
- }
107
-
108
- public groupByTotalWithSecuritySeverity(): ImmutableMap<SecuritySeverity, number> {
109
- const result = ImmutableMap<SecuritySeverity, number>().asMutable()
110
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
111
- for (const [k, v] of sarifModelPerRun.securitySeverityMap.entries()) {
112
- const count: number = result.get(k) || 0
113
- result.set(k, count + v)
114
- }
115
- }
116
- return sortSecuritySeverityMap(result)
117
- }
118
-
119
- public listToolNames(): Set<string> {
120
- const toolNames = new Set<string>()
121
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
122
- toolNames.add(sarifModelPerRun.toolName)
123
- }
124
- return toolNames
125
- }
126
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * Enum of security severity.
3
- * @internal
4
- */
5
- export enum SecuritySeverity {
6
- Unknown = 'Unknown',
7
- None = 'None',
8
- Low = 'Low',
9
- Medium = 'Medium',
10
- High = 'High',
11
- Critical = 'Critical'
12
- }
13
-
14
- /**
15
- * Ordering of security severity values. It is used for sorting purposes, so that
16
- * Slack message shows issues in the correct order.
17
- * @internal
18
- */
19
- export const SecuritySeverityOrder: SecuritySeverity[] = [
20
- SecuritySeverity.Critical,
21
- SecuritySeverity.High,
22
- SecuritySeverity.Medium,
23
- SecuritySeverity.Low,
24
- SecuritySeverity.None,
25
- SecuritySeverity.Unknown
26
- ]
27
-
28
- /**
29
- * Enum of security level.
30
- * @internal
31
- */
32
- export enum SecurityLevel {
33
- Unknown = 'Unknown',
34
- Note = 'Note',
35
- Warning = 'Warning',
36
- Error = 'Error'
37
- }
38
-
39
-
40
- /**
41
- * Ordering of security level values. It is used for sorting purposes, so that
42
- * Slack message shows issues in the correct order.
43
- * @internal
44
- */
45
- export const SecurityLevelOrder: SecurityLevel[] = [
46
- SecurityLevel.Error,
47
- SecurityLevel.Warning,
48
- SecurityLevel.Note,
49
- SecurityLevel.Unknown
50
- ]
@@ -1,33 +0,0 @@
1
- import { Map as ImmutableMap } from 'immutable'
2
- import {
3
- SecurityLevel,
4
- SecurityLevelOrder,
5
- SecuritySeverity,
6
- SecuritySeverityOrder
7
- } from '../model/types'
8
-
9
- /**
10
- * This function sorts the given map by security level.
11
- * See {@link SecurityLevelOrder}.
12
- * @param map A map that you need to sort.
13
- * @internal
14
- */
15
- export function sortSecurityLevelMap(map: ImmutableMap<SecurityLevel, number>): ImmutableMap<SecurityLevel, number> {
16
- return map.sortBy(
17
- (_: number, level: SecurityLevel): SecurityLevel => level,
18
- (a: SecurityLevel, b: SecurityLevel): number => SecurityLevelOrder.indexOf(a) - SecurityLevelOrder.indexOf(b),
19
- ).asImmutable()
20
- }
21
-
22
- /**
23
- * This function sorts the given map by security severity.
24
- * See {@link SecuritySeverityOrder}.
25
- * @param map A map that you need to sort.
26
- * @internal
27
- */
28
- export function sortSecuritySeverityMap(map: ImmutableMap<SecuritySeverity, number>): ImmutableMap<SecuritySeverity, number> {
29
- return map.sortBy(
30
- (_: number, severity: SecuritySeverity): SecuritySeverity => severity,
31
- (a: SecuritySeverity, b: SecuritySeverity): number => SecuritySeverityOrder.indexOf(a) - SecuritySeverityOrder.indexOf(b),
32
- ).asImmutable()
33
- }
package/src/version.ts DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * This value is used for the default footer in Slack message.
3
- *
4
- * @privateRemarks
5
- * This file is autogenerated by scripts/save-version.sh
6
- * Do not edit it manually!
7
- *
8
- * @internal
9
- */
10
- export const LIB_VERSION = '0.2.4'