RepoAuditor 0.2.81__tar.gz → 0.2.82__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 (186) hide show
  1. {repoauditor-0.2.81 → repoauditor-0.2.82}/DEVELOPMENT.md +6 -1
  2. {repoauditor-0.2.81 → repoauditor-0.2.82}/PKG-INFO +1 -1
  3. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +1 -1
  4. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRulesetRequirementImpl.py +25 -1
  5. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetQuery.py +120 -0
  6. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/AllowMainlineForcePushes.py +40 -0
  7. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/DismissStalePullRequestApprovals.py +59 -0
  8. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/EnsureStatusChecks.py +69 -0
  9. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireApprovalMostRecentPush.py +58 -0
  10. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireApprovals.py +68 -0
  11. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireCodeOwnerReview.py +62 -0
  12. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireCodeScanningResults.py +39 -0
  13. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireConversationResolution.py +59 -0
  14. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireLinearHistory.py +40 -0
  15. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequirePullRequests.py +19 -3
  16. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireSignedCommits.py +17 -3
  17. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireStatusChecksToPass.py +38 -0
  18. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireSuccessfulDeployments.py +42 -0
  19. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireUpToDateBranches.py +60 -0
  20. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RestrictCreations.py +38 -0
  21. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RestrictDeletions.py +38 -0
  22. repoauditor-0.2.82/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RestrictUpdates.py +38 -0
  23. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/__init__.py +1 -1
  24. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubEnterprise_EndToEndTest.py +182 -0
  25. repoauditor-0.2.82/tests/Plugins/GitHubModule/RulesetRequirements_UnitTest.py +688 -0
  26. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHub_EndToEndTest.py +132 -6
  27. repoauditor-0.2.81/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr → repoauditor-0.2.82/tests/Plugins/__snapshots__/GitHubEnterprise_EndToEndTest.ambr +761 -699
  28. repoauditor-0.2.82/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +3306 -0
  29. repoauditor-0.2.81/src/RepoAuditor/Plugins/GitHub/RulesetQuery.py +0 -78
  30. repoauditor-0.2.81/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/RequireStatusChecks.py +0 -25
  31. repoauditor-0.2.81/tests/Plugins/GitHubModule/RulesetRequirements_UnitTest.py +0 -190
  32. repoauditor-0.2.81/tests/Plugins/__snapshots__/GitHubEnterprise_EndToEndTest.ambr +0 -1688
  33. {repoauditor-0.2.81 → repoauditor-0.2.82}/.copier-answers.yml +0 -0
  34. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/CODEOWNERS +0 -0
  35. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  36. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  37. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  38. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  39. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/actions/release_impl/action.yml +0 -0
  40. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/pull_request_template.md +0 -0
  41. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/release_sources.yaml +0 -0
  42. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/workflows/CICD.yml +0 -0
  43. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/workflows/CICD_impl.yml +0 -0
  44. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/workflows/EndToEnd.yml +0 -0
  45. {repoauditor-0.2.81 → repoauditor-0.2.82}/.github/workflows/codeql.yml +0 -0
  46. {repoauditor-0.2.81 → repoauditor-0.2.82}/.gitignore +0 -0
  47. {repoauditor-0.2.81 → repoauditor-0.2.82}/.pre-commit-config.yaml +0 -0
  48. {repoauditor-0.2.81 → repoauditor-0.2.82}/.python-version +0 -0
  49. {repoauditor-0.2.81 → repoauditor-0.2.82}/CODE_OF_CONDUCT.md +0 -0
  50. {repoauditor-0.2.81 → repoauditor-0.2.82}/CONTRIBUTING.md +0 -0
  51. {repoauditor-0.2.81 → repoauditor-0.2.82}/GOVERNANCE.md +0 -0
  52. {repoauditor-0.2.81 → repoauditor-0.2.82}/LICENSE +0 -0
  53. {repoauditor-0.2.81 → repoauditor-0.2.82}/MAINTAINERS.md +0 -0
  54. {repoauditor-0.2.81 → repoauditor-0.2.82}/README.md +0 -0
  55. {repoauditor-0.2.81 → repoauditor-0.2.82}/SECURITY.md +0 -0
  56. {repoauditor-0.2.81 → repoauditor-0.2.82}/default_config.yaml +0 -0
  57. {repoauditor-0.2.81 → repoauditor-0.2.82}/minisign_key.pub +0 -0
  58. {repoauditor-0.2.81 → repoauditor-0.2.82}/pyproject.toml +0 -0
  59. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/AutoGitSemVer.yaml +0 -0
  60. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/CommandLineProcessor.py +0 -0
  61. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Display.py +0 -0
  62. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/EntryPoint.py +0 -0
  63. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/ExecuteModules.py +0 -0
  64. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +0 -0
  65. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Impl/__init__.py +0 -0
  66. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Module.py +0 -0
  67. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugin.py +0 -0
  68. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/CommunityStandardsQuery.py +0 -0
  69. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Impl/ExistsRequirementImpl.py +0 -0
  70. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Impl/__init__.py +0 -0
  71. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Module.py +0 -0
  72. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/CodeOfConduct.py +0 -0
  73. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/CodeOwners.py +0 -0
  74. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/Contributing.py +0 -0
  75. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/IssueTemplates.py +0 -0
  76. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/LicenseFile.py +0 -0
  77. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/PullRequestTemplates.py +0 -0
  78. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/ReadMe.py +0 -0
  79. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/SecurityPolicy.py +0 -0
  80. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/Requirements/__init__.py +0 -0
  81. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandards/__init__.py +0 -0
  82. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/CommunityStandardsPlugin.py +0 -0
  83. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +0 -0
  84. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
  85. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowMainlineForcePushes.py +0 -0
  86. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
  87. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +0 -0
  88. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +0 -0
  89. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
  90. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
  91. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
  92. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
  93. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
  94. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
  95. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
  96. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
  97. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
  98. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
  99. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
  100. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
  101. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
  102. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/DefaultBranchRequirements/Protected.py +0 -0
  103. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/DefaultBranchRequirements/__init__.py +0 -0
  104. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
  105. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +0 -0
  106. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
  107. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
  108. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/Module.py +0 -0
  109. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/RulesetRequirements/__init__.py +0 -0
  110. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
  111. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/AutoMerge.py +0 -0
  112. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/DefaultBranch.py +0 -0
  113. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/DeleteHeadBranches.py +0 -0
  114. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/DependabotSecurityUpdates.py +0 -0
  115. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/Description.py +0 -0
  116. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/Impl/StandardEnableRequirementImpl.py +0 -0
  117. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/Impl/StandardValueRequirementImpl.py +0 -0
  118. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/Impl/__init__.py +0 -0
  119. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/License.py +0 -0
  120. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/MergeCommit.py +0 -0
  121. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/MergeCommitMessage.py +0 -0
  122. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/Private.py +0 -0
  123. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/RebaseMergeCommit.py +0 -0
  124. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SecretScanning.py +0 -0
  125. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SecretScanningPushProtection.py +0 -0
  126. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SquashCommitMerge.py +0 -0
  127. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SquashMergeCommitMessage.py +0 -0
  128. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
  129. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SupportDiscussions.py +0 -0
  130. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SupportIssues.py +0 -0
  131. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SupportProjects.py +0 -0
  132. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/SupportWikis.py +0 -0
  133. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/TemplateRepository.py +0 -0
  134. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/WebCommitSignoff.py +0 -0
  135. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/StandardRequirements/__init__.py +0 -0
  136. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
  137. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHubBase/Module.py +0 -0
  138. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHubBase/__init__.py +0 -0
  139. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
  140. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Plugins/__init__.py +0 -0
  141. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Query.py +0 -0
  142. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/Requirement.py +0 -0
  143. {repoauditor-0.2.81 → repoauditor-0.2.82}/src/RepoAuditor/py.typed +0 -0
  144. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/CommandLineProcessor_UnitTest.py +0 -0
  145. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/EntryPoint_UnitTest.py +0 -0
  146. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/ExecuteModules_UnitTest.py +0 -0
  147. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Module_UnitTest.py +0 -0
  148. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugin_UnitTest.py +0 -0
  149. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/CommunityStandards/CommunityStandardsQuery_UnitTest.py +0 -0
  150. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/CommunityStandards/ExistsRequirementImpl_UnitTest.py +0 -0
  151. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/CommunityStandards/GitHubCommunityStandards_UnitTest.py +0 -0
  152. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/CommunityStandards_EndToEndTest.py +0 -0
  153. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionQuery_UnitTest.py +0 -0
  154. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals_UnitTest.py +0 -0
  155. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/EnsureStatusChecks_UnitTest.py +0 -0
  156. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush_UnitTest.py +0 -0
  157. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/RequireApprovals_UnitTest.py +0 -0
  158. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/RequireCodeOwnerReview_UnitTest.py +0 -0
  159. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicBranchProtectionRequirements/RequireUpToDateBranches_UnitTest.py +0 -0
  160. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ClassicValueRequirementImpl_UnitTest.py +0 -0
  161. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/DefaultBranchQueryRequirements/Protected_UnitTest.py +0 -0
  162. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/DefaultBranchQuery_UnitTest.py +0 -0
  163. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/EnableRulesetRequirementImpl_UnitTest.py +0 -0
  164. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/GitHubModule_UnitTest.py +0 -0
  165. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/GitHubSession_UnitTest.py +0 -0
  166. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/RulsesetQuery_UnitTest.py +0 -0
  167. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/DependabotSecurityUpdates_UnitTest.py +0 -0
  168. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/Description_UnitTest.py +0 -0
  169. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/License_UnitTest.py +0 -0
  170. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/MergeCommitMessage_UnitTest.py +0 -0
  171. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/Private_UnitTest.py +0 -0
  172. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/SecretScanningPushProtection_UnitTest.py +0 -0
  173. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/SecretScanning_UnitTest.py +0 -0
  174. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQueryRequirements/SquashMergeCommitMessage_UnitTest.py +0 -0
  175. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/StandardQuery_UnitTest.py +0 -0
  176. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/ValueRequrementImpl_UnitTest.py +0 -0
  177. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/GitHubModule/fixtures.py +0 -0
  178. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/__snapshots__/CommunityStandards_EndToEndTest.ambr +0 -0
  179. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/conftest.py +0 -0
  180. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Plugins/utilities.py +0 -0
  181. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Query_UnitTest.py +0 -0
  182. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/Requirement_UnitTest.py +0 -0
  183. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/__init__.py +0 -0
  184. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
  185. {repoauditor-0.2.81 → repoauditor-0.2.82}/tests/conftest.py +0 -0
  186. {repoauditor-0.2.81 → repoauditor-0.2.82}/uv.lock +0 -0
@@ -101,7 +101,12 @@ Please follow the steps below to complete the configuration.
101
101
  - Enable `Restrict deletions`
102
102
  - Enable `Require signed commits`
103
103
  - Enable `Require a pull request before merging` with 1 required approval.
104
- - Enable `Require status checks to pass` with the `CI+CD Workflow / Validate (ubuntu-latest, 3.12)` or an equivalent check.
104
+ - Enable `Dismiss stale pull request approvals when new commits are pushed`.
105
+ - Enable `Require approval of the most recent reviewable push`.
106
+ - Enable `Require conversation resolution before merging`.
107
+ - Enable `Require status checks to pass`.
108
+ - Enable `Require branches to be up to date before merging`.
109
+ - Set the `CI+CD Workflow / Validate (ubuntu-latest, 3.12)` or an equivalent check.
105
110
  - Disable `Block force pushes`.
106
111
  - Be sure to hit `Save changes` at the end.
107
112
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RepoAuditor
3
- Version: 0.2.81
3
+ Version: 0.2.82
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
@@ -4,7 +4,7 @@
4
4
  # | Distributed under the MIT License.
5
5
  # |
6
6
  # -------------------------------------------------------------------------------
7
- """Contains the AllowBypassSettings object."""
7
+ """Contains the DoNotAllowBypassSettings object."""
8
8
 
9
9
  import textwrap
10
10
 
@@ -6,6 +6,7 @@
6
6
  # -------------------------------------------------------------------------------
7
7
  """Contains the EnableRequirementImpl object."""
8
8
 
9
+ import textwrap
9
10
  from collections.abc import Callable
10
11
  from typing import Any, Optional
11
12
 
@@ -28,14 +29,24 @@ class EnableRulesetRequirementImpl(EnableRequirementImpl):
28
29
  github_ruleset_type: str,
29
30
  github_ruleset_value: str,
30
31
  get_configuration_value_func: Callable[[dict[str, Any]], Optional[bool]],
31
- resolution: str,
32
32
  rationale: str,
33
+ resolution: Optional[str] = None,
33
34
  subject: Optional[str] = None,
34
35
  *,
35
36
  requires_explicit_include: bool = False,
36
37
  unset_set_terminology: tuple[str, str] = ("disabled", "enabled"),
37
38
  missing_value_is_warning: bool = True,
38
39
  ) -> None:
40
+ if resolution is None:
41
+ resolution = textwrap.dedent(
42
+ """\
43
+ 1) Visit '{session.github_url}/settings/rules'.
44
+ 2) Find or create a ruleset on the branch '{branch}'.
45
+ 3) Go to '{__ruleset_value}'.
46
+ 4) {__enabled_str} the rule.
47
+ """
48
+ )
49
+
39
50
  super().__init__(
40
51
  name=name,
41
52
  enabled_by_default=enabled_by_default,
@@ -52,6 +63,17 @@ class EnableRulesetRequirementImpl(EnableRequirementImpl):
52
63
 
53
64
  self.github_ruleset_type = github_ruleset_type
54
65
 
66
+ # ----------------------------------------------------------------------
67
+ def _GetValue(
68
+ self,
69
+ rule: dict[str, Any],
70
+ ) -> Optional[bool]:
71
+ rule_type = rule.get("type")
72
+ if rule_type is None:
73
+ return None
74
+
75
+ return rule_type == self.github_ruleset_type
76
+
55
77
  # ----------------------------------------------------------------------
56
78
  @override
57
79
  def _EvaluateImpl(
@@ -70,6 +92,8 @@ class EnableRulesetRequirementImpl(EnableRequirementImpl):
70
92
 
71
93
  query_data["__expected_value"] = expected_rule_enabled
72
94
  query_data["__enabled_str"] = "Enable" if expected_rule_enabled else "Disable"
95
+ # ruleset_value is stored as settings_value
96
+ query_data["__ruleset_value"] = self.github_settings_value
73
97
 
74
98
  # Get the rules for the specified branch
75
99
  rules = query_data.get("rules", [])
@@ -0,0 +1,120 @@
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
+
13
+ from RepoAuditor.Impl.ParallelSequentialProcessor import ExecutionStyle
14
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.AllowMainlineForcePushes import (
15
+ AllowMainlineForcePushesRule,
16
+ )
17
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.DismissStalePullRequestApprovals import (
18
+ DismissStalePullRequestApprovalsRule,
19
+ )
20
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.EnsureStatusChecks import EnsureStatusChecksRule
21
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireApprovalMostRecentPush import (
22
+ RequireApprovalMostRecentPushRule,
23
+ )
24
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireApprovals import RequireApprovalsRule
25
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireCodeOwnerReview import RequireCodeOwnerReviewRule
26
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireCodeScanningResults import (
27
+ RequireCodeScanningResultsRule,
28
+ )
29
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireConversationResolution import (
30
+ RequireConversationResolutionRule,
31
+ )
32
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireLinearHistory import RequireLinearHistoryRule
33
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequirePullRequests import RequirePullRequests
34
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireSignedCommits import RequireSignedCommits
35
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireStatusChecksToPass import (
36
+ RequireStatusChecksToPassRule,
37
+ )
38
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireSuccessfulDeployments import (
39
+ RequireSuccessfulDeploymentsRule,
40
+ )
41
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RequireUpToDateBranches import RequireUpToDateBranchesRule
42
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RestrictCreations import RestrictCreationsRule
43
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RestrictDeletions import RestrictDeletionsRule
44
+ from RepoAuditor.Plugins.GitHub.RulesetRequirements.RestrictUpdates import RestrictUpdatesRule
45
+ from RepoAuditor.Query import Query
46
+
47
+
48
+ class RulesetQuery(Query):
49
+ """Query to validate GitHub repository rulesets."""
50
+
51
+ def __init__(self) -> None:
52
+ super().__init__(
53
+ "RulesetQuery",
54
+ ExecutionStyle.Parallel,
55
+ [
56
+ RestrictCreationsRule(),
57
+ RestrictUpdatesRule(),
58
+ RestrictDeletionsRule(),
59
+ RequireLinearHistoryRule(),
60
+ RequireSuccessfulDeploymentsRule(),
61
+ RequireSignedCommits(),
62
+ RequirePullRequests(),
63
+ RequireApprovalsRule(),
64
+ DismissStalePullRequestApprovalsRule(),
65
+ RequireCodeOwnerReviewRule(),
66
+ RequireApprovalMostRecentPushRule(),
67
+ RequireConversationResolutionRule(),
68
+ RequireStatusChecksToPassRule(),
69
+ RequireUpToDateBranchesRule(),
70
+ EnsureStatusChecksRule(),
71
+ AllowMainlineForcePushesRule(),
72
+ RequireCodeScanningResultsRule(),
73
+ ],
74
+ )
75
+
76
+ @override
77
+ def GetData(
78
+ self,
79
+ module_data: dict[str, Any],
80
+ ) -> Optional[dict[str, Any]]:
81
+ """Retrieve data required for validating GitHub rulesets.
82
+
83
+ Args:
84
+ module_data (dict): Dictionary containing initial data from the module.
85
+
86
+ Returns:
87
+ Optional[dict]: A dictionary containing ruleset-related
88
+ data, or None if an error occurs.
89
+
90
+ """
91
+ branch = module_data.get("branch")
92
+ if branch is None:
93
+ # Get the default branch name
94
+ response = module_data["session"].get("")
95
+
96
+ response.raise_for_status()
97
+ response = response.json()
98
+
99
+ branch = response["default_branch"]
100
+
101
+ # Record the branch name
102
+ module_data["branch"] = branch
103
+
104
+ # Fetch ruleset data for a specific branch.
105
+ # This only returns active rules on the branch
106
+ rules_response = module_data["session"].get(f"rules/branches/{branch}")
107
+
108
+ rules_response.raise_for_status()
109
+
110
+ # Add ruleset data to module_data
111
+ module_data["rules"] = rules_response.json()
112
+
113
+ # Also get the associated ruleset for each rule
114
+ for rule in module_data["rules"]:
115
+ ruleset_response = module_data["session"].get(f"rulesets/{rule['ruleset_id']}")
116
+ ruleset_response.raise_for_status()
117
+ ruleset = ruleset_response.json()
118
+ rule["ruleset"] = ruleset
119
+
120
+ return module_data
@@ -0,0 +1,40 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the AllowMainlineForcePushesRule requirement."""
8
+
9
+ import textwrap
10
+
11
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
12
+
13
+
14
+ class AllowMainlineForcePushesRule(EnableRulesetRequirementImpl):
15
+ """Requirement for rule to allow force pushes to the matching branch."""
16
+
17
+ def __init__(self) -> None:
18
+ super().__init__(
19
+ name="AllowMainlineForcePushesRule",
20
+ enabled_by_default=False,
21
+ dynamic_arg_name="yes",
22
+ github_ruleset_type="non_fast_forward",
23
+ github_ruleset_value="Block force pushes",
24
+ get_configuration_value_func=self._GetValue,
25
+ rationale=textwrap.dedent(
26
+ """\
27
+ The default behavior is to not allow force pushes to the mainline branch.
28
+
29
+ Reasons for this Default
30
+ ------------------------
31
+ - Force pushes rewrite history, which breaks git lineage for all other clones of the repository.
32
+ Merges are possible when this happens, but they are difficult to perform and data loss is
33
+ possible.
34
+
35
+ Reasons to Override this Default
36
+ --------------------------------
37
+ <unknown>
38
+ """,
39
+ ),
40
+ )
@@ -0,0 +1,59 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the DismissStalePullRequestApprovalsRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class DismissStalePullRequestApprovalsRule(EnableRulesetRequirementImpl):
19
+ """Rule to dismiss stale pull request approvals when new commits are pushed."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="DismissStalePullRequestApprovalsRule",
25
+ enabled_by_default=True,
26
+ dynamic_arg_name="no",
27
+ github_ruleset_type="dismiss_stale_reviews_on_push",
28
+ github_ruleset_value="Require a pull request before merging -> Dismiss stale pull request approvals when new commits are pushed",
29
+ get_configuration_value_func=self._GetValue,
30
+ rationale=textwrap.dedent(
31
+ """\
32
+ The default behavior is to dismiss stale pull request approvals when new commits are pushed.
33
+
34
+ Reasons for this Default
35
+ ------------------------
36
+ - Approvals apply to the changes as they existed when the approval was granted. The approval
37
+ may no longer be valid when new changes are pushed.
38
+
39
+ Reasons to Override this Default
40
+ --------------------------------
41
+ You trust the contributor to only make minor changes after approval.
42
+ """
43
+ ),
44
+ )
45
+
46
+ # ----------------------------------------------------------------------
47
+ @override
48
+ def _GetValue(
49
+ self,
50
+ rule: dict[str, Any],
51
+ ) -> Optional[bool]:
52
+ rule_type = rule.get("type")
53
+ if rule_type is None:
54
+ return None
55
+
56
+ if rule_type == "pull_request":
57
+ return rule["parameters"].get(self.github_ruleset_type, False)
58
+
59
+ return False
@@ -0,0 +1,69 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the EnsureStatusChecksRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class EnsureStatusChecksRule(EnableRulesetRequirementImpl):
19
+ """Rule to verify status checks have been assigned as a rule for a branch."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="EnsureStatusChecksRule",
25
+ enabled_by_default=True,
26
+ dynamic_arg_name="no",
27
+ github_ruleset_type="required_status_checks",
28
+ github_ruleset_value="Require status checks to pass -> Status checks that are required",
29
+ get_configuration_value_func=self._GetValue,
30
+ resolution=textwrap.dedent(
31
+ """\
32
+ 1) Visit '{session.github_url}/settings/rules'.
33
+ 2) Find or create a ruleset on the branch '{branch}'.
34
+ 3) Go to '{__ruleset_value}'.
35
+ 4) Click on '+ Add checks'.
36
+ 5) Type the name of the check to enforce.
37
+ 6) Select status checks that must pass before merging.
38
+ """,
39
+ ),
40
+ rationale=textwrap.dedent(
41
+ """\
42
+ The default behavior is to require the specification of at least one status check that must pass before merging.
43
+
44
+ Reasons for this Default
45
+ ------------------------
46
+ - A Continuous Integration process must be gated by some activity, action, or work flow.
47
+
48
+ Reasons to Override this Default
49
+ --------------------------------
50
+ - Code reviews are sufficient to ensure the quality of pull requests before they are merged into the branch
51
+ (this is not recommended).
52
+ """
53
+ ),
54
+ )
55
+
56
+ # ----------------------------------------------------------------------
57
+ @override
58
+ def _GetValue(
59
+ self,
60
+ rule: dict[str, Any],
61
+ ) -> Optional[bool]:
62
+ rule_type = rule.get("type")
63
+
64
+ # If rule_type doesn't exist,
65
+ # it means the rule is not applicable
66
+ if rule_type and rule_type == self.github_ruleset_type:
67
+ return len(rule["parameters"][self.github_ruleset_type]) > 0
68
+
69
+ return False
@@ -0,0 +1,58 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireApprovalMostRecentPushRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class RequireApprovalMostRecentPushRule(EnableRulesetRequirementImpl):
19
+ """Rule to require approval on the most recent reviewable push in a pull request."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="RequireApprovalMostRecentPushRule",
25
+ enabled_by_default=True,
26
+ dynamic_arg_name="no",
27
+ github_ruleset_type="require_last_push_approval",
28
+ github_ruleset_value="Require a pull request before merging -> Require approval of the most recent reviewable push",
29
+ get_configuration_value_func=self._GetValue,
30
+ rationale=textwrap.dedent(
31
+ """\
32
+ The default behavior is to require approval of the most recent reviewable push by someone other than the author of the pull request.
33
+
34
+ Reasons for this Default
35
+ ------------------------
36
+ - Self-approval of a pull request eliminates the value provided by a second pair of eyes during a code review.
37
+
38
+ Reasons to Override this Default
39
+ --------------------------------
40
+ - You are the only person working on the repository.
41
+ """,
42
+ ),
43
+ )
44
+
45
+ # ----------------------------------------------------------------------
46
+ @override
47
+ def _GetValue(
48
+ self,
49
+ rule: dict[str, Any],
50
+ ) -> Optional[bool]:
51
+ rule_type = rule.get("type")
52
+ if rule_type is None:
53
+ return None
54
+
55
+ if rule_type == "pull_request":
56
+ return rule["parameters"].get(self.github_ruleset_type, False)
57
+
58
+ return False
@@ -0,0 +1,68 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireApprovalsRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class RequireApprovalsRule(EnableRulesetRequirementImpl):
19
+ """Rule to require at least 1 approval on a pull request."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="RequireApprovalsRule",
25
+ enabled_by_default=True,
26
+ dynamic_arg_name="no",
27
+ github_ruleset_type="required_approving_review_count",
28
+ github_ruleset_value="Require a pull request before merging -> Required approvals",
29
+ get_configuration_value_func=self._GetValue,
30
+ resolution=textwrap.dedent(
31
+ """\
32
+ 1) Visit '{session.github_url}/settings/rules'.
33
+ 2) Find or create a ruleset on the branch '{branch}'.
34
+ 3) Go to '{__ruleset_value}'.
35
+ 4) Set the number of required approvals to at least 1.
36
+ """
37
+ ),
38
+ rationale=textwrap.dedent(
39
+ """\
40
+ The default behavior is to require at least one approval.
41
+
42
+ Reasons for this Default
43
+ ------------------------
44
+ - Code Reviews are a generally accepted best practice for software development.
45
+
46
+ Reasons to Override this Default
47
+ --------------------------------
48
+ - You are the only person working on the repository (set the value to 0).
49
+ - You want to require more than one approval (set the value to the number of approvals required).
50
+ - You are not comfortable with the amount of time code reviews introduce in the development process (set the value to 0).
51
+ """,
52
+ ),
53
+ )
54
+
55
+ # ----------------------------------------------------------------------
56
+ @override
57
+ def _GetValue(
58
+ self,
59
+ rule: dict[str, Any],
60
+ ) -> Optional[bool]:
61
+ rule_type = rule.get("type")
62
+ if rule_type is None:
63
+ return None
64
+
65
+ if rule_type == "pull_request":
66
+ return rule["parameters"].get(self.github_ruleset_type, 0) > 0
67
+
68
+ return False
@@ -0,0 +1,62 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireCodeOwnerReviewRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class RequireCodeOwnerReviewRule(EnableRulesetRequirementImpl):
19
+ """Rule to require a review on a pull request from a designated code owner."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="RequireCodeOwnerReviewRule",
25
+ enabled_by_default=False,
26
+ dynamic_arg_name="yes",
27
+ github_ruleset_type="require_code_owner_review",
28
+ github_ruleset_value="Require a pull request before merging -> Require review from Code Owners",
29
+ get_configuration_value_func=self._GetValue,
30
+ rationale=textwrap.dedent(
31
+ """\
32
+ The default behavior is to not require explicit approval from a Code Owner.
33
+
34
+ Reasons for this Default
35
+ ------------------------
36
+ - Most repositories are not large enough to warrant specialized reviews by people with specific knowledge about different
37
+ areas of the code.
38
+
39
+ Reasons to Override this Default
40
+ --------------------------------
41
+ - You have a large repository with specialized areas of code that require reviews from specific people.
42
+
43
+ * Note: consider reducing the barrier to entry for new contributors by simplifying the design and/or adding automated tests that
44
+ catch common problems before they are introduced into the code base.
45
+ """,
46
+ ),
47
+ )
48
+
49
+ # ----------------------------------------------------------------------
50
+ @override
51
+ def _GetValue(
52
+ self,
53
+ rule: dict[str, Any],
54
+ ) -> Optional[bool]:
55
+ rule_type = rule.get("type")
56
+ if rule_type is None:
57
+ return None
58
+
59
+ if rule_type == "pull_request":
60
+ return rule["parameters"].get(self.github_ruleset_type, False)
61
+
62
+ return False
@@ -0,0 +1,39 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireCodeScanningResultsRule requirement."""
8
+
9
+ import textwrap
10
+
11
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
12
+
13
+
14
+ class RequireCodeScanningResultsRule(EnableRulesetRequirementImpl):
15
+ """Requirement which checks for the ruleset rule regarding code scanning results."""
16
+
17
+ def __init__(self) -> None:
18
+ super().__init__(
19
+ name="RequireCodeScanningResultsRule",
20
+ enabled_by_default=True,
21
+ dynamic_arg_name="no",
22
+ github_ruleset_type="code_scanning",
23
+ github_ruleset_value="Require code scanning results",
24
+ get_configuration_value_func=self._GetValue,
25
+ rationale=textwrap.dedent(
26
+ """\
27
+ The default behavior is to enable requiring the results of code scanning.
28
+
29
+ Reasons for this Default
30
+ ------------------------
31
+ - Code scanning can help prevent security vulnerabilities and errors in your code.
32
+
33
+ Reasons to Override this Default
34
+ --------------------------------
35
+ - Different users/organization may have different tools for scanning code for security vulnerabilities.
36
+ - Single-user repositories that don't use secrets may not need this feature.
37
+ """
38
+ ),
39
+ )
@@ -0,0 +1,59 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the RequireConversationResolutionRule object."""
8
+
9
+ import textwrap
10
+ from typing import Any, Optional
11
+
12
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
13
+
14
+ from RepoAuditor.Plugins.GitHub.Impl.EnableRulesetRequirementImpl import EnableRulesetRequirementImpl
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class RequireConversationResolutionRule(EnableRulesetRequirementImpl):
19
+ """Rule to require all review conversations to be marked as resolved on a pull request."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ name="RequireConversationResolutionRule",
25
+ enabled_by_default=True,
26
+ dynamic_arg_name="no",
27
+ github_ruleset_type="required_review_thread_resolution",
28
+ github_ruleset_value="Require a pull request before merging -> Require conversation resolution before merging",
29
+ get_configuration_value_func=self._GetValue,
30
+ rationale=textwrap.dedent(
31
+ """\
32
+ The default behavior is to require conversation resolution before merging a pull request.
33
+
34
+ Reasons for this Default
35
+ ------------------------
36
+ - Conversation resolution is an important part of the development process.
37
+ - Prevent the accidental merging of a pull request before changes associated with the comments have been made.
38
+
39
+ Reasons to Override this Default
40
+ --------------------------------
41
+ <unknown>
42
+ """,
43
+ ),
44
+ )
45
+
46
+ # ----------------------------------------------------------------------
47
+ @override
48
+ def _GetValue(
49
+ self,
50
+ rule: dict[str, Any],
51
+ ) -> Optional[bool]:
52
+ rule_type = rule.get("type")
53
+ if rule_type is None:
54
+ return None
55
+
56
+ if rule_type == "pull_request":
57
+ return rule["parameters"].get(self.github_ruleset_type, False)
58
+
59
+ return False