RepoAuditor 0.2.20__tar.gz → 0.2.21__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 (114) hide show
  1. {repoauditor-0.2.20 → repoauditor-0.2.21}/PKG-INFO +1 -1
  2. repoauditor-0.2.21/src/RepoAuditor/Plugins/GitHub/Module.py +33 -0
  3. {repoauditor-0.2.20/src/RepoAuditor/Plugins/GitHub → repoauditor-0.2.21/src/RepoAuditor/Plugins/GitHubBase}/Module.py +144 -158
  4. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHubCustomization/Module.py +5 -16
  5. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/__init__.py +1 -1
  6. repoauditor-0.2.21/src/RepoAuditor/py.typed +0 -0
  7. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugins/GitHubModule_UnitTest.py +2 -1
  8. {repoauditor-0.2.20 → repoauditor-0.2.21}/.copier-answers.yml +0 -0
  9. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/CODEOWNERS +0 -0
  10. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  12. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  13. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  14. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/actions/release_impl/action.yml +0 -0
  15. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/pull_request_template.md +0 -0
  16. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/release_sources.yaml +0 -0
  17. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/workflows/CICD.yml +0 -0
  18. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/workflows/CICD_impl.yml +0 -0
  19. {repoauditor-0.2.20 → repoauditor-0.2.21}/.github/workflows/codeql.yml +0 -0
  20. {repoauditor-0.2.20 → repoauditor-0.2.21}/.gitignore +0 -0
  21. {repoauditor-0.2.20 → repoauditor-0.2.21}/.pre-commit-config.yaml +0 -0
  22. {repoauditor-0.2.20 → repoauditor-0.2.21}/.python-version +0 -0
  23. {repoauditor-0.2.20 → repoauditor-0.2.21}/CODE_OF_CONDUCT.md +0 -0
  24. {repoauditor-0.2.20 → repoauditor-0.2.21}/CONTRIBUTING.md +0 -0
  25. {repoauditor-0.2.20 → repoauditor-0.2.21}/DEVELOPMENT.md +0 -0
  26. {repoauditor-0.2.20 → repoauditor-0.2.21}/GOVERNANCE.md +0 -0
  27. {repoauditor-0.2.20 → repoauditor-0.2.21}/LICENSE +0 -0
  28. {repoauditor-0.2.20 → repoauditor-0.2.21}/MAINTAINERS.md +0 -0
  29. {repoauditor-0.2.20 → repoauditor-0.2.21}/README.md +0 -0
  30. {repoauditor-0.2.20 → repoauditor-0.2.21}/SECURITY.md +0 -0
  31. {repoauditor-0.2.20 → repoauditor-0.2.21}/minisign_key.pub +0 -0
  32. {repoauditor-0.2.20 → repoauditor-0.2.21}/pyproject.toml +0 -0
  33. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/AutoGitSemVer.yaml +0 -0
  34. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/CommandLineProcessor.py +0 -0
  35. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/EntryPoint.py +0 -0
  36. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/ExecuteModules.py +0 -0
  37. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +0 -0
  38. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Impl/__init__.py +0 -0
  39. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Module.py +0 -0
  40. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugin.py +0 -0
  41. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +0 -0
  42. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
  43. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowForcePushes.py +0 -0
  44. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
  45. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +0 -0
  46. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +0 -0
  47. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +0 -0
  48. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
  49. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
  50. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
  51. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
  52. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
  53. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
  54. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
  55. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
  56. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
  57. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
  58. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
  59. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
  60. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
  61. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/Protected.py +0 -0
  62. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/__init__.py +0 -0
  63. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
  64. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +0 -0
  65. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
  66. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
  67. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
  68. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/AutoMerge.py +0 -0
  69. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DefaultBranch.py +0 -0
  70. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DeleteHeadBranches.py +0 -0
  71. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DependabotSecurityUpdates.py +0 -0
  72. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Description.py +0 -0
  73. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardEnableRequirementImpl.py +0 -0
  74. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardValueRequirementImpl.py +0 -0
  75. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/__init__.py +0 -0
  76. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/License.py +0 -0
  77. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommit.py +0 -0
  78. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommitMessage.py +0 -0
  79. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Private.py +0 -0
  80. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/RebaseMergeCommit.py +0 -0
  81. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanning.py +0 -0
  82. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanningPushProtection.py +0 -0
  83. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashCommitMerge.py +0 -0
  84. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashMergeCommitMessage.py +0 -0
  85. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
  86. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportDiscussions.py +0 -0
  87. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportIssues.py +0 -0
  88. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportProjects.py +0 -0
  89. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportWikis.py +0 -0
  90. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/TemplateRepository.py +0 -0
  91. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/WebCommitSignoff.py +0 -0
  92. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/__init__.py +0 -0
  93. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
  94. {repoauditor-0.2.20/src/RepoAuditor/Plugins/GitHubCustomization → repoauditor-0.2.21/src/RepoAuditor/Plugins/GitHubBase}/__init__.py +0 -0
  95. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHubCustomization/CustomizationQuery.py +0 -0
  96. {repoauditor-0.2.20/src/RepoAuditor/Plugins → repoauditor-0.2.21/src/RepoAuditor/Plugins/GitHubCustomization}/__init__.py +0 -0
  97. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHubCustomizationPlugin.py +0 -0
  98. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
  99. /repoauditor-0.2.20/src/RepoAuditor/py.typed → /repoauditor-0.2.21/src/RepoAuditor/Plugins/__init__.py +0 -0
  100. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Query.py +0 -0
  101. {repoauditor-0.2.20 → repoauditor-0.2.21}/src/RepoAuditor/Requirement.py +0 -0
  102. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/CommandLineProcessor_UnitTest.py +0 -0
  103. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/EntryPoint_UnitTest.py +0 -0
  104. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/ExecuteModules_UnitTest.py +0 -0
  105. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Module_UnitTest.py +0 -0
  106. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugin_UnitTest.py +0 -0
  107. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugins/GitHubCustomization_UnitTest.py +0 -0
  108. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugins/GitHub_EndToEndTest.py +0 -0
  109. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +0 -0
  110. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Plugins/utilities.py +0 -0
  111. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Query_UnitTest.py +0 -0
  112. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/Requirement_UnitTest.py +0 -0
  113. {repoauditor-0.2.20 → repoauditor-0.2.21}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
  114. {repoauditor-0.2.20 → repoauditor-0.2.21}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RepoAuditor
3
- Version: 0.2.20
3
+ Version: 0.2.21
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
@@ -0,0 +1,33 @@
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the GitHubModule object."""
8
+
9
+ from RepoAuditor.Module import ExecutionStyle
10
+ from RepoAuditor.Plugins.GitHubBase.Module import GitHubBaseModule
11
+
12
+ from .ClassicBranchProtectionQuery import ClassicBranchProtectionQuery
13
+ from .DefaultBranchQuery import DefaultBranchQuery
14
+ from .StandardQuery import StandardQuery
15
+
16
+
17
+ # ----------------------------------------------------------------------
18
+ class GitHubModule(GitHubBaseModule):
19
+ """Module for validating GitHub repository configuration settings."""
20
+
21
+ # ----------------------------------------------------------------------
22
+ def __init__(self) -> None:
23
+ super().__init__(
24
+ "GitHub",
25
+ "Validates GitHub configuration settings.",
26
+ ExecutionStyle.Parallel,
27
+ [
28
+ StandardQuery(),
29
+ DefaultBranchQuery(),
30
+ ClassicBranchProtectionQuery(),
31
+ ],
32
+ requires_explicit_include=True,
33
+ )
@@ -1,158 +1,144 @@
1
- # -------------------------------------------------------------------------------
2
- # |
3
- # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
- # | Distributed under the MIT License.
5
- # |
6
- # -------------------------------------------------------------------------------
7
- """Contains the GitHubModule object."""
8
-
9
- from pathlib import Path
10
- from typing import Any, Optional
11
- from urllib.parse import urlparse
12
-
13
- import requests
14
- import typer
15
-
16
- from dbrownell_Common.TyperEx import TypeDefinitionItemType # type: ignore[import-untyped]
17
- from dbrownell_Common.Types import override # type: ignore[import-untyped]
18
-
19
- from RepoAuditor.Module import ExecutionStyle, Module
20
-
21
- from .ClassicBranchProtectionQuery import ClassicBranchProtectionQuery
22
- from .DefaultBranchQuery import DefaultBranchQuery
23
- from .StandardQuery import StandardQuery
24
-
25
-
26
- # ----------------------------------------------------------------------
27
- class GitHubModule(Module):
28
- """Module for validating GitHub repository configuration settings."""
29
-
30
- # ----------------------------------------------------------------------
31
- def __init__(self) -> None:
32
- super().__init__(
33
- "GitHub",
34
- "Validates GitHub configuration settings.",
35
- ExecutionStyle.Parallel,
36
- [
37
- StandardQuery(),
38
- DefaultBranchQuery(),
39
- ClassicBranchProtectionQuery(),
40
- ],
41
- requires_explicit_include=True,
42
- )
43
-
44
- # ----------------------------------------------------------------------
45
- @override
46
- def GetDynamicArgDefinitions(self) -> dict[str, TypeDefinitionItemType]:
47
- """Get the definitions for the arguments to this requirement."""
48
- return {
49
- "url": (
50
- str,
51
- typer.Option(
52
- ...,
53
- help="[REQUIRED] Github URL (e.g. https://github.com/gt-sse-center/RepoAuditor)",
54
- ),
55
- ),
56
- "pat": (
57
- str,
58
- typer.Option(
59
- None,
60
- help="GitHub Personal Access Token (PAT) or path to a local file containing the PAT.",
61
- ),
62
- ),
63
- "branch": (
64
- str,
65
- typer.Option(
66
- None,
67
- help="Branch to evaluate. The default branch will be used if not specified.",
68
- ),
69
- ),
70
- }
71
-
72
- # ----------------------------------------------------------------------
73
- @override
74
- def GenerateInitialData(self, dynamic_args: dict[str, Any]) -> Optional[dict[str, Any]]:
75
- """Generate the initial data to be used in the `dynamic_args`, such as session info, etc."""
76
- # Create a GitHub API session
77
- dynamic_args["session"] = _GitHubSession(dynamic_args["url"], dynamic_args.get("pat"))
78
-
79
- return dynamic_args
80
-
81
-
82
- # ----------------------------------------------------------------------
83
- # |
84
- # | Private Types
85
- # |
86
- # ----------------------------------------------------------------------
87
- class _GitHubSession(requests.Session):
88
- """Session used to communicate with GitHub APIs."""
89
-
90
- # ----------------------------------------------------------------------
91
- def __init__(
92
- self,
93
- github_url: str,
94
- github_pat: Optional[str],
95
- *args,
96
- **kwargs,
97
- ) -> None:
98
- super().__init__(*args, **kwargs)
99
-
100
- self.headers.update(
101
- {
102
- "X-GitHub-Api-Version": "2022-11-28",
103
- "Accept": "application/vnd.github+json",
104
- },
105
- )
106
-
107
- if github_pat:
108
- potential_file = Path(github_pat)
109
-
110
- if potential_file.is_file():
111
- with potential_file.open("r") as f:
112
- github_pat = f.read().strip()
113
-
114
- self.headers["Authorization"] = f"Bearer {github_pat}"
115
-
116
- github_url = github_url.removesuffix("/")
117
-
118
- url_parts = urlparse(github_url)
119
- path_parts = url_parts.path.split("/")
120
-
121
- if len(path_parts) != 3:
122
- msg = f"'{github_url}' is not a valid GitHub repository URL."
123
- raise ValueError(msg)
124
-
125
- _, username, repo = path_parts
126
-
127
- if url_parts.netloc.lower() in ["github.com", "www.github.com"]:
128
- api_url = f"https://api.github.com/repos/{username}/{repo}"
129
- is_enterprise = False
130
- else:
131
- api_url = f"{url_parts.scheme}://{url_parts.netloc}/api/v3/orgs/{username}/repos/{repo}"
132
- is_enterprise = True
133
-
134
- self.github_url = github_url
135
- self.github_pat = github_pat
136
- self.github_username = username
137
- self.github_repository = repo
138
- self.api_url = api_url
139
- self.is_enterprise = is_enterprise
140
- self.has_pat = bool(github_pat)
141
-
142
- # ----------------------------------------------------------------------
143
- def request(
144
- self,
145
- method: str,
146
- url: str,
147
- *args,
148
- **kwargs,
149
- ) -> requests.Response:
150
- if url and not url.startswith("/"):
151
- url = f"/{url}"
152
-
153
- return super().request(
154
- method,
155
- f"{self.api_url}{url}",
156
- *args,
157
- **kwargs,
158
- )
1
+ # -------------------------------------------------------------------------------
2
+ # |
3
+ # | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
4
+ # | Distributed under the MIT License.
5
+ # |
6
+ # -------------------------------------------------------------------------------
7
+ """Contains the GitHubBaseModule object."""
8
+
9
+ from pathlib import Path
10
+ from typing import Any, Optional
11
+ from urllib.parse import urlparse
12
+
13
+ import requests
14
+ import typer
15
+
16
+ from dbrownell_Common.TyperEx import TypeDefinitionItemType # type: ignore[import-untyped]
17
+ from dbrownell_Common.Types import override # type: ignore[import-untyped]
18
+
19
+ from RepoAuditor.Module import Module
20
+
21
+
22
+ # ----------------------------------------------------------------------
23
+ class GitHubBaseModule(Module):
24
+ """Module for common GitHub settings which can be inherited by various GitHub plugins."""
25
+
26
+ # ----------------------------------------------------------------------
27
+ # The __init__ method is inherited from the Module class
28
+ # and does not need to be overriden.
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 URL (e.g. https://github.com/gt-sse-center/RepoAuditor)",
40
+ ),
41
+ ),
42
+ "pat": (
43
+ str,
44
+ typer.Option(
45
+ None,
46
+ help="GitHub Personal Access Token (PAT) or path to a local file containing the PAT.",
47
+ ),
48
+ ),
49
+ "branch": (
50
+ str,
51
+ typer.Option(
52
+ None,
53
+ help="Branch to evaluate. The default branch will be used if not specified.",
54
+ ),
55
+ ),
56
+ }
57
+
58
+ # ----------------------------------------------------------------------
59
+ @override
60
+ def GenerateInitialData(self, dynamic_args: dict[str, Any]) -> Optional[dict[str, Any]]:
61
+ """Generate the initial data to be used in the `dynamic_args`, such as session info, etc."""
62
+ # Create a GitHub API session
63
+ dynamic_args["session"] = _GitHubSession(dynamic_args["url"], dynamic_args.get("pat"))
64
+
65
+ return dynamic_args
66
+
67
+
68
+ # ----------------------------------------------------------------------
69
+ # |
70
+ # | Private Types
71
+ # |
72
+ # ----------------------------------------------------------------------
73
+ class _GitHubSession(requests.Session):
74
+ """Session used to communicate with GitHub APIs."""
75
+
76
+ # ----------------------------------------------------------------------
77
+ def __init__(
78
+ self,
79
+ github_url: str,
80
+ github_pat: Optional[str],
81
+ *args,
82
+ **kwargs,
83
+ ) -> None:
84
+ super().__init__(*args, **kwargs)
85
+
86
+ self.headers.update(
87
+ {
88
+ "X-GitHub-Api-Version": "2022-11-28",
89
+ "Accept": "application/vnd.github+json",
90
+ },
91
+ )
92
+
93
+ if github_pat:
94
+ potential_file = Path(github_pat)
95
+
96
+ if potential_file.is_file():
97
+ with potential_file.open("r") as f:
98
+ github_pat = f.read().strip()
99
+
100
+ self.headers["Authorization"] = f"Bearer {github_pat}"
101
+
102
+ github_url = github_url.removesuffix("/")
103
+
104
+ url_parts = urlparse(github_url)
105
+ path_parts = url_parts.path.split("/")
106
+
107
+ if len(path_parts) != 3:
108
+ msg = f"'{github_url}' is not a valid GitHub repository URL."
109
+ raise ValueError(msg)
110
+
111
+ _, username, repo = path_parts
112
+
113
+ if url_parts.netloc.lower() in ["github.com", "www.github.com"]:
114
+ api_url = f"https://api.github.com/repos/{username}/{repo}"
115
+ is_enterprise = False
116
+ else:
117
+ api_url = f"{url_parts.scheme}://{url_parts.netloc}/api/v3/orgs/{username}/repos/{repo}"
118
+ is_enterprise = True
119
+
120
+ self.github_url = github_url
121
+ self.github_pat = github_pat
122
+ self.github_username = username
123
+ self.github_repository = repo
124
+ self.api_url = api_url
125
+ self.is_enterprise = is_enterprise
126
+ self.has_pat = bool(github_pat)
127
+
128
+ # ----------------------------------------------------------------------
129
+ def request(
130
+ self,
131
+ method: str,
132
+ url: str,
133
+ *args,
134
+ **kwargs,
135
+ ) -> requests.Response:
136
+ if url and not url.startswith("/"):
137
+ url = f"/{url}"
138
+
139
+ return super().request(
140
+ method,
141
+ f"{self.api_url}{url}",
142
+ *args,
143
+ **kwargs,
144
+ )
@@ -6,13 +6,14 @@
6
6
  # -------------------------------------------------------------------------------
7
7
  """Contains the GitHubCustomizationModule object."""
8
8
 
9
- from typing import Any, Optional
10
- from RepoAuditor.Module import ExecutionStyle, Module
11
- from dbrownell_Common.TyperEx import TypeDefinitionItemType
9
+ from typing import Any
12
10
  from dbrownell_Common.Types import override
13
11
 
12
+ from RepoAuditor.Module import ExecutionStyle
13
+ from RepoAuditor.Plugins.GitHubBase.Module import GitHubBaseModule
14
14
 
15
- class GitHubCustomizationModule(Module):
15
+
16
+ class GitHubCustomizationModule(GitHubBaseModule):
16
17
  """Module that validates GitHub repository customization files."""
17
18
 
18
19
  def __init__(self) -> None:
@@ -24,18 +25,6 @@ class GitHubCustomizationModule(Module):
24
25
  requires_explicit_include=False,
25
26
  )
26
27
 
27
- @override
28
- def GetDynamicArgDefinitions(self) -> dict[str, TypeDefinitionItemType]:
29
- """Return the dynamic arguments for this module."""
30
- # Return an empty dictionary as we don't have any dynamic args yet
31
- return {}
32
-
33
- @override
34
- def GenerateInitialData(self, dynamic_args: dict[str, Any]) -> Optional[dict[str, Any]]: # noqa: ARG002
35
- """Generate initial data for queries to use."""
36
- # Return an empty dictionary as we don't have any initial data yet
37
- return {}
38
-
39
28
  @override
40
29
  def Cleanup(self, dynamic_args: dict[str, Any]) -> None:
41
30
  """Clean up any resources created during execution."""
@@ -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.20"
6
+ __version__ = "0.2.21"
File without changes
@@ -11,7 +11,8 @@ from pathlib import Path
11
11
  import pytest
12
12
  from pyfakefs.fake_filesystem_unittest import TestCase as FakeFSTestCase
13
13
 
14
- from RepoAuditor.Plugins.GitHub.Module import GitHubModule, _GitHubSession
14
+ from RepoAuditor.Plugins.GitHub.Module import GitHubModule
15
+ from RepoAuditor.Plugins.GitHubBase.Module import _GitHubSession
15
16
 
16
17
 
17
18
  class TestGitHubSession(FakeFSTestCase):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes