openhound-github 0.6.5__tar.gz → 0.6.7__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.
- {openhound_github-0.6.5 → openhound_github-0.6.7}/PKG-INFO +16 -1
- {openhound_github-0.6.5 → openhound_github-0.6.7}/README.md +15 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/auth.py +10 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/helpers.py +201 -1
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/resources/enterprise.py +30 -12
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/resources/organization.py +63 -41
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/source.py +169 -32
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_github_app_retry.py +12 -0
- openhound_github-0.6.7/tests/test_repository_rulesets.py +429 -0
- openhound_github-0.6.7/tests/test_source_endpoints.py +474 -0
- openhound_github-0.6.5/tests/test_repository_rulesets.py +0 -241
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/CODE_OF_CONDUCT.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/CONTRIBUTING.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GOVERNANCE.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-COC-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-CONTRIB-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-GOV-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-LIC-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/GitHub-SEC-Header.png +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/SECURITY.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/SO-Dark.svg +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/SO-FOSS-Dark.svg +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/SO-FOSS-Light.svg +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/SO-Light.svg +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/workflows/publish.yml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/workflows/release-on-merge.yml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.github/workflows/validate-branch.yml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.gitignore +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.gitmodules +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/.pre-commit-config.yaml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/LICENSE.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AddAssignee.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AddCollaborator.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AddLabel.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AddMember.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AdminTo.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ApprovesDeploymentTo.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_AssignedTo.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_BypassBranchProtection.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_BypassPullRequestAllowances.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CallsWorkflow.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanAccess.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanAssumeIdentity.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanCreateBranch.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanCreateEnvironment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanCreateRepositoryWithRunnerAccess.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanDeployToEnvironment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanEditEnvironment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanEditProtection.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanPwnRequest.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanReadSecretScanningAlert.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanUseRunner.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CanWriteBranch.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CloseDiscussion.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CloseIssue.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ClosePullRequest.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_Contains.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ConvertIssuesToDiscussions.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CreateDiscussionCategory.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CreateRepository.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CreateSoloMergeQueueEntry.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CreateTag.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_CreateTeam.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeleteAlertsCodeScanning.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeleteDiscussion.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeleteDiscussionComment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeleteIssue.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeleteTag.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DependsOn.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_DeploysTo.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditCategoryOnDiscussion.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditDiscussionCategory.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditDiscussionComment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditRepoAnnouncementBanners.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditRepoCustomPropertiesValues.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditRepoMetadata.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_EditRepoProtections.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasBaseRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasBranch.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasEnvironment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasExternalIdentity.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasJob.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasMember.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasPersonalAccessToken.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasPersonalAccessTokenRequest.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasRunner.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasSamlIdentityProvider.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasSecret.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasStep.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasVariable.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_HasWorkflow.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_InheritedFrom.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_InstalledAs.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_InviteMember.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_IsEligibleFor.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_JumpMergeQueue.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageDeployKeys.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageDiscussionBadges.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageOrganizationWebhooks.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageRepoSecurityProducts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageSecurityProducts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageSettingsMergeTypes.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageSettingsPages.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageSettingsProjects.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageSettingsWiki.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageTopics.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ManageWebhooks.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_MapsToUser.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_MarkAsDuplicate.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_MatchesEnvironmentPolicy.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_MemberOf.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_OrgBypassCodeScanningDismissalRequests.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_OrgBypassSecretScanningClosureRequests.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_OrgReviewAndManageSecretScanningBypassRequests.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_OrgReviewAndManageSecretScanningClosureRequests.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_Owns.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ProtectedBy.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_PushProtectedBranch.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReadCodeScanning.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReadOrganizationActionsUsageMetrics.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReadOrganizationCustomOrgRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReadOrganizationCustomRepoRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReadRepoContents.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_RemoveAssignee.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_RemoveLabel.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReopenDiscussion.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReopenIssue.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ReopenPullRequest.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_RequestPrReview.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ResolveDependabotAlerts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ResolveSecretScanningAlerts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_RestrictionsCanPush.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_RunOrgMigration.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_SetInteractionLimits.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_SetIssueType.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_SetMilestone.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_SetSocialPreview.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_SyncedTo.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ToggleDiscussionAnswer.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ToggleDiscussionCommentMinimize.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_TransferRepository.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_UsesSecret.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_UsesVariable.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ValidToken.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ViewDependabotAlerts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_ViewSecretScanningAlerts.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteCodeScanning.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationActionsSecrets.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationActionsSettings.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationActionsVariables.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationCustomOrgRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationCustomRepoRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteOrganizationNetworkConfigurations.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteRepoContents.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/edges/GH_WriteRepoPullRequests.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_App.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_AppInstallation.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Branch.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_BranchProtectionRule.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_EnterpriseRunner.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_EnterpriseRunnerGroup.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Environment.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_EnvironmentBranchPolicy.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_EnvironmentSecret.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_EnvironmentVariable.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_ExternalIdentity.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_OrgRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_OrgRunner.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_OrgRunnerGroup.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_OrgSecret.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_OrgVariable.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Organization.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_PersonalAccessToken.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_PersonalAccessTokenRequest.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_RepoRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_RepoRunner.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_RepoSecret.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_RepoVariable.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Repository.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_SamlIdentityProvider.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_SecretScanningAlert.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Team.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_TeamRole.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_User.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_Workflow.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_WorkflowJob.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/descriptions/nodes/GH_WorkflowStep.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/docs/og-docs.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-all-repo-admin-role.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-app-installations-all-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-apps-all-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-external-identities-owners.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-organizations.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-owner-users.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-owners-role.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-pats-all-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-privilege-escalation-roles.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-privilege-escalation-users.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/privilege_zone_rules/t0-saml-identity-providers.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/README.md +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/actions-sha-pinning-not-required.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/active-leaked-secrets.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/advanced-security-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/all-actions-allowed.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/app-installations-all-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-admins-not-enforced.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-deletions-allowed.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-force-pushes.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-no-code-owner-reviews.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-no-pr-reviews.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-no-status-checks.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-self-approval.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/branch-protection-stale-reviews.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/bypass-pr-requirements.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/dangerous-branch-perms.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/default-repository-permissions.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/demo-sso-to-cloud-round-trip.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/dependabot-alerts-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/dependabot-updates-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/dependency-graph-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/environments-admin-bypass.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/expired-pats.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/external-identities-without-scim.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/github-to-azure-identity.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/global-repo-perms.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/hybrid-identities.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-change-repo-visibility.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-create-pages.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-create-public-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-delete-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-fork-private-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/members-can-invite-outside-collaborators.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/org-owners.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/orgs-without-2fa.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/pats-all-repo-access.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/pending-pat-requests.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/private-repos-forking-allowed.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/privileged-custom-org-roles.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/privileged-hybrid-identities.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/public-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/push-protection-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/push-to-protected-branches.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/repos-secret-scanning-disabled.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/repos-vulnerable-to-workflow-secret-exfil.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/repository-workflows.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/saml-configuration.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/secret-scanning-alerts.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/secret-scanning-disabled-new-repos.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/secrets-reachable-by-user.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/team-membership-admin.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/team-structure.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/unprotected-branches.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/unprotected-default-branch-with-workflow.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/unprotected-default-branches.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/saved_searches/web-commit-signoff-not-required.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/extension/schema.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/justfile +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/pyproject.toml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/main.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/__init__.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/extension.yaml +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/graph.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/graphql.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/kinds/edges.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/kinds/nodes.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/lookup.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/main.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/__init__.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/actions_permission.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/app_installation.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/branch.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/branch_pr_bypass_allowance.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/branch_protection_rule.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/branch_push_allowance.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_admin.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_helpers.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_managed_user.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_member.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_organization.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_role.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_role_team.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_role_user.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_team.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_team_member.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_team_organization.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_team_role.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/enterprise_user.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/env_secret.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/env_variable.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/environment.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/environment_branch_policy.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/external_identity.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org_role.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org_role_member.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org_role_team.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org_secret.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/org_variable.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/personal_access_token.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/personal_access_token_access.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/personal_access_token_request.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/projected_enterprise_team.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/repo_role_assignment.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/repository.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/repository_role.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/repository_secret.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/repository_variable.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/runner.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/saml_assertion_consumer_service.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/saml_helpers.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/saml_issuer.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/saml_provider.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/saml_service_provider.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/scim_user.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/secret_scanning_alert.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/team.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/team_member.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/team_role.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/user.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/workflow.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/workflow_job.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/models/workflow_step.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/resources/__init__.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/runner_ids.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/transforms.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_app_auth.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_branch_collection_gate.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_branch_protection_traversability.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/actions-permissions.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/actionsecrets.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/app.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/appinstalls.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/branch-policies.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/branch-prot-rules.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/branches.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/custom-roles.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/environments.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org-pat-request.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org-pat.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org-role-teams.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org-role-users.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org-roles.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/org.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/pat-repositories.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/repo-collaborators.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/repo-teams.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/repositories.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/scimusers.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/secrets.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/secretscanningalert.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/selected-org-secrets.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/variables.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_data/api/workflows.json +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_enterprise_capabilities.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_enterprise_organization.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_enterprise_resources.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_environment_model.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_environment_resources.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_environment_reviewer_lookup.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_error_resilience.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_github_rest_client.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_github_retry.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_helpers.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_lookup.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_org_scim_resources.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_org_secret_models.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_runner_ids.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_runner_models.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_runner_resources.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_saml_helpers.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_saml_models.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_scim_models.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_source_org_canonicalization.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_variable_models.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/tests/test_workflow_model.py +0 -0
- {openhound_github-0.6.5 → openhound_github-0.6.7}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: openhound-github
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: Github collector for OpenHound
|
|
5
5
|
Author-email: "jdreijer@specterops.io" <jdreijer@specterops.io>, Jared Atkinson <jatkinson@specterops.io>
|
|
6
6
|
License-File: LICENSE.md
|
|
@@ -51,6 +51,21 @@ Enterprise GitHub App credentials accept either `client_id` or `app_id` as the
|
|
|
51
51
|
JWT issuer. When both are configured, `client_id` is preferred. At least one
|
|
52
52
|
identifier must be supplied together with `key_path` and `enterprise_name`.
|
|
53
53
|
|
|
54
|
+
### GitHub Enterprise Server endpoints
|
|
55
|
+
|
|
56
|
+
GitHub.com is the default deployment and does not require endpoint configuration.
|
|
57
|
+
To collect from GitHub Enterprise Server, set both API endpoints in `config.toml`:
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
[sources.github]
|
|
61
|
+
rest_api_url = "https://ghe.example/api/v3"
|
|
62
|
+
graphql_url = "https://ghe.example/api/graphql"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Both values must be provided together when overriding the GitHub.com defaults.
|
|
66
|
+
Endpoint URLs must use HTTPS and share the same origin. GitHub App
|
|
67
|
+
`credentials.api_uri` may override only the path on that same origin.
|
|
68
|
+
|
|
54
69
|
### Enterprise SCIM and hybrid correlations
|
|
55
70
|
|
|
56
71
|
A token with enterprise SCIM access is used to collect both `/scim/v2/enterprises/{enterprise}/Users` and `/scim/v2/enterprises/{enterprise}/Groups`. The collector emits normalized `SCIM_Organization`, `SCIM_User`, and `SCIM_Group` nodes plus `SCIM_Contains`, `SCIM_MemberOf`, and `SCIM_Provisioned` relationships. Install the BloodHound SCIM extension alongside this extension to register the shared SCIM kinds.
|
|
@@ -40,6 +40,21 @@ Enterprise GitHub App credentials accept either `client_id` or `app_id` as the
|
|
|
40
40
|
JWT issuer. When both are configured, `client_id` is preferred. At least one
|
|
41
41
|
identifier must be supplied together with `key_path` and `enterprise_name`.
|
|
42
42
|
|
|
43
|
+
### GitHub Enterprise Server endpoints
|
|
44
|
+
|
|
45
|
+
GitHub.com is the default deployment and does not require endpoint configuration.
|
|
46
|
+
To collect from GitHub Enterprise Server, set both API endpoints in `config.toml`:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
[sources.github]
|
|
50
|
+
rest_api_url = "https://ghe.example/api/v3"
|
|
51
|
+
graphql_url = "https://ghe.example/api/graphql"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Both values must be provided together when overriding the GitHub.com defaults.
|
|
55
|
+
Endpoint URLs must use HTTPS and share the same origin. GitHub App
|
|
56
|
+
`credentials.api_uri` may override only the path on that same origin.
|
|
57
|
+
|
|
43
58
|
### Enterprise SCIM and hybrid correlations
|
|
44
59
|
|
|
45
60
|
A token with enterprise SCIM access is used to collect both `/scim/v2/enterprises/{enterprise}/Users` and `/scim/v2/enterprises/{enterprise}/Groups`. The collector emits normalized `SCIM_Organization`, `SCIM_User`, and `SCIM_Group` nodes plus `SCIM_Contains`, `SCIM_MemberOf`, and `SCIM_Provisioned` relationships. Install the BloodHound SCIM extension alongside this extension to register the shared SCIM kinds.
|
|
@@ -293,6 +293,16 @@ class GitHubAppInstallationAuth(AuthConfigBase):
|
|
|
293
293
|
return True
|
|
294
294
|
|
|
295
295
|
def __call__(self, request: requests.PreparedRequest) -> requests.PreparedRequest:
|
|
296
|
+
try:
|
|
297
|
+
request_origin = _normalized_http_origin(
|
|
298
|
+
request.url or "", allow_query=True
|
|
299
|
+
)
|
|
300
|
+
except ValueError:
|
|
301
|
+
return request
|
|
302
|
+
|
|
303
|
+
if request_origin != self._api_origin:
|
|
304
|
+
return request
|
|
305
|
+
|
|
296
306
|
request.headers["Authorization"] = f"Bearer {self.token()}"
|
|
297
307
|
return request
|
|
298
308
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Iterator
|
|
4
|
+
from typing import Any, Optional, overload
|
|
4
5
|
from urllib.parse import urlparse
|
|
5
6
|
|
|
6
7
|
from dlt.common import jsonpath
|
|
7
8
|
from dlt.sources.helpers import requests
|
|
8
9
|
from dlt.sources.helpers.rest_client.auth import AuthConfigBase
|
|
10
|
+
from dlt.sources.helpers.rest_client.client import RESTClient
|
|
9
11
|
from dlt.sources.helpers.rest_client.paginators import (
|
|
10
12
|
JSONResponseCursorPaginator,
|
|
11
13
|
)
|
|
@@ -15,11 +17,54 @@ from openhound_github.auth import GitHubAppInstallationAuth
|
|
|
15
17
|
|
|
16
18
|
logger = logging.getLogger(__name__)
|
|
17
19
|
|
|
20
|
+
DEFAULT_GITHUB_REST_API_URL = "https://api.github.com"
|
|
21
|
+
DEFAULT_GITHUB_GRAPHQL_URL = "https://api.github.com/graphql"
|
|
22
|
+
|
|
18
23
|
|
|
19
24
|
class GraphQLPaginationError(RuntimeError):
|
|
20
25
|
pass
|
|
21
26
|
|
|
22
27
|
|
|
28
|
+
@overload
|
|
29
|
+
def graphql_client_and_path(
|
|
30
|
+
rest_client: RESTClient,
|
|
31
|
+
graphql_client: RESTClient | None,
|
|
32
|
+
) -> tuple[RESTClient, str]: ...
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@overload
|
|
36
|
+
def graphql_client_and_path(
|
|
37
|
+
rest_client: RESTClient | None,
|
|
38
|
+
graphql_client: RESTClient | None,
|
|
39
|
+
) -> tuple[RESTClient | None, str]: ...
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def graphql_client_and_path(
|
|
43
|
+
rest_client: RESTClient | None,
|
|
44
|
+
graphql_client: RESTClient | None,
|
|
45
|
+
) -> tuple[RESTClient | None, str]:
|
|
46
|
+
"""Return the configured GraphQL client and its request path."""
|
|
47
|
+
if graphql_client:
|
|
48
|
+
return graphql_client, ""
|
|
49
|
+
return rest_client, "/graphql"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class AdaptiveGraphQLPageError(RuntimeError):
|
|
53
|
+
"""A terminal GraphQL page failure with adaptive pagination context."""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
*,
|
|
58
|
+
cursor: str | None,
|
|
59
|
+
page_size: int,
|
|
60
|
+
error: BaseException,
|
|
61
|
+
) -> None:
|
|
62
|
+
super().__init__(str(error))
|
|
63
|
+
self.cursor = cursor
|
|
64
|
+
self.page_size = page_size
|
|
65
|
+
self.error = error
|
|
66
|
+
|
|
67
|
+
|
|
23
68
|
def scim_skip_reason(exception: BaseException) -> str | None:
|
|
24
69
|
"""Return a user-facing reason for expected SCIM API unavailability."""
|
|
25
70
|
if not isinstance(exception, requests.HTTPError) or exception.response is None:
|
|
@@ -56,6 +101,10 @@ class GraphQLCursorPaginator(JSONResponseCursorPaginator):
|
|
|
56
101
|
self.has_next_field = has_next_field
|
|
57
102
|
self.allow_missing_page_info = allow_missing_page_info
|
|
58
103
|
|
|
104
|
+
@property
|
|
105
|
+
def next_cursor(self) -> str | None:
|
|
106
|
+
return self._next_reference
|
|
107
|
+
|
|
59
108
|
def init_request(self, request: "Request") -> None:
|
|
60
109
|
self._next_reference = None
|
|
61
110
|
self._has_next_page = True
|
|
@@ -149,6 +198,157 @@ class GraphQLCursorPaginator(JSONResponseCursorPaginator):
|
|
|
149
198
|
variables[self.cursor_variable] = self._next_reference
|
|
150
199
|
|
|
151
200
|
|
|
201
|
+
def _graphql_gateway_status(exception: BaseException) -> int | None:
|
|
202
|
+
if not isinstance(exception, requests.HTTPError) or exception.response is None:
|
|
203
|
+
return None
|
|
204
|
+
|
|
205
|
+
status_code = exception.response.status_code
|
|
206
|
+
if status_code in (502, 504):
|
|
207
|
+
return status_code
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def adaptive_graphql_paginate(
|
|
212
|
+
client: RESTClient,
|
|
213
|
+
*,
|
|
214
|
+
graphql_path: str = "/graphql",
|
|
215
|
+
query: str,
|
|
216
|
+
variables: dict[str, Any],
|
|
217
|
+
page_info_path: str,
|
|
218
|
+
cursor_variable: str = "after",
|
|
219
|
+
page_size_variable: str = "count",
|
|
220
|
+
page_sizes: tuple[int, ...] = (100, 50, 25),
|
|
221
|
+
allow_missing_page_info: bool = False,
|
|
222
|
+
resource_name: str = "graphql",
|
|
223
|
+
scope_name: str | None = None,
|
|
224
|
+
scope_value: str | None = None,
|
|
225
|
+
log: logging.Logger | None = None,
|
|
226
|
+
) -> Iterator[dict[str, Any]]:
|
|
227
|
+
"""Yield GraphQL pages while adapting connection size after gateway failures.
|
|
228
|
+
|
|
229
|
+
The underlying HTTP session still owns ordinary request retries. This helper
|
|
230
|
+
handles the remaining terminal 502/504 case by retrying the same cursor with
|
|
231
|
+
progressively smaller connection sizes.
|
|
232
|
+
"""
|
|
233
|
+
if not page_sizes or any(page_size <= 0 for page_size in page_sizes):
|
|
234
|
+
raise ValueError("page_sizes must contain positive integers")
|
|
235
|
+
if tuple(sorted(set(page_sizes), reverse=True)) != page_sizes:
|
|
236
|
+
raise ValueError("page_sizes must be unique and in descending order")
|
|
237
|
+
|
|
238
|
+
logger_instance = log or logger
|
|
239
|
+
base_page_size = page_sizes[0]
|
|
240
|
+
cursor = variables.get(cursor_variable)
|
|
241
|
+
if cursor is not None and not isinstance(cursor, str):
|
|
242
|
+
raise ValueError(f"{cursor_variable} must be a string or None")
|
|
243
|
+
|
|
244
|
+
stable_page_size = base_page_size
|
|
245
|
+
probe_base_page_size = False
|
|
246
|
+
|
|
247
|
+
while True:
|
|
248
|
+
if stable_page_size == base_page_size:
|
|
249
|
+
candidate_sizes = page_sizes
|
|
250
|
+
probing_base_page_size = False
|
|
251
|
+
elif probe_base_page_size:
|
|
252
|
+
candidate_sizes = (base_page_size,) + tuple(
|
|
253
|
+
page_size
|
|
254
|
+
for page_size in page_sizes
|
|
255
|
+
if page_size <= stable_page_size
|
|
256
|
+
)
|
|
257
|
+
probing_base_page_size = True
|
|
258
|
+
else:
|
|
259
|
+
candidate_sizes = tuple(
|
|
260
|
+
page_size
|
|
261
|
+
for page_size in page_sizes
|
|
262
|
+
if page_size <= stable_page_size
|
|
263
|
+
)
|
|
264
|
+
probing_base_page_size = False
|
|
265
|
+
|
|
266
|
+
page_data: dict[str, Any] | None = None
|
|
267
|
+
paginator: GraphQLCursorPaginator | None = None
|
|
268
|
+
successful_page_size: int | None = None
|
|
269
|
+
|
|
270
|
+
for index, page_size in enumerate(candidate_sizes):
|
|
271
|
+
request_variables = {
|
|
272
|
+
**variables,
|
|
273
|
+
cursor_variable: cursor,
|
|
274
|
+
page_size_variable: page_size,
|
|
275
|
+
}
|
|
276
|
+
try:
|
|
277
|
+
response = client.post(
|
|
278
|
+
graphql_path,
|
|
279
|
+
json={"query": query, "variables": request_variables},
|
|
280
|
+
)
|
|
281
|
+
response.raise_for_status()
|
|
282
|
+
response_json = response.json()
|
|
283
|
+
paginator = GraphQLCursorPaginator(
|
|
284
|
+
page_info_path=page_info_path,
|
|
285
|
+
cursor_variable=cursor_variable,
|
|
286
|
+
cursor_field="endCursor",
|
|
287
|
+
has_next_field="hasNextPage",
|
|
288
|
+
allow_missing_page_info=allow_missing_page_info,
|
|
289
|
+
)
|
|
290
|
+
paginator.update_state(response)
|
|
291
|
+
page_data = response_json.get("data")
|
|
292
|
+
if not isinstance(page_data, dict):
|
|
293
|
+
raise GraphQLPaginationError(
|
|
294
|
+
"GraphQL response data must be an object"
|
|
295
|
+
)
|
|
296
|
+
successful_page_size = page_size
|
|
297
|
+
break
|
|
298
|
+
except Exception as error:
|
|
299
|
+
status_code = _graphql_gateway_status(error)
|
|
300
|
+
next_page_size = (
|
|
301
|
+
candidate_sizes[index + 1]
|
|
302
|
+
if status_code is not None and index + 1 < len(candidate_sizes)
|
|
303
|
+
else None
|
|
304
|
+
)
|
|
305
|
+
if next_page_size is not None:
|
|
306
|
+
scope = (
|
|
307
|
+
f" {scope_name} '{scope_value}'"
|
|
308
|
+
if scope_name and scope_value
|
|
309
|
+
else ""
|
|
310
|
+
)
|
|
311
|
+
logger_instance.warning(
|
|
312
|
+
"Adaptive GraphQL pagination for resource '%s'%s retrying "
|
|
313
|
+
"cursor %r with page size %d after HTTP %d at page size %d",
|
|
314
|
+
resource_name,
|
|
315
|
+
scope,
|
|
316
|
+
cursor,
|
|
317
|
+
next_page_size,
|
|
318
|
+
status_code,
|
|
319
|
+
page_size,
|
|
320
|
+
)
|
|
321
|
+
continue
|
|
322
|
+
raise AdaptiveGraphQLPageError(
|
|
323
|
+
cursor=cursor,
|
|
324
|
+
page_size=page_size,
|
|
325
|
+
error=error,
|
|
326
|
+
) from error
|
|
327
|
+
|
|
328
|
+
if page_data is None or paginator is None or successful_page_size is None:
|
|
329
|
+
raise GraphQLPaginationError("GraphQL page did not produce data")
|
|
330
|
+
|
|
331
|
+
yield page_data
|
|
332
|
+
|
|
333
|
+
if successful_page_size == base_page_size:
|
|
334
|
+
stable_page_size = base_page_size
|
|
335
|
+
probe_base_page_size = False
|
|
336
|
+
elif stable_page_size == base_page_size:
|
|
337
|
+
stable_page_size = successful_page_size
|
|
338
|
+
probe_base_page_size = True
|
|
339
|
+
elif probing_base_page_size:
|
|
340
|
+
stable_page_size = successful_page_size
|
|
341
|
+
probe_base_page_size = False
|
|
342
|
+
elif successful_page_size < stable_page_size:
|
|
343
|
+
stable_page_size = successful_page_size
|
|
344
|
+
probe_base_page_size = False
|
|
345
|
+
|
|
346
|
+
if not paginator.has_next_page:
|
|
347
|
+
break
|
|
348
|
+
|
|
349
|
+
cursor = paginator.next_cursor
|
|
350
|
+
|
|
351
|
+
|
|
152
352
|
def _response_message(response: requests.Response) -> str:
|
|
153
353
|
try:
|
|
154
354
|
response_data = response.json()
|
{openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/resources/enterprise.py
RENAMED
|
@@ -11,7 +11,11 @@ from openhound_github.graphql import (
|
|
|
11
11
|
ENTERPRISE_QUERY,
|
|
12
12
|
ENTERPRISE_SAML_QUERY,
|
|
13
13
|
)
|
|
14
|
-
from openhound_github.helpers import
|
|
14
|
+
from openhound_github.helpers import (
|
|
15
|
+
GraphQLCursorPaginator,
|
|
16
|
+
graphql_client_and_path,
|
|
17
|
+
scim_skip_reason,
|
|
18
|
+
)
|
|
15
19
|
from openhound_github.main import app
|
|
16
20
|
from openhound_github.models import (
|
|
17
21
|
BaseUser,
|
|
@@ -53,7 +57,9 @@ class SourceContext:
|
|
|
53
57
|
"""Shared context for GitHub API access."""
|
|
54
58
|
|
|
55
59
|
client: RESTClient
|
|
60
|
+
graphql_client: RESTClient | None = None
|
|
56
61
|
sso_client: RESTClient | None = None
|
|
62
|
+
sso_graphql_client: RESTClient | None = None
|
|
57
63
|
org_name: str | None = None
|
|
58
64
|
enterprise_name: str | None = None
|
|
59
65
|
emit_legacy_scim_correlations: bool = False
|
|
@@ -61,6 +67,14 @@ class SourceContext:
|
|
|
61
67
|
github_web_origin: str = DEFAULT_GITHUB_WEB_ORIGIN
|
|
62
68
|
|
|
63
69
|
|
|
70
|
+
def _graphql_client(ctx: SourceContext) -> tuple[RESTClient, str]:
|
|
71
|
+
return graphql_client_and_path(ctx.client, ctx.graphql_client)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _sso_graphql_client(ctx: SourceContext) -> tuple[RESTClient | None, str]:
|
|
75
|
+
return graphql_client_and_path(ctx.sso_client, ctx.sso_graphql_client)
|
|
76
|
+
|
|
77
|
+
|
|
64
78
|
def iter_enterprise_scim_resources(
|
|
65
79
|
client: RESTClient,
|
|
66
80
|
enterprise_slug: str,
|
|
@@ -111,8 +125,9 @@ def enterprise(ctx: SourceContext):
|
|
|
111
125
|
"variables": {"slug": ctx.enterprise_name, "after": None},
|
|
112
126
|
}
|
|
113
127
|
|
|
128
|
+
client, graphql_path = _graphql_client(ctx)
|
|
114
129
|
try:
|
|
115
|
-
response =
|
|
130
|
+
response = client.post(graphql_path, json=data).json()
|
|
116
131
|
page_enterprise = (response.get("data") or {}).get("enterprise")
|
|
117
132
|
if page_enterprise:
|
|
118
133
|
yield page_enterprise
|
|
@@ -139,9 +154,10 @@ def enterprise_organizations(enterprise_data: Enterprise, ctx: SourceContext):
|
|
|
139
154
|
"variables": {"slug": ctx.enterprise_name, "after": None},
|
|
140
155
|
}
|
|
141
156
|
|
|
157
|
+
client, graphql_path = _graphql_client(ctx)
|
|
142
158
|
try:
|
|
143
|
-
for page_data in
|
|
144
|
-
|
|
159
|
+
for page_data in client.paginate(
|
|
160
|
+
graphql_path,
|
|
145
161
|
method="POST",
|
|
146
162
|
json=data,
|
|
147
163
|
paginator=paginator,
|
|
@@ -263,8 +279,9 @@ def enterprise_members(enterprise_data: Enterprise, ctx: SourceContext):
|
|
|
263
279
|
"query": ENTERPRISE_MEMBERS_QUERY,
|
|
264
280
|
"variables": {"slug": ctx.enterprise_name, "count": 100, "after": None},
|
|
265
281
|
}
|
|
266
|
-
|
|
267
|
-
|
|
282
|
+
client, graphql_path = _graphql_client(ctx)
|
|
283
|
+
for page_data in client.paginate(
|
|
284
|
+
graphql_path,
|
|
268
285
|
method="POST",
|
|
269
286
|
json=data,
|
|
270
287
|
paginator=paginator,
|
|
@@ -635,8 +652,9 @@ def enterprise_admins(enterprise_data: Enterprise, ctx: SourceContext):
|
|
|
635
652
|
"query": ENTERPRISE_ADMINS_QUERY,
|
|
636
653
|
"variables": {"slug": ctx.enterprise_name, "count": 100, "after": None},
|
|
637
654
|
}
|
|
638
|
-
|
|
639
|
-
|
|
655
|
+
client, graphql_path = _graphql_client(ctx)
|
|
656
|
+
for page_data in client.paginate(
|
|
657
|
+
graphql_path,
|
|
640
658
|
method="POST",
|
|
641
659
|
json=data,
|
|
642
660
|
paginator=paginator,
|
|
@@ -665,7 +683,7 @@ def enterprise_admins(enterprise_data: Enterprise, ctx: SourceContext):
|
|
|
665
683
|
parallelized=True
|
|
666
684
|
)
|
|
667
685
|
def enterprise_saml_provider(enterprise_data: Enterprise, ctx: SourceContext):
|
|
668
|
-
client = ctx
|
|
686
|
+
client, graphql_path = _sso_graphql_client(ctx)
|
|
669
687
|
if not client:
|
|
670
688
|
logger.info(
|
|
671
689
|
"Skipping enterprise_saml_provider for enterprise '%s': no SSO client configured",
|
|
@@ -679,7 +697,7 @@ def enterprise_saml_provider(enterprise_data: Enterprise, ctx: SourceContext):
|
|
|
679
697
|
}
|
|
680
698
|
|
|
681
699
|
try:
|
|
682
|
-
response = client.post(
|
|
700
|
+
response = client.post(graphql_path, json=data).json()
|
|
683
701
|
except Exception as e:
|
|
684
702
|
logger.error(
|
|
685
703
|
f"Error in resource 'enterprise_saml_provider' processing enterprise '{ctx.enterprise_name}': {e}",
|
|
@@ -779,7 +797,7 @@ def enterprise_saml_issuer(saml_provider: SamlProvider, ctx: SourceContext):
|
|
|
779
797
|
def enterprise_external_identity(
|
|
780
798
|
saml_provider: SamlProvider, ctx: SourceContext
|
|
781
799
|
):
|
|
782
|
-
client = ctx
|
|
800
|
+
client, graphql_path = _sso_graphql_client(ctx)
|
|
783
801
|
if not client:
|
|
784
802
|
logger.info(
|
|
785
803
|
"Skipping enterprise_external_identity for enterprise '%s': no SSO client configured",
|
|
@@ -801,7 +819,7 @@ def enterprise_external_identity(
|
|
|
801
819
|
|
|
802
820
|
try:
|
|
803
821
|
for page_data in client.paginate(
|
|
804
|
-
|
|
822
|
+
graphql_path,
|
|
805
823
|
method="POST",
|
|
806
824
|
json=data,
|
|
807
825
|
paginator=paginator,
|
{openhound_github-0.6.5 → openhound_github-0.6.7}/src/openhound_github/resources/organization.py
RENAMED
|
@@ -22,7 +22,14 @@ from openhound_github.graphql import (
|
|
|
22
22
|
TEAM_MEMBERS_OVERFLOW_QUERY,
|
|
23
23
|
TEAMS_QUERY,
|
|
24
24
|
)
|
|
25
|
-
from openhound_github.helpers import
|
|
25
|
+
from openhound_github.helpers import (
|
|
26
|
+
AdaptiveGraphQLPageError,
|
|
27
|
+
DEFAULT_GITHUB_REST_API_URL,
|
|
28
|
+
GraphQLCursorPaginator,
|
|
29
|
+
adaptive_graphql_paginate,
|
|
30
|
+
graphql_client_and_path,
|
|
31
|
+
scim_skip_reason,
|
|
32
|
+
)
|
|
26
33
|
from openhound_github.main import app
|
|
27
34
|
from openhound_github.models import (
|
|
28
35
|
ActionPermission,
|
|
@@ -83,11 +90,11 @@ from openhound_github.models.saml_helpers import (
|
|
|
83
90
|
|
|
84
91
|
logger = logging.getLogger(__name__)
|
|
85
92
|
|
|
86
|
-
|
|
87
93
|
@dataclass
|
|
88
94
|
class OrgContext:
|
|
89
95
|
client: RESTClient
|
|
90
96
|
org_name: str
|
|
97
|
+
graphql_client: RESTClient | None = None
|
|
91
98
|
enterprise_name: str | None = None
|
|
92
99
|
github_deployment_id: str = DEFAULT_GITHUB_DEPLOYMENT_ID
|
|
93
100
|
github_web_origin: str = DEFAULT_GITHUB_WEB_ORIGIN
|
|
@@ -97,6 +104,7 @@ class OrgContext:
|
|
|
97
104
|
class SourceContext:
|
|
98
105
|
client: RESTClient
|
|
99
106
|
organizations: list[OrgContext] = field(default_factory=list)
|
|
107
|
+
graphql_client: RESTClient | None = None
|
|
100
108
|
enterprise_name: str | None = None
|
|
101
109
|
github_deployment_id: str = DEFAULT_GITHUB_DEPLOYMENT_ID
|
|
102
110
|
github_web_origin: str = DEFAULT_GITHUB_WEB_ORIGIN
|
|
@@ -133,6 +141,20 @@ def _client_for_org(ctx: SourceContext, org_login: str) -> RESTClient:
|
|
|
133
141
|
return ctx.client
|
|
134
142
|
|
|
135
143
|
|
|
144
|
+
def _graphql_client_for_org(
|
|
145
|
+
ctx: SourceContext, org_login: str
|
|
146
|
+
) -> tuple[RESTClient, str]:
|
|
147
|
+
for org in ctx.organizations:
|
|
148
|
+
if org.org_name == org_login:
|
|
149
|
+
return graphql_client_and_path(org.client, org.graphql_client)
|
|
150
|
+
return graphql_client_and_path(ctx.client, ctx.graphql_client)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _rest_api_url(client: RESTClient) -> str:
|
|
154
|
+
base_url = getattr(client, "base_url", DEFAULT_GITHUB_REST_API_URL)
|
|
155
|
+
return str(base_url).strip().rstrip("/") or DEFAULT_GITHUB_REST_API_URL
|
|
156
|
+
|
|
157
|
+
|
|
136
158
|
def _encode_path_segment(value: str) -> str:
|
|
137
159
|
return quote(value, safe="")
|
|
138
160
|
|
|
@@ -459,7 +481,7 @@ def users(ctx: SourceContext) -> Iterator[dict[str, Any]]:
|
|
|
459
481
|
|
|
460
482
|
for org in ctx.organizations:
|
|
461
483
|
org_name = org.org_name
|
|
462
|
-
client =
|
|
484
|
+
client, graphql_path = _graphql_client_for_org(ctx, org_name)
|
|
463
485
|
try:
|
|
464
486
|
paginator = GraphQLCursorPaginator(
|
|
465
487
|
page_info_path="data.organization.membersWithRole.pageInfo",
|
|
@@ -473,7 +495,7 @@ def users(ctx: SourceContext) -> Iterator[dict[str, Any]]:
|
|
|
473
495
|
}
|
|
474
496
|
|
|
475
497
|
for page_data in client.paginate(
|
|
476
|
-
|
|
498
|
+
graphql_path,
|
|
477
499
|
method="POST",
|
|
478
500
|
json=data,
|
|
479
501
|
paginator=paginator,
|
|
@@ -510,7 +532,7 @@ def teams(ctx: SourceContext):
|
|
|
510
532
|
|
|
511
533
|
for org in ctx.organizations:
|
|
512
534
|
org_name = org.org_name
|
|
513
|
-
client =
|
|
535
|
+
client, graphql_path = _graphql_client_for_org(ctx, org_name)
|
|
514
536
|
try:
|
|
515
537
|
paginator = GraphQLCursorPaginator(
|
|
516
538
|
page_info_path="data.organization.teams.pageInfo",
|
|
@@ -523,7 +545,7 @@ def teams(ctx: SourceContext):
|
|
|
523
545
|
"variables": {"login": org_name, "count": 100, "after": None},
|
|
524
546
|
}
|
|
525
547
|
for page_data in client.paginate(
|
|
526
|
-
|
|
548
|
+
graphql_path,
|
|
527
549
|
method="POST",
|
|
528
550
|
json=data,
|
|
529
551
|
paginator=paginator,
|
|
@@ -621,7 +643,7 @@ def team_members(team: Team, ctx: SourceContext):
|
|
|
621
643
|
raise RuntimeError(
|
|
622
644
|
f"GitHub team {team.org_login}/{team.slug} has more members but no endCursor"
|
|
623
645
|
)
|
|
624
|
-
client =
|
|
646
|
+
client, graphql_path = _graphql_client_for_org(ctx, team.org_login)
|
|
625
647
|
data = {
|
|
626
648
|
"query": TEAM_MEMBERS_OVERFLOW_QUERY,
|
|
627
649
|
"variables": {
|
|
@@ -632,7 +654,7 @@ def team_members(team: Team, ctx: SourceContext):
|
|
|
632
654
|
},
|
|
633
655
|
}
|
|
634
656
|
for page_data in client.paginate(
|
|
635
|
-
|
|
657
|
+
graphql_path,
|
|
636
658
|
method="POST",
|
|
637
659
|
json=data,
|
|
638
660
|
paginator=paginator,
|
|
@@ -922,29 +944,22 @@ def repositories_graphql(ctx: SourceContext):
|
|
|
922
944
|
"""
|
|
923
945
|
for org in ctx.organizations:
|
|
924
946
|
org_name = org.org_name
|
|
925
|
-
client =
|
|
947
|
+
client, graphql_path = _graphql_client_for_org(ctx, org_name)
|
|
926
948
|
repository_cursor: str | None = None
|
|
927
949
|
emitted_repositories = 0
|
|
928
950
|
try:
|
|
929
|
-
|
|
951
|
+
for page_data in adaptive_graphql_paginate(
|
|
952
|
+
client,
|
|
953
|
+
graphql_path=graphql_path,
|
|
954
|
+
query=REPO_REFS_QUERY,
|
|
955
|
+
variables={"login": org_name, "after": None},
|
|
930
956
|
page_info_path="data.organization.repositories.pageInfo",
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
data = {
|
|
936
|
-
"query": REPO_REFS_QUERY,
|
|
937
|
-
"variables": {"login": org_name, "count": 100, "after": None},
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
for page_data in client.paginate(
|
|
941
|
-
"/graphql",
|
|
942
|
-
method="POST",
|
|
943
|
-
json=data,
|
|
944
|
-
paginator=paginator,
|
|
945
|
-
data_selector="data",
|
|
957
|
+
resource_name="repositories_graphql",
|
|
958
|
+
scope_name="organization",
|
|
959
|
+
scope_value=org_name,
|
|
960
|
+
log=logger,
|
|
946
961
|
):
|
|
947
|
-
repos_page = page_data[
|
|
962
|
+
repos_page = page_data["organization"]["repositories"]
|
|
948
963
|
for repo in repos_page["nodes"]:
|
|
949
964
|
repo_record = {**repo}
|
|
950
965
|
branch_rulesets = repo_record.pop("branchRulesets", None) or {}
|
|
@@ -959,22 +974,29 @@ def repositories_graphql(ctx: SourceContext):
|
|
|
959
974
|
if isinstance(page_info, dict):
|
|
960
975
|
repository_cursor = page_info.get("endCursor")
|
|
961
976
|
except Exception as e:
|
|
977
|
+
failure = e.error if isinstance(e, AdaptiveGraphQLPageError) else e
|
|
978
|
+
failure_cursor = (
|
|
979
|
+
e.cursor if isinstance(e, AdaptiveGraphQLPageError) else repository_cursor
|
|
980
|
+
)
|
|
981
|
+
page_size = e.page_size if isinstance(e, AdaptiveGraphQLPageError) else None
|
|
962
982
|
logger.error(
|
|
963
983
|
"Error in resource 'repositories_graphql' processing organization '%s' "
|
|
964
|
-
"at repository cursor %r after emitting %d repositories "
|
|
984
|
+
"at repository cursor %r with page size %r after emitting %d repositories "
|
|
965
985
|
"(%s): %s",
|
|
966
986
|
org_name,
|
|
967
|
-
|
|
987
|
+
failure_cursor,
|
|
988
|
+
page_size,
|
|
968
989
|
emitted_repositories,
|
|
969
|
-
type(
|
|
970
|
-
|
|
990
|
+
type(failure).__name__,
|
|
991
|
+
failure,
|
|
971
992
|
extra={
|
|
972
993
|
"resource": "repositories_graphql",
|
|
973
994
|
"phase": "resource_iteration",
|
|
974
995
|
"org_name": org_name,
|
|
975
|
-
"repository_cursor":
|
|
996
|
+
"repository_cursor": failure_cursor,
|
|
997
|
+
"page_size": page_size,
|
|
976
998
|
"emitted_repositories": emitted_repositories,
|
|
977
|
-
"error_type": type(
|
|
999
|
+
"error_type": type(failure).__name__,
|
|
978
1000
|
},
|
|
979
1001
|
)
|
|
980
1002
|
continue
|
|
@@ -1010,7 +1032,7 @@ def branches(repository: RepositoryQL, ctx: SourceContext):
|
|
|
1010
1032
|
}
|
|
1011
1033
|
|
|
1012
1034
|
if repository.refs.page_info.has_next_page:
|
|
1013
|
-
client =
|
|
1035
|
+
client, graphql_path = _graphql_client_for_org(ctx, repository.org_login)
|
|
1014
1036
|
data = {
|
|
1015
1037
|
"query": REF_OVERFLOW_QUERY,
|
|
1016
1038
|
"variables": {
|
|
@@ -1022,7 +1044,7 @@ def branches(repository: RepositoryQL, ctx: SourceContext):
|
|
|
1022
1044
|
}
|
|
1023
1045
|
|
|
1024
1046
|
for page_data in client.paginate(
|
|
1025
|
-
|
|
1047
|
+
graphql_path,
|
|
1026
1048
|
method="POST",
|
|
1027
1049
|
json=data,
|
|
1028
1050
|
paginator=paginator,
|
|
@@ -1064,12 +1086,12 @@ def branch_protection_rules(repository: RepositoryQL, ctx: SourceContext):
|
|
|
1064
1086
|
rule_ids_seen.add(rule_id)
|
|
1065
1087
|
|
|
1066
1088
|
rule_ids_list = list(rule_ids_seen)
|
|
1067
|
-
client =
|
|
1089
|
+
client, graphql_path = _graphql_client_for_org(ctx, repository.org_login)
|
|
1068
1090
|
for i in range(0, len(rule_ids_list), 100):
|
|
1069
1091
|
rules_chunk = rule_ids_list[i : i + 100]
|
|
1070
1092
|
if rules_chunk:
|
|
1071
1093
|
data = {"query": PROTECTION_RULES_QUERY, "variables": {"ids": rules_chunk}}
|
|
1072
|
-
response = client.post(
|
|
1094
|
+
response = client.post(graphql_path, json=data).json()
|
|
1073
1095
|
for rule in response["data"].get("nodes", []):
|
|
1074
1096
|
# GitHub can return null actors for deleted or inaccessible allowance actors.
|
|
1075
1097
|
for allowance_key in ("bypassPullRequestAllowances", "pushAllowances"):
|
|
@@ -1653,7 +1675,7 @@ def secret_scanning_alerts(ctx: SourceContext):
|
|
|
1653
1675
|
):
|
|
1654
1676
|
try:
|
|
1655
1677
|
resp = requests.get(
|
|
1656
|
-
"
|
|
1678
|
+
f"{_rest_api_url(client)}/user",
|
|
1657
1679
|
headers={"Authorization": f"Bearer {secret}"},
|
|
1658
1680
|
timeout=10,
|
|
1659
1681
|
)
|
|
@@ -1789,14 +1811,14 @@ def saml_provider(ctx: SourceContext):
|
|
|
1789
1811
|
"""
|
|
1790
1812
|
for org in ctx.organizations:
|
|
1791
1813
|
org_name = org.org_name
|
|
1792
|
-
client =
|
|
1814
|
+
client, graphql_path = _graphql_client_for_org(ctx, org_name)
|
|
1793
1815
|
try:
|
|
1794
1816
|
data = {
|
|
1795
1817
|
"query": SAML_QUERY,
|
|
1796
1818
|
"variables": {"login": org_name, "count": 100, "after": None},
|
|
1797
1819
|
}
|
|
1798
1820
|
|
|
1799
|
-
response = client.post(
|
|
1821
|
+
response = client.post(graphql_path, json=data).json()
|
|
1800
1822
|
response_data = response.get("data", {})
|
|
1801
1823
|
org_data = response_data.get("organization", {})
|
|
1802
1824
|
if response_data and org_data:
|
|
@@ -1833,7 +1855,7 @@ def external_identities(ctx: SourceContext):
|
|
|
1833
1855
|
"""
|
|
1834
1856
|
for org in ctx.organizations:
|
|
1835
1857
|
org_name = org.org_name
|
|
1836
|
-
client =
|
|
1858
|
+
client, graphql_path = _graphql_client_for_org(ctx, org_name)
|
|
1837
1859
|
github_deployment_id = org.github_deployment_id
|
|
1838
1860
|
try:
|
|
1839
1861
|
paginator = GraphQLCursorPaginator(
|
|
@@ -1849,7 +1871,7 @@ def external_identities(ctx: SourceContext):
|
|
|
1849
1871
|
}
|
|
1850
1872
|
|
|
1851
1873
|
for page_data in client.paginate(
|
|
1852
|
-
|
|
1874
|
+
graphql_path,
|
|
1853
1875
|
method="POST",
|
|
1854
1876
|
json=data,
|
|
1855
1877
|
paginator=paginator,
|