lintro 0.6.2__tar.gz → 0.7.0__tar.gz

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.

Potentially problematic release.


This version of lintro might be problematic. Click here for more details.

Files changed (199) hide show
  1. {lintro-0.6.2/lintro.egg-info → lintro-0.7.0}/PKG-INFO +46 -8
  2. {lintro-0.6.2 → lintro-0.7.0}/README.md +39 -1
  3. {lintro-0.6.2 → lintro-0.7.0}/assets/images/coverage-badge.svg +3 -3
  4. {lintro-0.6.2 → lintro-0.7.0}/docs/README.md +5 -4
  5. {lintro-0.6.2 → lintro-0.7.0}/docs/contributing.md +13 -0
  6. lintro-0.7.0/docs/security/assurance.md +79 -0
  7. lintro-0.7.0/docs/security/requirements.md +42 -0
  8. {lintro-0.6.2 → lintro-0.7.0}/lintro/__init__.py +1 -1
  9. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_prettier.py +7 -1
  10. {lintro-0.6.2 → lintro-0.7.0/lintro.egg-info}/PKG-INFO +46 -8
  11. {lintro-0.6.2 → lintro-0.7.0}/lintro.egg-info/SOURCES.txt +4 -0
  12. {lintro-0.6.2 → lintro-0.7.0}/lintro.egg-info/requires.txt +6 -6
  13. {lintro-0.6.2 → lintro-0.7.0}/pyproject.toml +4 -4
  14. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_prettier_integration.py +32 -0
  15. lintro-0.7.0/tests/scripts/test_ci_post_pr_comment.py +336 -0
  16. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_ghcr_prune_untagged.py +2 -2
  17. lintro-0.7.0/tests/scripts/test_github_comment_utilities.py +435 -0
  18. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_script_environment.py +263 -1
  19. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_shell_scripts.py +76 -2
  20. {lintro-0.6.2 → lintro-0.7.0}/tests/test_documentation.py +1 -1
  21. {lintro-0.6.2 → lintro-0.7.0}/LICENSE +0 -0
  22. {lintro-0.6.2 → lintro-0.7.0}/MANIFEST.in +0 -0
  23. {lintro-0.6.2 → lintro-0.7.0}/assets/images/lintro.png +0 -0
  24. {lintro-0.6.2 → lintro-0.7.0}/docs/configuration.md +0 -0
  25. {lintro-0.6.2 → lintro-0.7.0}/docs/coverage-setup.md +0 -0
  26. {lintro-0.6.2 → lintro-0.7.0}/docs/docker.md +0 -0
  27. {lintro-0.6.2 → lintro-0.7.0}/docs/getting-started.md +0 -0
  28. {lintro-0.6.2 → lintro-0.7.0}/docs/github-integration.md +0 -0
  29. {lintro-0.6.2 → lintro-0.7.0}/docs/lintro-self-use.md +0 -0
  30. {lintro-0.6.2 → lintro-0.7.0}/docs/style-guide.md +0 -0
  31. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/README.md +0 -0
  32. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/actionlint-analysis.md +0 -0
  33. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/bandit-analysis.md +0 -0
  34. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/black-analysis.md +0 -0
  35. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/darglint-analysis.md +0 -0
  36. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/hadolint-analysis.md +0 -0
  37. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/prettier-analysis.md +0 -0
  38. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/ruff-analysis.md +0 -0
  39. {lintro-0.6.2 → lintro-0.7.0}/docs/tool-analysis/yamllint-analysis.md +0 -0
  40. {lintro-0.6.2 → lintro-0.7.0}/lintro/__main__.py +0 -0
  41. {lintro-0.6.2 → lintro-0.7.0}/lintro/ascii-art/fail.txt +0 -0
  42. {lintro-0.6.2 → lintro-0.7.0}/lintro/ascii-art/success.txt +0 -0
  43. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli.py +0 -0
  44. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli_utils/__init__.py +0 -0
  45. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli_utils/commands/__init__.py +0 -0
  46. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli_utils/commands/check.py +0 -0
  47. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli_utils/commands/format.py +0 -0
  48. {lintro-0.6.2 → lintro-0.7.0}/lintro/cli_utils/commands/list_tools.py +0 -0
  49. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/__init__.py +0 -0
  50. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/action.py +0 -0
  51. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/darglint_strictness.py +0 -0
  52. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/group_by.py +0 -0
  53. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/hadolint_enums.py +0 -0
  54. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/output_format.py +0 -0
  55. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/tool_name.py +0 -0
  56. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/tool_type.py +0 -0
  57. {lintro-0.6.2 → lintro-0.7.0}/lintro/enums/yamllint_format.py +0 -0
  58. {lintro-0.6.2 → lintro-0.7.0}/lintro/exceptions/__init__.py +0 -0
  59. {lintro-0.6.2 → lintro-0.7.0}/lintro/exceptions/errors.py +0 -0
  60. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/__init__.py +0 -0
  61. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/core/__init__.py +0 -0
  62. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/core/output_style.py +0 -0
  63. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/core/table_descriptor.py +0 -0
  64. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/__init__.py +0 -0
  65. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/csv.py +0 -0
  66. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/grid.py +0 -0
  67. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/html.py +0 -0
  68. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/json.py +0 -0
  69. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/markdown.py +0 -0
  70. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/styles/plain.py +0 -0
  71. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/__init__.py +0 -0
  72. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/actionlint_formatter.py +0 -0
  73. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/bandit_formatter.py +0 -0
  74. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/black_formatter.py +0 -0
  75. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/darglint_formatter.py +0 -0
  76. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/hadolint_formatter.py +0 -0
  77. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/prettier_formatter.py +0 -0
  78. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/ruff_formatter.py +0 -0
  79. {lintro-0.6.2 → lintro-0.7.0}/lintro/formatters/tools/yamllint_formatter.py +0 -0
  80. {lintro-0.6.2 → lintro-0.7.0}/lintro/models/__init__.py +0 -0
  81. {lintro-0.6.2 → lintro-0.7.0}/lintro/models/core/__init__.py +0 -0
  82. {lintro-0.6.2 → lintro-0.7.0}/lintro/models/core/tool.py +0 -0
  83. {lintro-0.6.2 → lintro-0.7.0}/lintro/models/core/tool_config.py +0 -0
  84. {lintro-0.6.2 → lintro-0.7.0}/lintro/models/core/tool_result.py +0 -0
  85. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/__init__.py +0 -0
  86. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/actionlint/__init__.py +0 -0
  87. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/actionlint/actionlint_issue.py +0 -0
  88. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/actionlint/actionlint_parser.py +0 -0
  89. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/black/black_issue.py +0 -0
  90. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/black/black_parser.py +0 -0
  91. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/darglint/__init__.py +0 -0
  92. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/darglint/darglint_issue.py +0 -0
  93. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/darglint/darglint_parser.py +0 -0
  94. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/hadolint/__init__.py +0 -0
  95. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/hadolint/hadolint_issue.py +0 -0
  96. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/hadolint/hadolint_parser.py +0 -0
  97. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/prettier/__init__.py +0 -0
  98. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/prettier/prettier_issue.py +0 -0
  99. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/prettier/prettier_parser.py +0 -0
  100. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/ruff/__init__.py +0 -0
  101. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/ruff/ruff_issue.py +0 -0
  102. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/ruff/ruff_parser.py +0 -0
  103. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/yamllint/__init__.py +0 -0
  104. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/yamllint/yamllint_issue.py +0 -0
  105. {lintro-0.6.2 → lintro-0.7.0}/lintro/parsers/yamllint/yamllint_parser.py +0 -0
  106. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/__init__.py +0 -0
  107. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/core/__init__.py +0 -0
  108. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/core/tool_base.py +0 -0
  109. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/core/tool_manager.py +0 -0
  110. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/__init__.py +0 -0
  111. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_actionlint.py +0 -0
  112. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_bandit.py +0 -0
  113. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_black.py +0 -0
  114. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_darglint.py +0 -0
  115. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_hadolint.py +0 -0
  116. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_ruff.py +0 -0
  117. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/implementations/tool_yamllint.py +0 -0
  118. {lintro-0.6.2 → lintro-0.7.0}/lintro/tools/tool_enum.py +0 -0
  119. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/__init__.py +0 -0
  120. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/ascii_normalize_cli.py +0 -0
  121. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/config.py +0 -0
  122. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/console_logger.py +0 -0
  123. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/formatting.py +0 -0
  124. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/output_manager.py +0 -0
  125. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/path_utils.py +0 -0
  126. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/tool_executor.py +0 -0
  127. {lintro-0.6.2 → lintro-0.7.0}/lintro/utils/tool_utils.py +0 -0
  128. {lintro-0.6.2 → lintro-0.7.0}/lintro.egg-info/dependency_links.txt +0 -0
  129. {lintro-0.6.2 → lintro-0.7.0}/lintro.egg-info/entry_points.txt +0 -0
  130. {lintro-0.6.2 → lintro-0.7.0}/lintro.egg-info/top_level.txt +0 -0
  131. {lintro-0.6.2 → lintro-0.7.0}/setup.cfg +0 -0
  132. {lintro-0.6.2 → lintro-0.7.0}/test_samples/Dockerfile.violations +0 -0
  133. {lintro-0.6.2 → lintro-0.7.0}/test_samples/actionlint_violations.yml +0 -0
  134. {lintro-0.6.2 → lintro-0.7.0}/test_samples/bandit_violations.py +0 -0
  135. {lintro-0.6.2 → lintro-0.7.0}/test_samples/darglint_violations.py +0 -0
  136. {lintro-0.6.2 → lintro-0.7.0}/test_samples/prettier_violations.js +0 -0
  137. {lintro-0.6.2 → lintro-0.7.0}/test_samples/ruff_black_e501_wrappable.py +0 -0
  138. {lintro-0.6.2 → lintro-0.7.0}/test_samples/ruff_clean.py +0 -0
  139. {lintro-0.6.2 → lintro-0.7.0}/test_samples/ruff_violations.py +0 -0
  140. {lintro-0.6.2 → lintro-0.7.0}/test_samples/yaml_violations.yml +0 -0
  141. {lintro-0.6.2 → lintro-0.7.0}/tests/__init__.py +0 -0
  142. {lintro-0.6.2 → lintro-0.7.0}/tests/cli/__init__.py +0 -0
  143. {lintro-0.6.2 → lintro-0.7.0}/tests/cli/conftest.py +0 -0
  144. {lintro-0.6.2 → lintro-0.7.0}/tests/cli/test_cli.py +0 -0
  145. {lintro-0.6.2 → lintro-0.7.0}/tests/conftest.py +0 -0
  146. {lintro-0.6.2 → lintro-0.7.0}/tests/formatters/__init__.py +0 -0
  147. {lintro-0.6.2 → lintro-0.7.0}/tests/formatters/conftest.py +0 -0
  148. {lintro-0.6.2 → lintro-0.7.0}/tests/formatters/test_formatters.py +0 -0
  149. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/__init__.py +0 -0
  150. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/conftest.py +0 -0
  151. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_actionlint_integration.py +0 -0
  152. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_bandit_integration.py +0 -0
  153. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_darglint_integration.py +0 -0
  154. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_hadolint_integration.py +0 -0
  155. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_ruff_black_policy.py +0 -0
  156. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_ruff_integration.py +0 -0
  157. {lintro-0.6.2 → lintro-0.7.0}/tests/integration/test_yamllint_integration.py +0 -0
  158. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/__init__.py +0 -0
  159. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_delete_previous_lintro_comments.py +0 -0
  160. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_extract_version.py +0 -0
  161. {lintro-0.6.2 → lintro-0.7.0}/tests/scripts/test_semantic_release_compute_next.py +0 -0
  162. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/__init__.py +0 -0
  163. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_ascii_normalize.py +0 -0
  164. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_bandit_command_building.py +0 -0
  165. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_bandit_config_hydration.py +0 -0
  166. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_bandit_formatter_mapping.py +0 -0
  167. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_bandit_parsing.py +0 -0
  168. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_black_formatter.py +0 -0
  169. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_black_parser.py +0 -0
  170. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_black_tool.py +0 -0
  171. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_black_tool_more.py +0 -0
  172. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_cli_commands.py +0 -0
  173. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_cli_commands_more.py +0 -0
  174. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_cli_programmatic.py +0 -0
  175. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_compatibility_ruff_black.py +0 -0
  176. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_config_loader.py +0 -0
  177. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_config_loader_more.py +0 -0
  178. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_console_logger.py +0 -0
  179. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_console_logger_more.py +0 -0
  180. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_enums_and_normalizers.py +0 -0
  181. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_exceptions.py +0 -0
  182. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_formatters_tables.py +0 -0
  183. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_output_manager_reports.py +0 -0
  184. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_parsers_actionlint.py +0 -0
  185. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_ruff_parser_additional.py +0 -0
  186. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_ruff_parser_more.py +0 -0
  187. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_executor.py +0 -0
  188. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_executor_fmt_exclusion.py +0 -0
  189. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_executor_more.py +0 -0
  190. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_executor_post_checks.py +0 -0
  191. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_manager.py +0 -0
  192. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_utils.py +0 -0
  193. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_utils_fallbacks.py +0 -0
  194. {lintro-0.6.2 → lintro-0.7.0}/tests/unit/test_tool_utils_more.py +0 -0
  195. {lintro-0.6.2 → lintro-0.7.0}/tests/utils/__init__.py +0 -0
  196. {lintro-0.6.2 → lintro-0.7.0}/tests/utils/conftest.py +0 -0
  197. {lintro-0.6.2 → lintro-0.7.0}/tests/utils/test_formatting.py +0 -0
  198. {lintro-0.6.2 → lintro-0.7.0}/tests/utils/test_output_manager.py +0 -0
  199. {lintro-0.6.2 → lintro-0.7.0}/tests/utils/test_path_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lintro
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: A unified CLI tool for code formatting, linting, and quality assurance
5
5
  Author-email: TurboCoder13 <turbocoder13@gmail.com>
6
6
  License: MIT License
@@ -50,21 +50,21 @@ Requires-Dist: toml==0.10.2
50
50
  Requires-Dist: defusedxml==0.7.1
51
51
  Provides-Extra: dev
52
52
  Requires-Dist: pytest==8.4.2; extra == "dev"
53
- Requires-Dist: pytest-cov==6.3.0; extra == "dev"
54
- Requires-Dist: pytest-mock==3.15.0; extra == "dev"
53
+ Requires-Dist: pytest-cov==7.0.0; extra == "dev"
54
+ Requires-Dist: pytest-mock==3.15.1; extra == "dev"
55
55
  Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
56
- Requires-Dist: tox==4.30.1; extra == "dev"
56
+ Requires-Dist: tox==4.30.3; extra == "dev"
57
57
  Requires-Dist: allure-pytest==2.15.0; extra == "dev"
58
58
  Requires-Dist: ruff; extra == "dev"
59
59
  Requires-Dist: mypy; extra == "dev"
60
60
  Requires-Dist: coverage-badge==1.1.2; extra == "dev"
61
- Requires-Dist: python-semantic-release==10.3.2; extra == "dev"
61
+ Requires-Dist: python-semantic-release==10.4.1; extra == "dev"
62
62
  Requires-Dist: assertpy==1.1; extra == "dev"
63
63
  Requires-Dist: httpx==0.28.1; extra == "dev"
64
64
  Provides-Extra: test
65
65
  Requires-Dist: pytest==8.4.2; extra == "test"
66
- Requires-Dist: pytest-cov==6.3.0; extra == "test"
67
- Requires-Dist: pytest-mock==3.15.0; extra == "test"
66
+ Requires-Dist: pytest-cov==7.0.0; extra == "test"
67
+ Requires-Dist: pytest-mock==3.15.1; extra == "test"
68
68
  Requires-Dist: pytest-xdist==3.8.0; extra == "test"
69
69
  Requires-Dist: assertpy==1.1; extra == "test"
70
70
  Provides-Extra: typing
@@ -88,10 +88,12 @@ Lintro is a unified command-line interface that brings together multiple code qu
88
88
  [![Tests](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/test-and-coverage.yml?label=tests&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/test-and-coverage.yml?query=branch%3Amain)
89
89
  [![CI](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/ci-lintro-analysis.yml?label=ci&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/ci-lintro-analysis.yml?query=branch%3Amain)
90
90
  [![Docker](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/docker-build-publish.yml?label=docker&logo=docker&branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/docker-build-publish.yml?query=branch%3Amain)
91
+ [![SBOM (main)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/sbom-on-main.yml?label=sbom%20(main)&branch=main>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml?query=branch%3Amain)
92
+ [![Release pipeline (tags)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/publish-pypi-on-tag.yml?label=release%20pipeline%20(tags)&event=push>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/publish-pypi-on-tag.yml?query=event%3Apush)
91
93
  [![PyPI](https://img.shields.io/pypi/v/lintro?label=pypi)](https://pypi.org/project/lintro/)
92
94
 
93
95
  [![CodeQL](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml?query=branch%3Amain)
94
- [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro)
96
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro) [![SBOM](https://img.shields.io/badge/SBOM-enabled-brightgreen)](docs/security/assurance.md) [![Download SBOM](https://img.shields.io/badge/SBOM-download_latest-blue?logo=github)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/11142/badge)](https://www.bestpractices.dev/projects/11142)
95
97
 
96
98
  ### Why Lintro?
97
99
 
@@ -112,6 +114,42 @@ Lintro is a unified command-line interface that brings together multiple code qu
112
114
  - **Docker support** for containerized environments
113
115
  - **CI/CD integration** with GitHub Actions
114
116
 
117
+ ## Security & Compliance
118
+
119
+ Lintro follows modern security best practices and provides comprehensive supply chain transparency:
120
+
121
+ - **SBOM Generation**: Automated Software Bill of Materials on every push to main
122
+ - **Formats**: CycloneDX 1.6 and SPDX 2.3 (industry standards)
123
+ - **Compliance**: Meets Executive Order 14028 requirements for federal software
124
+ - **Download**: [Latest SBOM artifacts](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml)
125
+ - **Documentation**: See [Security Assurance](docs/security/assurance.md) for details
126
+
127
+ ### What's in the SBOM?
128
+
129
+ The SBOM provides a complete inventory of all dependencies:
130
+
131
+ - All Python packages with exact versions
132
+ - All npm packages (like Prettier)
133
+ - All GitHub Actions dependencies (pinned by SHA)
134
+ - Transitive dependencies
135
+ - License information
136
+
137
+ ### For Enterprise Users
138
+
139
+ Download SBOMs for security auditing and compliance:
140
+
141
+ ```bash
142
+ # Download latest SBOM artifacts
143
+ gh run download -R TurboCoder13/py-lintro \
144
+ --name sbom-artifacts \
145
+ $(gh run list -R TurboCoder13/py-lintro \
146
+ -w "Security - SBOM Generation" -L 1 \
147
+ --json databaseId -q '.[0].databaseId')
148
+
149
+ # Scan for vulnerabilities (requires grype)
150
+ grype sbom:main-*-py-lintro-sbom.spdx-2.3.json
151
+ ```
152
+
115
153
  ## Supported Tools
116
154
 
117
155
  | Tool | Language | Auto-fix |
@@ -14,10 +14,12 @@ Lintro is a unified command-line interface that brings together multiple code qu
14
14
  [![Tests](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/test-and-coverage.yml?label=tests&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/test-and-coverage.yml?query=branch%3Amain)
15
15
  [![CI](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/ci-lintro-analysis.yml?label=ci&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/ci-lintro-analysis.yml?query=branch%3Amain)
16
16
  [![Docker](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/docker-build-publish.yml?label=docker&logo=docker&branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/docker-build-publish.yml?query=branch%3Amain)
17
+ [![SBOM (main)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/sbom-on-main.yml?label=sbom%20(main)&branch=main>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml?query=branch%3Amain)
18
+ [![Release pipeline (tags)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/publish-pypi-on-tag.yml?label=release%20pipeline%20(tags)&event=push>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/publish-pypi-on-tag.yml?query=event%3Apush)
17
19
  [![PyPI](https://img.shields.io/pypi/v/lintro?label=pypi)](https://pypi.org/project/lintro/)
18
20
 
19
21
  [![CodeQL](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml?query=branch%3Amain)
20
- [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro)
22
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro) [![SBOM](https://img.shields.io/badge/SBOM-enabled-brightgreen)](docs/security/assurance.md) [![Download SBOM](https://img.shields.io/badge/SBOM-download_latest-blue?logo=github)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/11142/badge)](https://www.bestpractices.dev/projects/11142)
21
23
 
22
24
  ### Why Lintro?
23
25
 
@@ -38,6 +40,42 @@ Lintro is a unified command-line interface that brings together multiple code qu
38
40
  - **Docker support** for containerized environments
39
41
  - **CI/CD integration** with GitHub Actions
40
42
 
43
+ ## Security & Compliance
44
+
45
+ Lintro follows modern security best practices and provides comprehensive supply chain transparency:
46
+
47
+ - **SBOM Generation**: Automated Software Bill of Materials on every push to main
48
+ - **Formats**: CycloneDX 1.6 and SPDX 2.3 (industry standards)
49
+ - **Compliance**: Meets Executive Order 14028 requirements for federal software
50
+ - **Download**: [Latest SBOM artifacts](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml)
51
+ - **Documentation**: See [Security Assurance](docs/security/assurance.md) for details
52
+
53
+ ### What's in the SBOM?
54
+
55
+ The SBOM provides a complete inventory of all dependencies:
56
+
57
+ - All Python packages with exact versions
58
+ - All npm packages (like Prettier)
59
+ - All GitHub Actions dependencies (pinned by SHA)
60
+ - Transitive dependencies
61
+ - License information
62
+
63
+ ### For Enterprise Users
64
+
65
+ Download SBOMs for security auditing and compliance:
66
+
67
+ ```bash
68
+ # Download latest SBOM artifacts
69
+ gh run download -R TurboCoder13/py-lintro \
70
+ --name sbom-artifacts \
71
+ $(gh run list -R TurboCoder13/py-lintro \
72
+ -w "Security - SBOM Generation" -L 1 \
73
+ --json databaseId -q '.[0].databaseId')
74
+
75
+ # Scan for vulnerabilities (requires grype)
76
+ grype sbom:main-*-py-lintro-sbom.spdx-2.3.json
77
+ ```
78
+
41
79
  ## Supported Tools
42
80
 
43
81
  | Tool | Language | Auto-fix |
@@ -9,13 +9,13 @@
9
9
  </clipPath>
10
10
  <g clip-path="url(#a)">
11
11
  <path fill="#555" d="M0 0h63v20H0z"/>
12
- <path fill="#4c1" d="M63 0h36v20H63z"/>
12
+ <path fill="#e05d44" d="M63 0h36v20H63z"/>
13
13
  <path fill="url(#b)" d="M0 0h99v20H0z"/>
14
14
  </g>
15
15
  <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
16
16
  <text x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">coverage</text>
17
17
  <text x="325" y="140" transform="scale(.1)" textLength="530">coverage</text>
18
- <text x="800" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="260">82.0%</text>
19
- <text x="800" y="140" transform="scale(.1)" textLength="260">82.0%</text>
18
+ <text x="800" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="260">83.6%</text>
19
+ <text x="800" y="140" transform="scale(.1)" textLength="260">83.6%</text>
20
20
  </g>
21
21
  </svg>
@@ -30,7 +30,6 @@ Welcome to the Lintro documentation! This hub provides comprehensive guides for
30
30
  - **[Style Guide](style-guide.md)** - Coding standards and best practices
31
31
  - **[Coverage Setup](coverage-setup.md)** - Test coverage configuration reference
32
32
  - **[Self-Use Documentation](lintro-self-use.md)** - How Lintro uses itself
33
- - **[Removed CLI Options](removed_cli_options.md)** - Deprecated features reference
34
33
 
35
34
  ## 🚀 Quick Links
36
35
 
@@ -171,10 +170,12 @@ docker run --rm -v "$(pwd):/code" lintro:latest check
171
170
 
172
171
  ## 🆕 Recent Updates
173
172
 
173
+ - **Security audit framework** - Comprehensive security verification for workflows and scripts
174
+ - **DRY consolidation** - Reduced duplicate patterns across workflows and actions
175
+ - **Shell-free design** - Moved inline shell commands to dedicated scripts
176
+ - **Environment standardization** - Consistent variable usage across all workflows
174
177
  - **Documentation restructure** - Improved organization and navigation
175
- - **New tool analysis** - Detailed comparisons with core tools
176
- - **Enhanced GitHub integration** - More workflow examples
177
- - **Comprehensive configuration guide** - All tools covered
178
+ - **Enhanced tool analysis** - Detailed comparisons with core tools
178
179
 
179
180
  ## 🤝 Contributing to Documentation
180
181
 
@@ -53,6 +53,19 @@ Notes:
53
53
  - If work is ambiguous (e.g., a large refactor), explicitly signal with `!` or a `BREAKING CHANGE:` footer.
54
54
  - The PR title validator (`.github/workflows/semantic-pr-title.yml`) enforces the format before merge.
55
55
 
56
+ ## Developer Certificate of Origin (required)
57
+
58
+ All contributions must be signed off under the Developer Certificate of
59
+ Origin (DCO). Use `git commit -s` (or `--signoff`) so your commit message
60
+ contains a line like:
61
+
62
+ ```
63
+ Signed-off-by: Your Name <your.email@example.com>
64
+ ```
65
+
66
+ See `DCO.md` for details. Pull requests without DCO sign-offs will be asked
67
+ to amend commits before merge.
68
+
56
69
  ## Quick Start
57
70
 
58
71
  1. Clone the repository:
@@ -0,0 +1,79 @@
1
+ # Security Assurance (Overview)
2
+
3
+ This assurance note explains how `py-lintro` meets its documented security requirements and provides pointers to evidence.
4
+
5
+ ## Requirements Coverage
6
+
7
+ - Governance and Roles — see `GOVERNANCE.md`
8
+ - Contribution Integrity — DCO sign-offs required; see `DCO.md` and CI checks
9
+ - Responsible Disclosure — see `SECURITY.md`
10
+ - Branch Protection — enforced via Allstar (`.allstar/branch_protection.yaml`)
11
+ - Dependency Hygiene — Renovate, Dependency Review CI, `uv.lock`
12
+ - Static/SAST — Ruff, Bandit, CodeQL; policy checks for workflows (Actionlint)
13
+ - Container and Dockerfile — Hadolint
14
+ - SBOM (Software Bill of Materials) — Automated generation in CycloneDX 1.6 and SPDX 2.3 formats
15
+ - Workflow: `.github/workflows/sbom-on-main.yml`
16
+ - Generated on every push to main branch
17
+ - Includes all Python, npm, and GitHub Actions dependencies
18
+ - Artifacts available via GitHub Actions (90-day retention)
19
+ - Meets Executive Order 14028 federal software requirements
20
+ - Documentation and Versioning — `README.md`, `CHANGELOG.md`, semantic releases
21
+
22
+ ## Evidence Pointers
23
+
24
+ - CI Workflows: `.github/workflows/*.yml`
25
+ - Allstar Policy: `.allstar/branch_protection.yaml`
26
+ - Scorecard: badge in `README.md`
27
+ - Coverage: `coverage.xml` and README badge
28
+
29
+ ## SBOM (Supply Chain Transparency)
30
+
31
+ py-lintro automatically generates Software Bill of Materials (SBOM) for supply chain security:
32
+
33
+ ### What is Generated
34
+
35
+ - **CycloneDX 1.6 JSON**: Industry-standard format for dependency tracking
36
+ - **SPDX 2.3 JSON**: Linux Foundation standard for license compliance
37
+ - **Complete inventory**: All direct and transitive dependencies
38
+ - **Cryptographic hashes**: For verification and integrity checking
39
+
40
+ ### How to Access
41
+
42
+ 1. **Via GitHub Actions UI**:
43
+ - Navigate to [SBOM workflow runs](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml)
44
+ - Select the latest successful run
45
+ - Download "sbom-artifacts" from the Artifacts section
46
+
47
+ 2. **Via GitHub CLI**:
48
+
49
+ ```bash
50
+ gh run download -R TurboCoder13/py-lintro --name sbom-artifacts
51
+ ```
52
+
53
+ 3. **Via API**:
54
+ ```bash
55
+ gh api repos/TurboCoder13/py-lintro/actions/artifacts \
56
+ --jq '.artifacts[] | select(.name=="sbom-artifacts") | .archive_download_url'
57
+ ```
58
+
59
+ ### Use Cases
60
+
61
+ - **Security Scanning**: Feed into vulnerability scanners (Grype, Snyk, etc.)
62
+ - **License Compliance**: Audit all dependency licenses
63
+ - **Supply Chain Security**: Track all software components
64
+ - **Federal Compliance**: Meets EO 14028 requirements
65
+ - **Enterprise Procurement**: Satisfy security questionnaires
66
+
67
+ ### File Naming Convention
68
+
69
+ SBOM files are named: `{branch}-{commit-sha}-py-lintro-sbom.{format}.json`
70
+
71
+ Example: `main-3b97378f3438-py-lintro-sbom.cyclonedx-1.6.json`
72
+
73
+ This ensures traceability to exact codebase versions.
74
+
75
+ ## Continuous Improvement
76
+
77
+ - Periodic updates via Renovate
78
+ - Automated analyses (Scorecard, CodeQL)
79
+ - Maintainer reviews for all changes
@@ -0,0 +1,42 @@
1
+ # Security Requirements
2
+
3
+ This document summarizes security requirements adopted by `py-lintro` to support OpenSSF Best Practices (Silver).
4
+
5
+ ## Project and Process
6
+
7
+ - FLOSS license (MIT) and public repository
8
+ - Governance documented in `GOVERNANCE.md`
9
+ - Responsible disclosure process in `SECURITY.md`
10
+ - DCO required for contributions (`DCO.md`), enforced via commit sign-offs
11
+
12
+ ## Source Integrity and Branch Protection
13
+
14
+ - All changes land via PR with maintainer review
15
+ - Branch protection enforced on `main` (no force pushes; required reviews; admins included)
16
+
17
+ ## Dependencies and Supply Chain
18
+
19
+ - Dependencies managed via `pyproject.toml` and `uv.lock`
20
+ - Automated dependency updates (Renovate) with CI validation
21
+ - Dependency Review workflow enabled in CI
22
+
23
+ ## Static and Policy Analysis
24
+
25
+ - Linting/formatting: Ruff, Black, Prettier, Yamllint, Hadolint, Actionlint
26
+ - Security linting: Bandit; GitHub CodeQL configured
27
+ - OpenSSF Scorecard monitored
28
+
29
+ ## Build and Release
30
+
31
+ - CI builds, tests, and coverage for PRs and `main`
32
+ - Semantic versioning; signed release artifacts published via CI using OIDC
33
+
34
+ ## Testing and Coverage
35
+
36
+ - Automated test suite with ~84% statement coverage
37
+ - New code requires tests and coverage reporting
38
+
39
+ ## Secure Defaults
40
+
41
+ - No execution of untrusted code
42
+ - Docker image and scripts follow hardening practices (pinned actions, validated inputs)
@@ -1,3 +1,3 @@
1
1
  """Lintro - A unified CLI core for code formatting, linting, and quality assurance."""
2
2
 
3
- __version__ = "0.6.2"
3
+ __version__ = "0.7.0"
@@ -142,11 +142,14 @@ class PrettierTool(BaseTool):
142
142
  # so the unified logger prints a single, consistent success line.
143
143
  if success:
144
144
  output = None
145
- return Tool.to_result(
145
+
146
+ # Return full ToolResult so table rendering can use parsed issues
147
+ return ToolResult(
146
148
  name=self.name,
147
149
  success=success,
148
150
  output=output,
149
151
  issues_count=issues_count,
152
+ issues=issues,
150
153
  )
151
154
 
152
155
  def fix(
@@ -264,6 +267,9 @@ class PrettierTool(BaseTool):
264
267
  output=final_output,
265
268
  # For fix operations, issues_count represents remaining for summaries
266
269
  issues_count=remaining_count,
270
+ # Provide issues so formatters can render tables. Use initial issues
271
+ # (auto-fixable set) for display; fall back to remaining when none.
272
+ issues=(initial_issues if initial_issues else remaining_issues),
267
273
  initial_issues_count=initial_count,
268
274
  fixed_issues_count=fixed_count,
269
275
  remaining_issues_count=remaining_count,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lintro
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: A unified CLI tool for code formatting, linting, and quality assurance
5
5
  Author-email: TurboCoder13 <turbocoder13@gmail.com>
6
6
  License: MIT License
@@ -50,21 +50,21 @@ Requires-Dist: toml==0.10.2
50
50
  Requires-Dist: defusedxml==0.7.1
51
51
  Provides-Extra: dev
52
52
  Requires-Dist: pytest==8.4.2; extra == "dev"
53
- Requires-Dist: pytest-cov==6.3.0; extra == "dev"
54
- Requires-Dist: pytest-mock==3.15.0; extra == "dev"
53
+ Requires-Dist: pytest-cov==7.0.0; extra == "dev"
54
+ Requires-Dist: pytest-mock==3.15.1; extra == "dev"
55
55
  Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
56
- Requires-Dist: tox==4.30.1; extra == "dev"
56
+ Requires-Dist: tox==4.30.3; extra == "dev"
57
57
  Requires-Dist: allure-pytest==2.15.0; extra == "dev"
58
58
  Requires-Dist: ruff; extra == "dev"
59
59
  Requires-Dist: mypy; extra == "dev"
60
60
  Requires-Dist: coverage-badge==1.1.2; extra == "dev"
61
- Requires-Dist: python-semantic-release==10.3.2; extra == "dev"
61
+ Requires-Dist: python-semantic-release==10.4.1; extra == "dev"
62
62
  Requires-Dist: assertpy==1.1; extra == "dev"
63
63
  Requires-Dist: httpx==0.28.1; extra == "dev"
64
64
  Provides-Extra: test
65
65
  Requires-Dist: pytest==8.4.2; extra == "test"
66
- Requires-Dist: pytest-cov==6.3.0; extra == "test"
67
- Requires-Dist: pytest-mock==3.15.0; extra == "test"
66
+ Requires-Dist: pytest-cov==7.0.0; extra == "test"
67
+ Requires-Dist: pytest-mock==3.15.1; extra == "test"
68
68
  Requires-Dist: pytest-xdist==3.8.0; extra == "test"
69
69
  Requires-Dist: assertpy==1.1; extra == "test"
70
70
  Provides-Extra: typing
@@ -88,10 +88,12 @@ Lintro is a unified command-line interface that brings together multiple code qu
88
88
  [![Tests](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/test-and-coverage.yml?label=tests&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/test-and-coverage.yml?query=branch%3Amain)
89
89
  [![CI](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/ci-lintro-analysis.yml?label=ci&branch=main&logo=githubactions&logoColor=white)](https://github.com/TurboCoder13/py-lintro/actions/workflows/ci-lintro-analysis.yml?query=branch%3Amain)
90
90
  [![Docker](https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/docker-build-publish.yml?label=docker&logo=docker&branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/docker-build-publish.yml?query=branch%3Amain)
91
+ [![SBOM (main)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/sbom-on-main.yml?label=sbom%20(main)&branch=main>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml?query=branch%3Amain)
92
+ [![Release pipeline (tags)](<https://img.shields.io/github/actions/workflow/status/TurboCoder13/py-lintro/publish-pypi-on-tag.yml?label=release%20pipeline%20(tags)&event=push>)](https://github.com/TurboCoder13/py-lintro/actions/workflows/publish-pypi-on-tag.yml?query=event%3Apush)
91
93
  [![PyPI](https://img.shields.io/pypi/v/lintro?label=pypi)](https://pypi.org/project/lintro/)
92
94
 
93
95
  [![CodeQL](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/TurboCoder13/py-lintro/actions/workflows/codeql.yml?query=branch%3Amain)
94
- [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro)
96
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TurboCoder13/py-lintro/badge)](https://scorecard.dev/viewer/?uri=github.com/TurboCoder13/py-lintro) [![SBOM](https://img.shields.io/badge/SBOM-enabled-brightgreen)](docs/security/assurance.md) [![Download SBOM](https://img.shields.io/badge/SBOM-download_latest-blue?logo=github)](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/11142/badge)](https://www.bestpractices.dev/projects/11142)
95
97
 
96
98
  ### Why Lintro?
97
99
 
@@ -112,6 +114,42 @@ Lintro is a unified command-line interface that brings together multiple code qu
112
114
  - **Docker support** for containerized environments
113
115
  - **CI/CD integration** with GitHub Actions
114
116
 
117
+ ## Security & Compliance
118
+
119
+ Lintro follows modern security best practices and provides comprehensive supply chain transparency:
120
+
121
+ - **SBOM Generation**: Automated Software Bill of Materials on every push to main
122
+ - **Formats**: CycloneDX 1.6 and SPDX 2.3 (industry standards)
123
+ - **Compliance**: Meets Executive Order 14028 requirements for federal software
124
+ - **Download**: [Latest SBOM artifacts](https://github.com/TurboCoder13/py-lintro/actions/workflows/sbom-on-main.yml)
125
+ - **Documentation**: See [Security Assurance](docs/security/assurance.md) for details
126
+
127
+ ### What's in the SBOM?
128
+
129
+ The SBOM provides a complete inventory of all dependencies:
130
+
131
+ - All Python packages with exact versions
132
+ - All npm packages (like Prettier)
133
+ - All GitHub Actions dependencies (pinned by SHA)
134
+ - Transitive dependencies
135
+ - License information
136
+
137
+ ### For Enterprise Users
138
+
139
+ Download SBOMs for security auditing and compliance:
140
+
141
+ ```bash
142
+ # Download latest SBOM artifacts
143
+ gh run download -R TurboCoder13/py-lintro \
144
+ --name sbom-artifacts \
145
+ $(gh run list -R TurboCoder13/py-lintro \
146
+ -w "Security - SBOM Generation" -L 1 \
147
+ --json databaseId -q '.[0].databaseId')
148
+
149
+ # Scan for vulnerabilities (requires grype)
150
+ grype sbom:main-*-py-lintro-sbom.spdx-2.3.json
151
+ ```
152
+
115
153
  ## Supported Tools
116
154
 
117
155
  | Tool | Language | Auto-fix |
@@ -13,6 +13,8 @@ docs/getting-started.md
13
13
  docs/github-integration.md
14
14
  docs/lintro-self-use.md
15
15
  docs/style-guide.md
16
+ docs/security/assurance.md
17
+ docs/security/requirements.md
16
18
  docs/tool-analysis/README.md
17
19
  docs/tool-analysis/actionlint-analysis.md
18
20
  docs/tool-analysis/bandit-analysis.md
@@ -147,9 +149,11 @@ tests/integration/test_ruff_black_policy.py
147
149
  tests/integration/test_ruff_integration.py
148
150
  tests/integration/test_yamllint_integration.py
149
151
  tests/scripts/__init__.py
152
+ tests/scripts/test_ci_post_pr_comment.py
150
153
  tests/scripts/test_delete_previous_lintro_comments.py
151
154
  tests/scripts/test_extract_version.py
152
155
  tests/scripts/test_ghcr_prune_untagged.py
156
+ tests/scripts/test_github_comment_utilities.py
153
157
  tests/scripts/test_script_environment.py
154
158
  tests/scripts/test_semantic_release_compute_next.py
155
159
  tests/scripts/test_shell_scripts.py
@@ -10,22 +10,22 @@ defusedxml==0.7.1
10
10
 
11
11
  [dev]
12
12
  pytest==8.4.2
13
- pytest-cov==6.3.0
14
- pytest-mock==3.15.0
13
+ pytest-cov==7.0.0
14
+ pytest-mock==3.15.1
15
15
  pytest-xdist==3.8.0
16
- tox==4.30.1
16
+ tox==4.30.3
17
17
  allure-pytest==2.15.0
18
18
  ruff
19
19
  mypy
20
20
  coverage-badge==1.1.2
21
- python-semantic-release==10.3.2
21
+ python-semantic-release==10.4.1
22
22
  assertpy==1.1
23
23
  httpx==0.28.1
24
24
 
25
25
  [test]
26
26
  pytest==8.4.2
27
- pytest-cov==6.3.0
28
- pytest-mock==3.15.0
27
+ pytest-cov==7.0.0
28
+ pytest-mock==3.15.1
29
29
  pytest-xdist==3.8.0
30
30
  assertpy==1.1
31
31
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lintro"
7
- version = "0.6.2"
7
+ version = "0.7.0"
8
8
  description = "A unified CLI tool for code formatting, linting, and quality assurance"
9
9
  keywords = [ "linting", "formatting", "code-quality", "cli", "python", "javascript", "yaml", "docker",]
10
10
  classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities",]
@@ -15,7 +15,7 @@ name = "TurboCoder13"
15
15
  email = "turbocoder13@gmail.com"
16
16
 
17
17
  [dependency-groups]
18
- dev = [ "build==1.3.0", "pytest==8.4.2", "pytest-cov==6.3.0", "pytest-xdist==3.8.0", "twine==6.2.0", "assertpy==1.1",]
18
+ dev = [ "build==1.3.0", "pytest==8.4.2", "pytest-cov==7.0.0", "pytest-xdist==3.8.0", "twine==6.2.0", "assertpy==1.1",]
19
19
 
20
20
  [project.license]
21
21
  file = "LICENSE"
@@ -25,8 +25,8 @@ file = "README.md"
25
25
  content-type = "text/markdown"
26
26
 
27
27
  [project.optional-dependencies]
28
- dev = [ "pytest==8.4.2", "pytest-cov==6.3.0", "pytest-mock==3.15.0", "pytest-xdist==3.8.0", "tox==4.30.1", "allure-pytest==2.15.0", "ruff", "mypy", "coverage-badge==1.1.2", "python-semantic-release==10.3.2", "assertpy==1.1", "httpx==0.28.1",]
29
- test = [ "pytest==8.4.2", "pytest-cov==6.3.0", "pytest-mock==3.15.0", "pytest-xdist==3.8.0", "assertpy==1.1",]
28
+ dev = [ "pytest==8.4.2", "pytest-cov==7.0.0", "pytest-mock==3.15.1", "pytest-xdist==3.8.0", "tox==4.30.3", "allure-pytest==2.15.0", "ruff", "mypy", "coverage-badge==1.1.2", "python-semantic-release==10.4.1", "assertpy==1.1", "httpx==0.28.1",]
29
+ test = [ "pytest==8.4.2", "pytest-cov==7.0.0", "pytest-mock==3.15.1", "pytest-xdist==3.8.0", "assertpy==1.1",]
30
30
  typing = [ "types-setuptools==80.9.0.20250822", "types-tabulate==0.9.0.20241207",]
31
31
 
32
32
  [project.scripts]
@@ -8,6 +8,7 @@ from loguru import logger
8
8
 
9
9
  from lintro.parsers.prettier.prettier_parser import parse_prettier_output
10
10
  from lintro.tools.implementations.tool_prettier import PrettierTool
11
+ from lintro.utils.tool_utils import format_tool_output
11
12
 
12
13
  logger.remove()
13
14
  logger.add(lambda msg: print(msg, end=""), level="INFO")
@@ -167,3 +168,34 @@ def test_prettier_output_consistency_direct_vs_lintro(temp_prettier_file):
167
168
  f"Issue count mismatch: CLI={direct_issues}, Lintro={result.issues_count}\n"
168
169
  f"CLI Output:\n{direct_output}\nLintro Output:\n{result.output}"
169
170
  )
171
+
172
+
173
+ def test_prettier_fix_sets_issues_for_table(temp_prettier_file):
174
+ """PrettierTool.fix should populate issues for table rendering.
175
+
176
+ Args:
177
+ temp_prettier_file: Pytest fixture providing a temporary file with violations.
178
+ """
179
+ tool = PrettierTool()
180
+ tool.set_options()
181
+
182
+ # Ensure there are initial issues
183
+ pre_result = tool.check([str(temp_prettier_file)])
184
+ assert pre_result.issues_count > 0
185
+
186
+ # Run fix and assert issues are provided for table formatting
187
+ fix_result = tool.fix([str(temp_prettier_file)])
188
+ assert fix_result.success is True
189
+ assert fix_result.remaining_issues_count == 0
190
+ assert fix_result.issues is not None
191
+ assert len(fix_result.issues) == pre_result.issues_count
192
+
193
+ # Verify that formatted output renders a table section for auto-fixables
194
+ formatted = format_tool_output(
195
+ tool_name="prettier",
196
+ output=fix_result.output or "",
197
+ group_by="auto",
198
+ output_format="grid",
199
+ issues=fix_result.issues,
200
+ )
201
+ assert "Auto-fixable issues" in formatted or formatted