RepoAuditor 0.2.25__tar.gz → 0.2.27__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.
Files changed (135) hide show
  1. {repoauditor-0.2.25 → repoauditor-0.2.27}/PKG-INFO +1 -1
  2. {repoauditor-0.2.25 → repoauditor-0.2.27}/pyproject.toml +1 -0
  3. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanning.py +3 -3
  4. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanningPushProtection.py +1 -1
  5. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRuleset.py +20 -0
  6. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/Module.py +49 -0
  7. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequirePullRequests.py +47 -0
  8. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequireSignedCommits.py +47 -0
  9. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequireStatusChecks.py +47 -0
  10. repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/RulesetQuery.py +53 -0
  11. repoauditor-0.2.27/src/RepoAuditor/Plugins/__init__.py +0 -0
  12. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/__init__.py +1 -1
  13. repoauditor-0.2.27/src/RepoAuditor/py.typed +0 -0
  14. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/CommandLineProcessor_UnitTest.py +19 -0
  15. repoauditor-0.2.27/tests/Plugins/GitHubRuleset_UnitTest.py +213 -0
  16. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +6 -6
  17. {repoauditor-0.2.25 → repoauditor-0.2.27}/.copier-answers.yml +0 -0
  18. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/CODEOWNERS +0 -0
  19. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  20. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  21. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  22. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  23. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/actions/release_impl/action.yml +0 -0
  24. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/pull_request_template.md +0 -0
  25. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/release_sources.yaml +0 -0
  26. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/workflows/CICD.yml +0 -0
  27. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/workflows/CICD_impl.yml +0 -0
  28. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/workflows/EndToEnd.yml +0 -0
  29. {repoauditor-0.2.25 → repoauditor-0.2.27}/.github/workflows/codeql.yml +0 -0
  30. {repoauditor-0.2.25 → repoauditor-0.2.27}/.gitignore +0 -0
  31. {repoauditor-0.2.25 → repoauditor-0.2.27}/.pre-commit-config.yaml +0 -0
  32. {repoauditor-0.2.25 → repoauditor-0.2.27}/.python-version +0 -0
  33. {repoauditor-0.2.25 → repoauditor-0.2.27}/CODE_OF_CONDUCT.md +0 -0
  34. {repoauditor-0.2.25 → repoauditor-0.2.27}/CONTRIBUTING.md +0 -0
  35. {repoauditor-0.2.25 → repoauditor-0.2.27}/DEVELOPMENT.md +0 -0
  36. {repoauditor-0.2.25 → repoauditor-0.2.27}/GOVERNANCE.md +0 -0
  37. {repoauditor-0.2.25 → repoauditor-0.2.27}/LICENSE +0 -0
  38. {repoauditor-0.2.25 → repoauditor-0.2.27}/MAINTAINERS.md +0 -0
  39. {repoauditor-0.2.25 → repoauditor-0.2.27}/README.md +0 -0
  40. {repoauditor-0.2.25 → repoauditor-0.2.27}/SECURITY.md +0 -0
  41. {repoauditor-0.2.25 → repoauditor-0.2.27}/minisign_key.pub +0 -0
  42. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/AutoGitSemVer.yaml +0 -0
  43. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/CommandLineProcessor.py +0 -0
  44. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Display.py +0 -0
  45. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/EntryPoint.py +0 -0
  46. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/ExecuteModules.py +0 -0
  47. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +0 -0
  48. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Impl/__init__.py +0 -0
  49. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Module.py +0 -0
  50. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugin.py +0 -0
  51. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +0 -0
  52. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
  53. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowForcePushes.py +0 -0
  54. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
  55. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +0 -0
  56. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +0 -0
  57. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +0 -0
  58. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
  59. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
  60. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
  61. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
  62. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
  63. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
  64. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
  65. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
  66. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
  67. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
  68. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
  69. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
  70. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
  71. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/Protected.py +0 -0
  72. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/__init__.py +0 -0
  73. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
  74. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +0 -0
  75. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
  76. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
  77. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/Module.py +0 -0
  78. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
  79. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/AutoMerge.py +0 -0
  80. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DefaultBranch.py +0 -0
  81. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DeleteHeadBranches.py +0 -0
  82. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DependabotSecurityUpdates.py +0 -0
  83. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Description.py +0 -0
  84. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardEnableRequirementImpl.py +0 -0
  85. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardValueRequirementImpl.py +0 -0
  86. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/__init__.py +0 -0
  87. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/License.py +0 -0
  88. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommit.py +0 -0
  89. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommitMessage.py +0 -0
  90. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Private.py +0 -0
  91. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/RebaseMergeCommit.py +0 -0
  92. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashCommitMerge.py +0 -0
  93. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashMergeCommitMessage.py +0 -0
  94. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
  95. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportDiscussions.py +0 -0
  96. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportIssues.py +0 -0
  97. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportProjects.py +0 -0
  98. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportWikis.py +0 -0
  99. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/TemplateRepository.py +0 -0
  100. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/WebCommitSignoff.py +0 -0
  101. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/__init__.py +0 -0
  102. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
  103. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubBase/Module.py +0 -0
  104. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubBase/__init__.py +0 -0
  105. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/CustomizationQuery.py +0 -0
  106. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Impl/ExistsRequirementImpl.py +0 -0
  107. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Impl/__init__.py +0 -0
  108. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Module.py +0 -0
  109. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/CodeOwners.py +0 -0
  110. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/Contributing.py +0 -0
  111. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/IssueTemplates.py +0 -0
  112. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/PullRequestTemplates.py +0 -0
  113. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/SecurityPolicy.py +0 -0
  114. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/__init__.py +0 -0
  115. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomization/__init__.py +0 -0
  116. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubCustomizationPlugin.py +0 -0
  117. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
  118. {repoauditor-0.2.25/src/RepoAuditor/Plugins → repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/Requirements}/__init__.py +0 -0
  119. /repoauditor-0.2.25/src/RepoAuditor/py.typed → /repoauditor-0.2.27/src/RepoAuditor/Plugins/GitHubRulesets/__init__.py +0 -0
  120. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Query.py +0 -0
  121. {repoauditor-0.2.25 → repoauditor-0.2.27}/src/RepoAuditor/Requirement.py +0 -0
  122. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/EntryPoint_UnitTest.py +0 -0
  123. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/ExecuteModules_UnitTest.py +0 -0
  124. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Module_UnitTest.py +0 -0
  125. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugin_UnitTest.py +0 -0
  126. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/GitHubCustomization_EndToEndTest.py +0 -0
  127. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/GitHubCustomization_UnitTest.py +0 -0
  128. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/GitHubModule_UnitTest.py +0 -0
  129. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/GitHub_EndToEndTest.py +0 -0
  130. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/__snapshots__/GitHubCustomization_EndToEndTest.ambr +0 -0
  131. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Plugins/utilities.py +0 -0
  132. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Query_UnitTest.py +0 -0
  133. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/Requirement_UnitTest.py +0 -0
  134. {repoauditor-0.2.25 → repoauditor-0.2.27}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
  135. {repoauditor-0.2.25 → repoauditor-0.2.27}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RepoAuditor
3
- Version: 0.2.25
3
+ Version: 0.2.27
4
4
  Summary: Add your description here
5
5
  Project-URL: Homepage, https://github.com/gt-sse-center/RepoAuditor
6
6
  Project-URL: Documentation, https://github.com/gt-sse-center/RepoAuditor
@@ -39,6 +39,7 @@ repo_auditor = "RepoAuditor:EntryPoint.app"
39
39
  [project.entry-points.RepoAuditor]
40
40
  GitHubPlugin = "RepoAuditor.Plugins.GitHubPlugin"
41
41
  GitHubCustomizationPlugin = "RepoAuditor.Plugins.GitHubCustomizationPlugin"
42
+ GitHubRulesetPlugin="RepoAuditor.Plugins.GitHubRuleset"
42
43
 
43
44
  [build-system]
44
45
  requires = ["hatchling"]
@@ -24,12 +24,12 @@ class SecretScanning(StandardEnableRequirementImpl):
24
24
  True,
25
25
  "false",
26
26
  "settings/security_analysis",
27
- "Secret scanning",
28
- "Secret scanning",
27
+ "Secret Protection",
28
+ "Secret protection",
29
29
  _GetValue,
30
30
  textwrap.dedent(
31
31
  """\
32
- The default behavior is to enable secret scanning.
32
+ The default behavior is to enable secret protection.
33
33
 
34
34
  Reasons for this Default
35
35
  ------------------------
@@ -24,7 +24,7 @@ class SecretScanningPushProtection(StandardEnableRequirementImpl):
24
24
  True,
25
25
  "false",
26
26
  "settings/security_analysis",
27
- "Secret scanning",
27
+ "Secret Protection",
28
28
  "Push protection",
29
29
  _GetValue,
30
30
  textwrap.dedent(
@@ -0,0 +1,20 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains Plugin functionality."""
8
+
9
+ import pluggy
10
+
11
+ from RepoAuditor import APP_NAME
12
+ from RepoAuditor.Module import Module
13
+
14
+ from RepoAuditor.Plugins.GitHubRulesets.Module import GitHubRulesetModule
15
+
16
+
17
+ @pluggy.HookimplMarker(APP_NAME)
18
+ def GetModule() -> Module:
19
+ """Return GitHubRulesetModule Module."""
20
+ return GitHubRulesetModule()
@@ -0,0 +1,49 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the GitHubRulesetModule object."""
8
+
9
+ import typer
10
+
11
+ from dbrownell_Common.TyperEx import TypeDefinitionItemType
12
+ from dbrownell_Common.Types import override
13
+
14
+ from RepoAuditor.Module import ExecutionStyle
15
+ from RepoAuditor.Plugins.GitHubBase.Module import GitHubBaseModule
16
+ from RepoAuditor.Plugins.GitHubRulesets.RulesetQuery import RulesetQuery
17
+
18
+
19
+ class GitHubRulesetModule(GitHubBaseModule):
20
+ """Module that validates GitHub repository rulesets."""
21
+
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ "GitHubRuleset",
25
+ "Validates GitHub repository rulesets.",
26
+ ExecutionStyle.Parallel,
27
+ [RulesetQuery()],
28
+ requires_explicit_include=True,
29
+ )
30
+
31
+ @override
32
+ def GetDynamicArgDefinitions(self) -> dict[str, TypeDefinitionItemType]:
33
+ """Get the definitions for the arguments to this requirement."""
34
+ return {
35
+ "url": (
36
+ str,
37
+ typer.Option(
38
+ ...,
39
+ help="[REQUIRED] GitHub repository URL (e.g., https://github.com/owner/repo).",
40
+ ),
41
+ ),
42
+ "branch": (
43
+ str,
44
+ typer.Option(
45
+ None,
46
+ help="Branch to evaluate. The default branch will be used if not specified.",
47
+ ),
48
+ ),
49
+ }
@@ -0,0 +1,47 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequirePullRequests object."""
8
+
9
+ from typing import override, Any
10
+ from RepoAuditor.Requirement import EvaluateResult, ExecutionStyle, Requirement
11
+
12
+
13
+ class RequirePullRequests(Requirement):
14
+ """Implement the Pull Requests required ruleset for the branch."""
15
+
16
+ def __init__(self) -> None:
17
+ super().__init__(
18
+ name="RequirePullRequests",
19
+ description="Require pull requests before merging to default branch",
20
+ style=ExecutionStyle.Parallel,
21
+ resolution_template="Enable pull request requirements in repository rulesets",
22
+ rationale_template="Pull request reviews help maintain code quality and collaboration",
23
+ )
24
+
25
+ @override
26
+ def _EvaluateImpl(
27
+ self,
28
+ query_data: dict[str, Any],
29
+ requirement_args: dict[str, Any],
30
+ ) -> Requirement.EvaluateImplResult:
31
+ rulesets = query_data.get("rulesets", [])
32
+
33
+ for ruleset in rulesets:
34
+ if (
35
+ ruleset.get("enforcement", "") == "active"
36
+ and ruleset.get("target", "") == "branch"
37
+ and ruleset.get("parameters", {}).get("pull_request", {}).get("required", False)
38
+ ):
39
+ return self.EvaluateImplResult(
40
+ EvaluateResult.Success, f"Ruleset '{ruleset['name']}' enforces pull requests"
41
+ )
42
+
43
+ return self.EvaluateImplResult(
44
+ EvaluateResult.Error,
45
+ "No active branch ruleset requiring pull requests found",
46
+ provide_resolution=True,
47
+ )
@@ -0,0 +1,47 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireSignedCommits object."""
8
+
9
+ from typing import override, Any
10
+ from RepoAuditor.Requirement import EvaluateResult, ExecutionStyle, Requirement
11
+
12
+
13
+ class RequireSignedCommits(Requirement):
14
+ """Implement the Signed Commits required ruleset for a branch."""
15
+
16
+ def __init__(self) -> None:
17
+ super().__init__(
18
+ name="RequireSignedCommits",
19
+ description="Require signed commits",
20
+ style=ExecutionStyle.Parallel,
21
+ resolution_template="Enable commit signing requirement in repository rulesets",
22
+ rationale_template="Signed commits ensure commit authenticity",
23
+ )
24
+
25
+ @override
26
+ def _EvaluateImpl(
27
+ self,
28
+ query_data: dict[str, Any],
29
+ requirement_args: dict[str, Any],
30
+ ) -> Requirement.EvaluateImplResult:
31
+ rulesets = query_data.get("rulesets", [])
32
+
33
+ for ruleset in rulesets:
34
+ if (
35
+ ruleset.get("enforcement", "") == "active"
36
+ and ruleset.get("target", "") == "branch"
37
+ and ruleset.get("parameters", {}).get("commit_signatures", False)
38
+ ):
39
+ return self.EvaluateImplResult(
40
+ EvaluateResult.Success, f"Ruleset '{ruleset['name']}' enforces signed commits"
41
+ )
42
+
43
+ return self.EvaluateImplResult(
44
+ EvaluateResult.Error,
45
+ "No active branch ruleset requiring signed commits found",
46
+ provide_resolution=True,
47
+ )
@@ -0,0 +1,47 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireStatusChecks object."""
8
+
9
+ from typing import override, Any
10
+ from RepoAuditor.Requirement import EvaluateResult, ExecutionStyle, Requirement
11
+
12
+
13
+ class RequireStatusChecks(Requirement):
14
+ """Implement the Status Check ruleset for a branch."""
15
+
16
+ def __init__(self) -> None:
17
+ super().__init__(
18
+ name="RequireStatusChecks",
19
+ description="Require status checks to pass before merging",
20
+ style=ExecutionStyle.Parallel,
21
+ resolution_template="Configure required status checks in repository rulesets",
22
+ rationale_template="Status checks ensure code quality and compatibility",
23
+ )
24
+
25
+ @override
26
+ def _EvaluateImpl(
27
+ self,
28
+ query_data: dict[str, Any],
29
+ requirement_args: dict[str, Any],
30
+ ) -> Requirement.EvaluateImplResult:
31
+ rulesets = query_data.get("rulesets", [])
32
+
33
+ for ruleset in rulesets:
34
+ if (
35
+ ruleset.get("enforcement", "") == "active"
36
+ and ruleset.get("target", "") == "branch"
37
+ and len(ruleset.get("parameters", {}).get("required_status_checks", [])) > 0
38
+ ):
39
+ return self.EvaluateImplResult(
40
+ EvaluateResult.Success, f"Ruleset '{ruleset['name']}' enforces status checks"
41
+ )
42
+
43
+ return self.EvaluateImplResult(
44
+ EvaluateResult.Error,
45
+ "No active branch ruleset requiring status checks found",
46
+ provide_resolution=True,
47
+ )
@@ -0,0 +1,53 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RulesetQuery object."""
8
+
9
+ from typing import Any, Optional
10
+
11
+ from dbrownell_Common.Types import override
12
+ from RepoAuditor.Impl.ParallelSequentialProcessor import ExecutionStyle
13
+ from RepoAuditor.Query import Query
14
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequirePullRequests import RequirePullRequests
15
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequireSignedCommits import RequireSignedCommits
16
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequireStatusChecks import RequireStatusChecks
17
+
18
+
19
+ class RulesetQuery(Query):
20
+ """Query to validate GitHub repository rulesets."""
21
+
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ "RulesetQuery",
25
+ ExecutionStyle.Parallel,
26
+ [
27
+ RequireStatusChecks(),
28
+ RequirePullRequests(),
29
+ RequireSignedCommits(),
30
+ ],
31
+ )
32
+
33
+ @override
34
+ def GetData(
35
+ self,
36
+ module_data: dict[str, Any],
37
+ ) -> Optional[dict[str, Any]]:
38
+ """Retrieve data required for validating GitHub rulesets.
39
+
40
+ Args:
41
+ module_data (dict): Dictionary containing initial data from the module.
42
+
43
+ Returns:
44
+ Optional[dict]: A dictionary containing ruleset-related
45
+ data, or None if an error occurs.
46
+
47
+ """
48
+ # Fetch ruleset data from the GitHub API
49
+ ruleset_data = module_data["session"].get("rulesets")
50
+
51
+ # Add ruleset data to module_data
52
+ module_data["ruleset_data"] = ruleset_data
53
+ return module_data
File without changes
@@ -3,4 +3,4 @@ APP_NAME = "RepoAuditor"
3
3
  # Note that this value will be overwritten by calls to `python ../../Build.py update_version` based
4
4
  # on changes observed in the git repository. The default value below will be used until the value
5
5
  # here is explicitly updated by the Continuous Integration system.
6
- __version__ = "0.2.25"
6
+ __version__ = "0.2.27"
File without changes
@@ -446,3 +446,22 @@ def test_InvalidArgName():
446
446
  set(),
447
447
  set(),
448
448
  )
449
+
450
+
451
+ # ----------------------------------------------------------------------
452
+ def test_InvalidArgs():
453
+ """Check if an invalid module is specified as an argument."""
454
+ with pytest.raises(
455
+ Exception,
456
+ match=re.escape("'InvalidModule' is not a recognized module name."),
457
+ ):
458
+ CommandLineProcessor.Create(
459
+ # Specify an unregistered module
460
+ get_dynamic_args_func=lambda dynamic_arg_definitions: {"InvalidModule-arg1": "value"},
461
+ # ValidModule is the registered module.
462
+ modules=[MyModule(name="ValidModule")],
463
+ includes=["InvalidModule"],
464
+ excludes=[],
465
+ warnings_as_error_module_names=set(),
466
+ ignore_warnings_module_names=set(),
467
+ )
@@ -0,0 +1,213 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Unit tests for the GitHub Rulesets Plugin"""
8
+
9
+ from RepoAuditor.Requirement import EvaluateResult
10
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequirePullRequests import RequirePullRequests
11
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequireStatusChecks import RequireStatusChecks
12
+ from RepoAuditor.Plugins.GitHubRulesets.Requirements.RequireSignedCommits import (
13
+ RequireSignedCommits,
14
+ )
15
+
16
+
17
+ def create_ruleset(name, target, enforcement, parameters):
18
+ """Helper function to create ruleset structure"""
19
+ return {"name": name, "target": target, "enforcement": enforcement, "parameters": parameters}
20
+
21
+
22
+ # ----------------------------------------------------------------------
23
+ class TestRequirePullRequests:
24
+ """Unit tests for the RequirePullRequests requirement."""
25
+
26
+ def test_Enabled(self):
27
+ requirement = RequirePullRequests() # type: ignore
28
+ context = {
29
+ "rulesets": [
30
+ create_ruleset(
31
+ name="PR Rules",
32
+ target="branch",
33
+ enforcement="active",
34
+ parameters={"pull_request": {"required": True, "require_code_owner_review": True}},
35
+ )
36
+ ]
37
+ }
38
+ result = requirement.Evaluate(context, {})
39
+ assert result.result == EvaluateResult.Success
40
+ assert "enforces pull requests" in result.context
41
+
42
+ def test_Disabled(self):
43
+ requirement = RequirePullRequests() # type: ignore
44
+ context = {
45
+ "rulesets": [
46
+ create_ruleset(
47
+ name="Inactive PR Rules",
48
+ target="branch",
49
+ enforcement="disabled", # Wrong enforcement
50
+ parameters={"pull_request": {"required": True}},
51
+ )
52
+ ]
53
+ }
54
+ result = requirement.Evaluate(context, {})
55
+ assert result.result == EvaluateResult.Error
56
+
57
+ def test_WrongTarget(self):
58
+ requirement = RequirePullRequests() # type: ignore
59
+ context = {
60
+ "rulesets": [
61
+ create_ruleset(
62
+ name="Wrong Target Rules",
63
+ target="tag", # Wrong target
64
+ enforcement="active",
65
+ parameters={"pull_request": {"required": True}},
66
+ )
67
+ ]
68
+ }
69
+ result = requirement.Evaluate(context, {})
70
+ assert result.result == EvaluateResult.Error
71
+
72
+ def test_MissingParameter(self):
73
+ requirement = RequirePullRequests() # type: ignore
74
+ context = {
75
+ "rulesets": [
76
+ create_ruleset(
77
+ name="Partial Rules",
78
+ target="branch",
79
+ enforcement="active",
80
+ parameters={"other_rule": {}}, # Missing pull_request
81
+ )
82
+ ]
83
+ }
84
+ result = requirement.Evaluate(context, {})
85
+ assert result.result == EvaluateResult.Error
86
+
87
+ def test_NoRulesets(self):
88
+ requirement = RequirePullRequests() # type: ignore
89
+ context = {"rulesets": []}
90
+ result = requirement.Evaluate(context, {})
91
+ assert result.result == EvaluateResult.Error
92
+ assert "No active branch ruleset requiring pull requests found" in result.context
93
+
94
+
95
+ # ----------------------------------------------------------------------
96
+ class TestRequireSignedCommits:
97
+ """Unit tests for the RequireSignedCommits requirement."""
98
+
99
+ def test_Enabled(self):
100
+ requirement = RequireSignedCommits() # type: ignore
101
+ context = {
102
+ "rulesets": [
103
+ create_ruleset(
104
+ name="Signing Rules",
105
+ target="branch",
106
+ enforcement="active",
107
+ parameters={"commit_signatures": True},
108
+ )
109
+ ]
110
+ }
111
+ result = requirement.Evaluate(context, {})
112
+ assert result.result == EvaluateResult.Success
113
+ assert "enforces signed commits" in result.context
114
+
115
+ def test_Disabled(self):
116
+ requirement = RequireSignedCommits() # type: ignore
117
+ context = {
118
+ "rulesets": [
119
+ create_ruleset(
120
+ name="Inactive Signing",
121
+ target="branch",
122
+ enforcement="evaluate", # Wrong enforcement
123
+ parameters={"commit_signatures": True},
124
+ )
125
+ ]
126
+ }
127
+ result = requirement.Evaluate(context, {})
128
+ assert result.result == EvaluateResult.Error
129
+
130
+ def test_PartialConfig(self):
131
+ requirement = RequireSignedCommits() # type: ignore
132
+ context = {
133
+ "rulesets": [
134
+ create_ruleset(
135
+ name="Partial Config",
136
+ target="branch",
137
+ enforcement="active",
138
+ parameters={"commit_signatures": False}, # Explicitly disabled
139
+ )
140
+ ]
141
+ }
142
+ result = requirement.Evaluate(context, {})
143
+ assert result.result == EvaluateResult.Error
144
+
145
+ def test_NoRulesets(self):
146
+ requirement = RequireSignedCommits() # type: ignore
147
+ context = {"rulesets": []}
148
+ result = requirement.Evaluate(context, {})
149
+ assert result.result == EvaluateResult.Error
150
+ assert "No active branch ruleset requiring signed commits found" in result.context
151
+
152
+
153
+ # ----------------------------------------------------------------------
154
+ class TestRequireStatusChecks:
155
+ """Unit tests for the RequireStatusChecks requirement."""
156
+
157
+ def test_Enabled(self):
158
+ requirement = RequireStatusChecks() # type: ignore
159
+ context = {
160
+ "rulesets": [
161
+ create_ruleset(
162
+ name="CI Checks",
163
+ target="branch",
164
+ enforcement="active",
165
+ parameters={
166
+ "required_status_checks": [
167
+ {"context": "ci-test"},
168
+ {"context": "security-scan"},
169
+ ]
170
+ },
171
+ )
172
+ ]
173
+ }
174
+ result = requirement.Evaluate(context, {})
175
+ assert result.result == EvaluateResult.Success
176
+ assert "enforces status checks" in result.context
177
+
178
+ def test_EmptyChecks(self):
179
+ requirement = RequireStatusChecks() # type: ignore
180
+ context = {
181
+ "rulesets": [
182
+ create_ruleset(
183
+ name="Empty Checks",
184
+ target="branch",
185
+ enforcement="active",
186
+ parameters={"required_status_checks": []}, # Empty list
187
+ )
188
+ ]
189
+ }
190
+ result = requirement.Evaluate(context, {})
191
+ assert result.result == EvaluateResult.Error
192
+
193
+ def test_InactiveRuleset(self):
194
+ requirement = RequireStatusChecks() # type: ignore
195
+ context = {
196
+ "rulesets": [
197
+ create_ruleset(
198
+ name="Inactive Checks",
199
+ target="branch",
200
+ enforcement="disabled", # Inactive
201
+ parameters={"required_status_checks": [{"context": "ci-test"}]},
202
+ )
203
+ ]
204
+ }
205
+ result = requirement.Evaluate(context, {})
206
+ assert result.result == EvaluateResult.Error
207
+
208
+ def test_NoRulesets(self):
209
+ requirement = RequireStatusChecks() # type: ignore
210
+ context = {"rulesets": []}
211
+ result = requirement.Evaluate(context, {})
212
+ assert result.result == EvaluateResult.Error
213
+ assert "No active branch ruleset requiring status checks found" in result.context
@@ -886,15 +886,15 @@
886
886
  │ │
887
887
  │ ╭─ [Error] SecretScanning ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
888
888
  │ │ │ │
889
- │ │ Validates that 'Secret scanning' is set to the expected value. │ │
889
+ │ │ Validates that 'Secret protection' is set to the expected value. │ │
890
890
  │ │ │ │
891
- │ │ ERROR: 'Secret scanning' must be set to 'False' (it is currently set to 'True'). │ │
891
+ │ │ ERROR: 'Secret protection' must be set to 'False' (it is currently set to 'True'). │ │
892
892
  │ │ │ │
893
893
  │ │ Resolution │ │
894
894
  │ │ ---------- │ │
895
895
  │ │ 1) Visit '<scrubbed-github-url>'<scrubbed-space>│ │
896
- │ │ 2) Locate the 'Secret scanning' section │ │
897
- │ │ 3) Ensure that 'Secret scanning' is disabled │ │
896
+ │ │ 2) Locate the 'Secret Protection' section │ │
897
+ │ │ 3) Ensure that 'Secret protection' is disabled │ │
898
898
  │ │ │ │
899
899
  │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
900
900
  │ │
@@ -935,7 +935,7 @@
935
935
  │ │ Resolution │ │
936
936
  │ │ ---------- │ │
937
937
  │ │ 1) Visit '<scrubbed-github-url>'<scrubbed-space>│ │
938
- │ │ 2) Locate the 'Secret scanning' section │ │
938
+ │ │ 2) Locate the 'Secret Protection' section │ │
939
939
  │ │ 3) Ensure that 'Push protection' is disabled │ │
940
940
  │ │ │ │
941
941
  │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
@@ -1511,7 +1511,7 @@
1511
1511
  │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
1512
1512
  │ ╭─ [Warning] SecretScanning ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
1513
1513
  │ │ │ │
1514
- │ │ Validates that 'Secret scanning' is set to the expected value. │ │
1514
+ │ │ Validates that 'Secret protection' is set to the expected value. │ │
1515
1515
  │ │ │ │
1516
1516
  │ │ WARNING: Incomplete data was encountered; please provide the GitHub PAT or update the PAT's permissions if one was provided. │ │
1517
1517
  │ │ │ │
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes