@oneuptime/common 13.0.0 → 13.0.1
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.
- package/Models/DatabaseModels/Alert.ts +55 -0
- package/Models/DatabaseModels/CloudResource.ts +45 -7
- package/Models/DatabaseModels/CodeRepository.ts +85 -0
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +57 -7
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +263 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/User.ts +51 -2
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +43 -2
- package/Models/DatabaseModels/UserWebAuthn.ts +17 -0
- package/Models/DatabaseModels/VMwareResource.ts +1149 -0
- package/Models/DatabaseModels/VMwareVCenter.ts +1122 -0
- package/Models/DatabaseModels/VMwareVCenterFeed.ts +625 -0
- package/Models/DatabaseModels/VMwareVCenterLabelRule.ts +514 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerRule.ts +596 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerTeam.ts +485 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerUser.ts +484 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +22 -1
- package/Server/API/AIAgentDataAPI.ts +79 -4
- package/Server/API/AIAgentGitHubAPI.ts +523 -0
- package/Server/API/AIChatAPI.ts +20 -1
- package/Server/API/BillingAPI.ts +33 -0
- package/Server/API/DashboardAPI.ts +10 -0
- package/Server/API/GitHubAPI.ts +47 -5
- package/Server/API/GoogleSecOpsConnectionAPI.ts +79 -0
- package/Server/API/UserWebAuthnAPI.ts +21 -1
- package/Server/API/VMwareResourceAPI.ts +143 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.ts +636 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Middleware/IdentityRateLimit.ts +101 -0
- package/Server/Services/AIRunService.ts +13 -0
- package/Server/Services/BillingPaymentMethodService.ts +99 -28
- package/Server/Services/BillingService.ts +287 -20
- package/Server/Services/CloudResourceInstanceService.ts +70 -0
- package/Server/Services/ExceptionAggregationService.ts +1 -0
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +10 -0
- package/Server/Services/GoogleSecOpsConnectionService.ts +12 -0
- package/Server/Services/Index.ts +16 -0
- package/Server/Services/LogAggregationService.ts +1 -0
- package/Server/Services/MetricAggregationService.ts +1 -0
- package/Server/Services/MobilePasskeyLoginService.ts +216 -0
- package/Server/Services/MonitorService.ts +51 -1
- package/Server/Services/MonitorTemplateService.ts +91 -29
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +132 -1
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +176 -2
- package/Server/Services/OpenTelemetryIngestService.ts +17 -0
- package/Server/Services/PayAsYouGoBillingService.ts +446 -0
- package/Server/Services/ProjectService.ts +46 -2
- package/Server/Services/ServerlessFunctionInstanceService.ts +71 -0
- package/Server/Services/TeamMemberService.ts +96 -36
- package/Server/Services/TelemetryIngestionKeyService.ts +80 -10
- package/Server/Services/TelemetryUsageBillingService.ts +95 -5
- package/Server/Services/TraceAggregationService.ts +5 -4
- package/Server/Services/UserWebAuthnService.ts +592 -133
- package/Server/Services/VMwareResourceService.ts +648 -0
- package/Server/Services/VMwareVCenterFeedService.ts +99 -0
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +240 -0
- package/Server/Services/VMwareVCenterLabelRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +252 -0
- package/Server/Services/VMwareVCenterOwnerRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerTeamService.ts +139 -0
- package/Server/Services/VMwareVCenterOwnerUserService.ts +133 -0
- package/Server/Services/VMwareVCenterService.ts +629 -0
- package/Server/Services/WorkflowVariableService.ts +203 -0
- package/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.ts +17 -0
- package/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.ts +31 -1
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +7 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.ts +341 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.ts +274 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.ts +375 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubConversation.ts +846 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.ts +360 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubRunReply.ts +421 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.ts +140 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.ts +906 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +143 -0
- package/Server/Utils/DataSource/EgressGuard.ts +160 -15
- package/Server/Utils/Database/TruncateColumnValue.ts +1 -1
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +2 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +33 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +44 -0
- package/Server/Utils/LogRedaction.ts +2 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +302 -3
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +26 -4
- package/Server/Utils/Monitor/MonitorResourceContext.ts +5 -3
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +14 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +26 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +28 -5
- package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +3 -3
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +14 -9
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +116 -84
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +594 -195
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +466 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -0
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +2 -1
- package/Server/Utils/Telemetry/TelemetryEntity.ts +181 -1
- package/Server/Utils/Telemetry/VMwareSnapshotScan.ts +1352 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +529 -0
- package/Tests/App/Accounts/MobilePasskey.test.tsx +620 -0
- package/Tests/App/Accounts/PasswordRequirements.test.tsx +254 -0
- package/Tests/App/Accounts/RegisterPassword.test.tsx +553 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +224 -0
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +432 -0
- package/Tests/App/Dashboard/BackupCodes.test.tsx +414 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +530 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +195 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +199 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +198 -0
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +215 -0
- package/Tests/App/Dashboard/CloudFleetSummary.test.ts +183 -0
- package/Tests/App/Dashboard/CloudFleetSummaryComponent.test.tsx +248 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +215 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +3 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +441 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +458 -0
- package/Tests/App/Dashboard/DashboardToolbarPopupLayering.test.tsx +566 -0
- package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +376 -0
- package/Tests/App/Dashboard/DiscoveryScanLiveUpdates.test.tsx +642 -0
- package/Tests/App/Dashboard/DiscoveryScanProgress.test.tsx +267 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +69 -231
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +244 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +724 -0
- package/Tests/App/Dashboard/MonitorTemplateSyncFields.test.tsx +539 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +24 -7
- package/Tests/App/Dashboard/OnCallOverridePresentation.test.ts +496 -0
- package/Tests/App/Dashboard/OnCallScheduleOverrideClarity.test.tsx +677 -0
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +31 -3
- package/Tests/App/Dashboard/PaidUsageConsent.test.tsx +180 -0
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +1220 -0
- package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +176 -275
- package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +380 -233
- package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +3 -23
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +1 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/TwoFactorStatus.test.tsx +260 -0
- package/Tests/App/Dashboard/VMwareDashboardWidgets.test.ts +573 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +768 -0
- package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +532 -40
- package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +19 -2
- package/Tests/Fixtures/MobilePasskeyUser.json +8 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +25 -6
- package/Tests/Models/DatabaseModels/VMwareModels.test.ts +1134 -0
- package/Tests/Models/RunnerVersionLabel.test.ts +4 -2
- package/Tests/Server/API/AIChatProvidersAIEnabled.test.ts +259 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +31 -2
- package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +116 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +29 -1
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +13 -2
- package/Tests/Server/API/GitHubWebhookSignature.test.ts +368 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +248 -0
- package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +330 -0
- package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +172 -0
- package/Tests/Server/API/VMwareResourceAPI.test.ts +546 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupMetadataMigration.test.ts +85 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +34 -3
- package/Tests/Server/Middleware/PasskeyRateLimit.test.ts +141 -0
- package/Tests/Server/Services/AutoImportRuleRearmRecentScans.test.ts +343 -0
- package/Tests/Server/Services/AutoImportRuleWriteRearmsScans.test.ts +381 -0
- package/Tests/Server/Services/BillingPaymentMethodServiceSync.test.ts +175 -0
- package/Tests/Server/Services/BillingService.test.ts +26 -11
- package/Tests/Server/Services/BillingServiceMeteredPaymentAuthorization.test.ts +245 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +362 -0
- package/Tests/Server/Services/CloudResourceInstanceStalePrune.test.ts +188 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +16 -2
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +153 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +13 -0
- package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +5 -0
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +36 -0
- package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +151 -0
- package/Tests/Server/Services/MobilePasskeyLoginIntegration.test.ts +231 -0
- package/Tests/Server/Services/MobilePasskeyLoginService.test.ts +315 -0
- package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +302 -0
- package/Tests/Server/Services/MonitorTemplateServiceFieldSync.test.ts +994 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +22 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +857 -0
- package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +379 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +99 -1
- package/Tests/Server/Services/ProjectServiceSubscriptionSeats.test.ts +134 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +3 -2
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +32 -6
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +363 -175
- package/Tests/Server/Services/ServerlessFunctionInstanceStalePrune.test.ts +200 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +3 -0
- package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +762 -0
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +3 -0
- package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +72 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +17 -4
- package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +355 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +41 -4
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +37 -0
- package/Tests/Server/Services/UserWebAuthnPasskeyIntegration.test.ts +401 -0
- package/Tests/Server/Services/UserWebAuthnPasskeyService.test.ts +769 -0
- package/Tests/Server/Services/UserWebAuthnUserVerification.test.ts +649 -0
- package/Tests/Server/Services/VMwareResourceService.test.ts +945 -0
- package/Tests/Server/Services/VMwareVCenterService.test.ts +722 -0
- package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +842 -0
- package/Tests/Server/TestingUtils/PasskeyHttpIntegration.ts +102 -0
- package/Tests/Server/TestingUtils/SecurityKey.ts +464 -0
- package/Tests/Server/TestingUtils/WebAuthnServiceMocks.ts +60 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +573 -0
- package/Tests/Server/Types/Database/Permissions/ProjectCustomerSupportAccessColumn.test.ts +261 -0
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +95 -0
- package/Tests/Server/Utils/CodeRepository/GitHubAgentTaskTrigger.test.ts +2101 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandAuthorizer.test.ts +883 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandParser.test.ts +1474 -0
- package/Tests/Server/Utils/CodeRepository/GitHubConversation.test.ts +1526 -0
- package/Tests/Server/Utils/CodeRepository/GitHubReplyComposer.test.ts +1389 -0
- package/Tests/Server/Utils/CodeRepository/GitHubRunReply.test.ts +1707 -0
- package/Tests/Server/Utils/CodeRepository/GitHubWebhookHandler.test.ts +2202 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +345 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +896 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupMetadataIntegration.test.ts +246 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +299 -1
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +6 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +185 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +33 -0
- package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +2 -1
- package/Tests/Server/Utils/Monitor/Criteria/TelemetryStepMetricAlias.test.ts +10 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +66 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +362 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +60 -1
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +60 -0
- package/Tests/Server/Utils/Monitor/MonitorRootCauseTargetResolution.test.ts +423 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +46 -2
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +81 -45
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +711 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClickhouseIntegration.test.ts +223 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +69 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +838 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +241 -28
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +651 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +11 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +13 -12
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +112 -127
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +12 -18
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +43 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +580 -0
- package/Tests/Server/Utils/Telemetry/VMwareSnapshotScan.test.ts +1748 -0
- package/Tests/Types/Cloud/CloudPlatform.test.ts +574 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +2 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +9 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepInfraMonitorUtils.test.ts +53 -8
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +97 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepTemplateSyncFields.test.ts +107 -0
- package/Tests/Types/Monitor/MonitorTemplateSyncField.test.ts +172 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +2 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +1 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +9 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +131 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +10 -0
- package/Tests/Types/Monitor/VMwareAlertTemplates.test.ts +1608 -0
- package/Tests/Types/Monitor/VMwareMetricCatalog.test.ts +488 -0
- package/Tests/Types/OnCallDutyPolicy/OverrideProvenance.test.ts +295 -0
- package/Tests/Types/Runner/RunnerLiveStatus.test.ts +2 -2
- package/Tests/Types/SignupPassword.test.ts +205 -0
- package/Tests/Types/StatusPage/StatusPageLanguage.test.ts +44 -0
- package/Tests/Types/SupportedLanguages.test.ts +119 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +19 -0
- package/Tests/UI/ColorPickerBuild.test.ts +86 -0
- package/Tests/UI/Components/Breadcrumbs.test.tsx +32 -0
- package/Tests/UI/Components/Forms/ModelFormPreservesUserInput.test.tsx +937 -0
- package/Tests/UI/Components/Forms/ModelFormWriteOnlyColumnSelect.test.tsx +230 -0
- package/Tests/UI/Components/Forms/ValidationFormSteps.test.ts +3 -4
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +907 -0
- package/Tests/UI/Components/ModelTable/ModelTableCreateAfterEdit.test.tsx +514 -0
- package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +301 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +2 -1
- package/Tests/UI/Components/TooltipLazyContent.test.tsx +373 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +43 -12
- package/Tests/UI/ReactDomBuild.test.ts +104 -0
- package/Tests/UI/ReactRouterSingletonBuild.test.ts +11 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +148 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +29 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +197 -0
- package/Tests/UI/Utils/LabelRuleImportExport.test.ts +546 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +109 -2
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +7 -2
- package/Tests/UI/Utils/UserEmailRegistrationStatus.test.tsx +295 -0
- package/Tests/UI/Utils/WebAuthn.test.ts +265 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +5 -0
- package/Tests/Utils/Dashboard/Components/DashboardVMwareListComponents.test.ts +548 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +17 -3
- package/Tests/Utils/LabelRuleImportExport.test.ts +583 -0
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/MonitorTemplateSyncUtil.test.ts +590 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +325 -0
- package/Tests/Utils/Telemetry/CloudInstanceIdentity.test.ts +255 -0
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +167 -0
- package/Tests/Utils/WebAuthnTestUtil.ts +79 -0
- package/Tests/__mocks__/simplewebauthn.js +33 -4
- package/Types/AI/CodeFixTaskContext.ts +122 -0
- package/Types/AI/CodeFixTaskType.ts +62 -0
- package/Types/Accounts/AccountsLanguage.ts +1 -0
- package/Types/AdminDashboard/AdminDashboardLanguage.ts +1 -0
- package/Types/Calendar/CalendarEvent.ts +16 -0
- package/Types/Cloud/CloudPlatform.ts +372 -0
- package/Types/CodeRepository/GitHubCommand.ts +69 -0
- package/Types/Dashboard/DashboardComponentType.ts +2 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.ts +23 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.ts +30 -0
- package/Types/Dashboard/DashboardLanguage.ts +1 -0
- package/Types/Dashboard/DashboardTemplates.ts +314 -0
- package/Types/Docs/DocsLanguage.ts +1 -0
- package/Types/Exception/EgressGuardException.ts +65 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +36 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +1 -0
- package/Types/Monitor/MonitorStep.ts +78 -17
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +1 -0
- package/Types/Monitor/MonitorStepVMwareMonitor.ts +127 -0
- package/Types/Monitor/MonitorTemplateSyncField.ts +291 -0
- package/Types/Monitor/MonitorType.ts +24 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +33 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +2 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +3 -0
- package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +158 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +61 -0
- package/Types/Monitor/VMwareAlertTemplates.ts +1070 -0
- package/Types/Monitor/VMwareMetricCatalog.ts +914 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +29 -0
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +16 -0
- package/Types/Password.ts +84 -5
- package/Types/Permission.ts +265 -0
- package/Types/Probe/RequestFailedDetails.ts +7 -0
- package/Types/Runner/RunnerLiveStatus.ts +1 -1
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -0
- package/Types/StatusPage/StatusPageLanguage.ts +1 -0
- package/Types/Telemetry/EntityType.ts +21 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/Typings/Index.d.ts +63 -0
- package/UI/Components/Breadcrumbs/Breadcrumbs.tsx +2 -2
- package/UI/Components/Calendar/Calendar.css +78 -0
- package/UI/Components/Calendar/Calendar.tsx +28 -3
- package/UI/Components/Forms/BasicForm.tsx +44 -2
- package/UI/Components/Forms/Fields/ColorPicker.tsx +2 -1
- package/UI/Components/Forms/Fields/FormField.tsx +16 -3
- package/UI/Components/Forms/ModelForm.tsx +159 -5
- package/UI/Components/Forms/Types/Field.ts +8 -1
- package/UI/Components/Graphs/DayUptimeGraph.tsx +8 -10
- package/UI/Components/Icon/Icon.tsx +16 -0
- package/UI/Components/Input/Input.tsx +42 -7
- package/UI/Components/LabelRule/ImportLabelRulesModal.tsx +441 -0
- package/UI/Components/LabelRule/LabelRuleTable.tsx +142 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +22 -5
- package/UI/Components/ModelTable/ModelTable.tsx +14 -6
- package/UI/Components/MonitorGraphs/Uptime.tsx +17 -27
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +3 -1
- package/UI/Components/Tooltip/Tooltip.tsx +52 -6
- package/UI/Utils/DashboardStackingLayers.ts +85 -0
- package/UI/Utils/LabelRuleImportExport.ts +310 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +4 -3
- package/UI/Utils/TelemetryService.ts +4 -3
- package/UI/Utils/UseDashboardGridDnd.ts +4 -1
- package/UI/Utils/UserEmailRegistrationStatus.ts +33 -5
- package/UI/Utils/WebAuthn.ts +220 -0
- package/UI/esbuild-config.js +4 -0
- package/Utils/API.ts +34 -0
- package/Utils/Dashboard/Components/DashboardVMwareHostListComponent.ts +38 -0
- package/Utils/Dashboard/Components/DashboardVMwareResourceListShared.ts +70 -0
- package/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.ts +76 -0
- package/Utils/Dashboard/Components/Index.ts +16 -0
- package/Utils/LabelRuleImportExport.ts +496 -0
- package/Utils/Monitor/MonitorTemplateSyncUtil.ts +164 -0
- package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +8 -0
- package/Utils/Telemetry/CloudInstanceIdentity.ts +94 -0
- package/Utils/Telemetry/EntityKey.ts +19 -0
- package/Utils/Telemetry/EntityRelationship.ts +19 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +44 -7
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +87 -0
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +60 -7
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +57 -4
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +47 -2
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +18 -0
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareResource.js +1201 -0
- package/build/dist/Models/DatabaseModels/VMwareResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +1149 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +22 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +63 -3
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentGitHubAPI.js +363 -0
- package/build/dist/Server/API/AIAgentGitHubAPI.js.map +1 -0
- package/build/dist/Server/API/AIChatAPI.js +19 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/BillingAPI.js +22 -0
- package/build/dist/Server/API/BillingAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +10 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +33 -5
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +56 -0
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/UserWebAuthnAPI.js +17 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/API/VMwareResourceAPI.js +106 -0
- package/build/dist/Server/API/VMwareResourceAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js +241 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +80 -0
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +14 -1
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/BillingPaymentMethodService.js +71 -21
- package/build/dist/Server/Services/BillingPaymentMethodService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +210 -22
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceInstanceService.js +66 -0
- package/build/dist/Server/Services/CloudResourceInstanceService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +1 -0
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +9 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +7 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +16 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +1 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +1 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MobilePasskeyLoginService.js +137 -0
- package/build/dist/Server/Services/MobilePasskeyLoginService.js.map +1 -0
- package/build/dist/Server/Services/MonitorService.js +34 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +64 -26
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +124 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +142 -2
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +28 -13
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PayAsYouGoBillingService.js +297 -0
- package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +38 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js +66 -0
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +85 -28
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +61 -10
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +62 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +5 -4
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/UserWebAuthnService.js +345 -113
- package/build/dist/Server/Services/UserWebAuthnService.js.map +1 -1
- package/build/dist/Server/Services/VMwareResourceService.js +395 -0
- package/build/dist/Server/Services/VMwareResourceService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js +89 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +197 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +214 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js +129 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js +122 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterService.js +533 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -0
- package/build/dist/Server/Services/WorkflowVariableService.js +169 -0
- package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js +12 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js +25 -2
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js +226 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js +297 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js +582 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js +365 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js +103 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js +661 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +113 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +99 -15
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +2 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +18 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +31 -2
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +2 -1
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +219 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +12 -4
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +22 -9
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +21 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +21 -6
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +3 -3
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +9 -9
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +92 -71
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +428 -143
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +376 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +136 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js +933 -0
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +40 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +57 -0
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -1
- package/build/dist/Types/Accounts/AccountsLanguage.js +1 -0
- package/build/dist/Types/Accounts/AccountsLanguage.js.map +1 -1
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js +1 -0
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js.map +1 -1
- package/build/dist/Types/Cloud/CloudPlatform.js +277 -0
- package/build/dist/Types/Cloud/CloudPlatform.js.map +1 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js +52 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +286 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Docs/DocsLanguage.js +1 -0
- package/build/dist/Types/Docs/DocsLanguage.js.map +1 -1
- package/build/dist/Types/Exception/EgressGuardException.js +59 -0
- package/build/dist/Types/Exception/EgressGuardException.js.map +1 -0
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +61 -18
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +1 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js +71 -0
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js +211 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +23 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +28 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +2 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +120 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +60 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js +775 -0
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js +799 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +25 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +5 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
- package/build/dist/Types/Password.js +63 -5
- package/build/dist/Types/Password.js.map +1 -1
- package/build/dist/Types/Permission.js +234 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Probe/RequestFailedDetails.js +7 -0
- package/build/dist/Types/Probe/RequestFailedDetails.js.map +1 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +21 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js +2 -2
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +24 -4
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +28 -3
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +89 -6
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +5 -6
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +14 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +37 -8
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js +228 -0
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js.map +1 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +102 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +15 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +13 -5
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +14 -15
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +2 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +33 -4
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Utils/DashboardStackingLayers.js +44 -0
- package/build/dist/UI/Utils/DashboardStackingLayers.js.map +1 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js +195 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +4 -4
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +2 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -1
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js +21 -4
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js.map +1 -1
- package/build/dist/UI/Utils/WebAuthn.js +121 -0
- package/build/dist/UI/Utils/WebAuthn.js.map +1 -0
- package/build/dist/Utils/API.js +29 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js +33 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js +54 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js +60 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +8 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +356 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js +110 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +6 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -1
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js +88 -0
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +15 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +13 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,846 @@
|
|
|
1
|
+
import logger from "../../Logger";
|
|
2
|
+
import HTTPErrorResponse from "../../../../Types/API/HTTPErrorResponse";
|
|
3
|
+
import HTTPResponse from "../../../../Types/API/HTTPResponse";
|
|
4
|
+
import URL from "../../../../Types/API/URL";
|
|
5
|
+
import Headers from "../../../../Types/API/Headers";
|
|
6
|
+
import { JSONArray, JSONObject } from "../../../../Types/JSON";
|
|
7
|
+
import API from "../../../../Utils/API";
|
|
8
|
+
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
9
|
+
import GlobalCache from "../../../Infrastructure/GlobalCache";
|
|
10
|
+
import { GitHubAppName } from "../../../EnvironmentConfig";
|
|
11
|
+
import GitHubUtil, { GitHubInstallationToken } from "./GitHub";
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* The GitHub REST surface the interactive app needs: issue and pull request
|
|
15
|
+
* conversations, reactions, reviews, labels and collaborator permissions.
|
|
16
|
+
*
|
|
17
|
+
* Kept apart from GitHub.ts on purpose. That file is the CODE path — clone,
|
|
18
|
+
* read files, commit, open pull requests — and its callers are the fix
|
|
19
|
+
* pipeline. This one is the CONVERSATION path, reached from the webhook
|
|
20
|
+
* handler and the run-reply helper, and every method here writes something a
|
|
21
|
+
* human will read in a repository we do not own. The split keeps "what the
|
|
22
|
+
* agent may change" and "what the app may say" reviewable independently.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// One reaction GitHub accepts on an issue, comment or review comment.
|
|
26
|
+
export enum GitHubReaction {
|
|
27
|
+
// Acknowledgement: "seen, working on it".
|
|
28
|
+
Eyes = "eyes",
|
|
29
|
+
// Success.
|
|
30
|
+
Rocket = "rocket",
|
|
31
|
+
// Refusal / failure.
|
|
32
|
+
Confused = "confused",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface GitHubIssueComment {
|
|
36
|
+
commentId: number;
|
|
37
|
+
htmlUrl: string;
|
|
38
|
+
body: string;
|
|
39
|
+
authorLogin: string;
|
|
40
|
+
// GitHub App comments have type "Bot"; the app's own replies must not loop.
|
|
41
|
+
isBot: boolean;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface GitHubIssueDetails {
|
|
46
|
+
issueNumber: number;
|
|
47
|
+
title: string;
|
|
48
|
+
body: string;
|
|
49
|
+
state: string;
|
|
50
|
+
htmlUrl: string;
|
|
51
|
+
authorLogin: string;
|
|
52
|
+
labels: Array<string>;
|
|
53
|
+
/*
|
|
54
|
+
* GitHub models pull requests as issues, so /issues/{n} answers for both.
|
|
55
|
+
* The `pull_request` key is the only reliable discriminator on that route.
|
|
56
|
+
*/
|
|
57
|
+
isPullRequest: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface GitHubPullRequestDetails {
|
|
61
|
+
pullRequestNumber: number;
|
|
62
|
+
title: string;
|
|
63
|
+
body: string;
|
|
64
|
+
state: string;
|
|
65
|
+
htmlUrl: string;
|
|
66
|
+
authorLogin: string;
|
|
67
|
+
headRefName: string;
|
|
68
|
+
headSha: string;
|
|
69
|
+
baseRefName: string;
|
|
70
|
+
/*
|
|
71
|
+
* "owner/repo" of the branch this pull request is FROM. Equal to the base
|
|
72
|
+
* repository for an ordinary branch pull request; different for one opened
|
|
73
|
+
* from a fork — and a fork's branch does not exist in the repository this
|
|
74
|
+
* installation can write to, so anything that pushes must check this first.
|
|
75
|
+
*/
|
|
76
|
+
headRepositoryFullName: string | null;
|
|
77
|
+
isDraft: boolean;
|
|
78
|
+
isMerged: boolean;
|
|
79
|
+
changedFilesCount: number;
|
|
80
|
+
additions: number;
|
|
81
|
+
deletions: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface GitHubPullRequestFile {
|
|
85
|
+
filename: string;
|
|
86
|
+
status: string;
|
|
87
|
+
additions: number;
|
|
88
|
+
deletions: number;
|
|
89
|
+
// Absent for binary files and for files whose diff GitHub declined to send.
|
|
90
|
+
patch: string | null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// One inline review comment, anchored to a line of the pull request's diff.
|
|
94
|
+
export interface GitHubReviewComment {
|
|
95
|
+
path: string;
|
|
96
|
+
// Line number in the file AFTER the change (GitHub's RIGHT side).
|
|
97
|
+
line: number;
|
|
98
|
+
body: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* What a GitHub user may do in a repository, as reported by the collaborator
|
|
103
|
+
* permission API. Ordered least to most privileged.
|
|
104
|
+
*/
|
|
105
|
+
export enum GitHubRepositoryPermission {
|
|
106
|
+
None = "none",
|
|
107
|
+
Read = "read",
|
|
108
|
+
Triage = "triage",
|
|
109
|
+
Write = "write",
|
|
110
|
+
Maintain = "maintain",
|
|
111
|
+
Admin = "admin",
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Retire a cached installation token this long before GitHub expires it.
|
|
115
|
+
const TOKEN_EXPIRY_SAFETY_MARGIN_MS: number = 60 * 1000;
|
|
116
|
+
|
|
117
|
+
const APP_SLUG_CACHE_NAMESPACE: string = "github-app";
|
|
118
|
+
const APP_SLUG_CACHE_KEY: string = "slug";
|
|
119
|
+
const APP_SLUG_CACHE_SECONDS: number = 60 * 60 * 24;
|
|
120
|
+
|
|
121
|
+
interface CachedInstallationToken {
|
|
122
|
+
token: string;
|
|
123
|
+
expiresAtMilliseconds: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default class GitHubConversation {
|
|
127
|
+
private static tokenCache: Map<string, CachedInstallationToken> = new Map<
|
|
128
|
+
string,
|
|
129
|
+
CachedInstallationToken
|
|
130
|
+
>();
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* Whether this pull request's branch lives in a DIFFERENT repository.
|
|
134
|
+
*
|
|
135
|
+
* This decides whether a revision is possible at all. An installation token
|
|
136
|
+
* is scoped to the repositories the app is installed on, and a fork is not
|
|
137
|
+
* one of them — so pushing a "revision" of a fork pull request would either
|
|
138
|
+
* be refused or, worse, create a same-named branch in the BASE repository
|
|
139
|
+
* that the pull request does not point at. Neither is what anyone asked for.
|
|
140
|
+
*
|
|
141
|
+
* A null head repository (GitHub reports one for a deleted fork) counts as a
|
|
142
|
+
* fork: it is certainly not a branch we can push to.
|
|
143
|
+
*/
|
|
144
|
+
public static isFromFork(pullRequest: {
|
|
145
|
+
headRepositoryFullName: string | null;
|
|
146
|
+
organizationName: string;
|
|
147
|
+
repositoryName: string;
|
|
148
|
+
}): boolean {
|
|
149
|
+
if (!pullRequest.headRepositoryFullName) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
pullRequest.headRepositoryFullName.toLowerCase() !==
|
|
155
|
+
`${pullRequest.organizationName}/${pullRequest.repositoryName}`.toLowerCase()
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private static buildHeaders(token: string): Headers {
|
|
160
|
+
return {
|
|
161
|
+
Authorization: `Bearer ${token}`,
|
|
162
|
+
Accept: "application/vnd.github+json",
|
|
163
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/*
|
|
168
|
+
* Every conversation write needs issues:write (GitHub routes pull request
|
|
169
|
+
* conversation comments through the issues API) and pull_requests:write for
|
|
170
|
+
* reviews. metadata:read is mandatory on every installation token.
|
|
171
|
+
*
|
|
172
|
+
* Cached IN PROCESS, never in Redis. Answering one mention touches GitHub
|
|
173
|
+
* five or six times — permission check, issue read, pull request read,
|
|
174
|
+
* reaction, comment — and minting a fresh `ghs_` token for each is both
|
|
175
|
+
* pointless latency and a real slice of the installation's rate limit. But
|
|
176
|
+
* an installation token is a live write credential for someone else's
|
|
177
|
+
* repositories, so it does not leave this process: a module-level Map dies
|
|
178
|
+
* with the pod, whereas a shared cache turns one Redis exposure into
|
|
179
|
+
* cross-tenant repository access.
|
|
180
|
+
*
|
|
181
|
+
* Retired a minute before GitHub expires it, so a token cannot go stale
|
|
182
|
+
* between the check and the request that uses it.
|
|
183
|
+
*/
|
|
184
|
+
private static async getConversationToken(
|
|
185
|
+
installationId: string,
|
|
186
|
+
): Promise<string> {
|
|
187
|
+
const cached: CachedInstallationToken | undefined =
|
|
188
|
+
GitHubConversation.tokenCache.get(installationId);
|
|
189
|
+
|
|
190
|
+
if (cached && cached.expiresAtMilliseconds > Date.now()) {
|
|
191
|
+
return cached.token;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const tokenData: GitHubInstallationToken =
|
|
195
|
+
await GitHubUtil.getInstallationAccessToken(installationId, {
|
|
196
|
+
permissions: {
|
|
197
|
+
issues: "write",
|
|
198
|
+
pull_requests: "write",
|
|
199
|
+
contents: "read",
|
|
200
|
+
metadata: "read",
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
GitHubConversation.tokenCache.set(installationId, {
|
|
205
|
+
token: tokenData.token,
|
|
206
|
+
expiresAtMilliseconds:
|
|
207
|
+
tokenData.expiresAt.getTime() - TOKEN_EXPIRY_SAFETY_MARGIN_MS,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return tokenData.token;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Drops every cached token. Exists so tests never share one across cases.
|
|
214
|
+
public static clearTokenCache(): void {
|
|
215
|
+
GitHubConversation.tokenCache.clear();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private static repoApiUrl(data: {
|
|
219
|
+
organizationName: string;
|
|
220
|
+
repositoryName: string;
|
|
221
|
+
}): string {
|
|
222
|
+
return `https://api.github.com/repos/${encodeURIComponent(
|
|
223
|
+
data.organizationName,
|
|
224
|
+
)}/${encodeURIComponent(data.repositoryName)}`;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/*
|
|
228
|
+
* The app's own slug — what users type after the "@" and what its bot login
|
|
229
|
+
* (`<slug>[bot]`) is derived from.
|
|
230
|
+
*
|
|
231
|
+
* Read from GET /app rather than trusted from GITHUB_APP_NAME, because that
|
|
232
|
+
* variable holds the app's DISPLAY NAME. GitHub derives the slug from it by
|
|
233
|
+
* lowercasing and replacing spaces with hyphens, so an app named "OneUptime
|
|
234
|
+
* AI" is mentioned as "@oneuptime-ai" and a configuration that assumed
|
|
235
|
+
* otherwise would silently never match a mention. The env var stays as the
|
|
236
|
+
* fallback for instances whose credentials cannot reach GitHub.
|
|
237
|
+
*/
|
|
238
|
+
@CaptureSpan()
|
|
239
|
+
public static async getAppSlug(): Promise<string | null> {
|
|
240
|
+
try {
|
|
241
|
+
const cached: string | null = await GlobalCache.getString(
|
|
242
|
+
APP_SLUG_CACHE_NAMESPACE,
|
|
243
|
+
APP_SLUG_CACHE_KEY,
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
if (cached) {
|
|
247
|
+
return cached;
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
// A cache outage must not stop the app from answering mentions.
|
|
251
|
+
logger.debug(`Could not read the cached GitHub App slug: ${error}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
256
|
+
await API.get({
|
|
257
|
+
url: URL.fromString("https://api.github.com/app"),
|
|
258
|
+
headers: GitHubConversation.buildHeaders(GitHubUtil.generateAppJWT()),
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
if (result instanceof HTTPErrorResponse) {
|
|
262
|
+
throw result;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const slug: string | undefined = result.data["slug"]?.toString();
|
|
266
|
+
|
|
267
|
+
if (slug) {
|
|
268
|
+
await GlobalCache.setString(
|
|
269
|
+
APP_SLUG_CACHE_NAMESPACE,
|
|
270
|
+
APP_SLUG_CACHE_KEY,
|
|
271
|
+
slug,
|
|
272
|
+
{ expiresInSeconds: APP_SLUG_CACHE_SECONDS },
|
|
273
|
+
).catch((error: unknown) => {
|
|
274
|
+
logger.debug(`Could not cache the GitHub App slug: ${error}`);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
return slug;
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
logger.debug(
|
|
281
|
+
`Could not resolve the GitHub App slug from GitHub, falling back to GITHUB_APP_NAME: ${error}`,
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return GitHubConversation.slugifyAppName(GitHubAppName);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/*
|
|
289
|
+
* GitHub's own slug rule, applied to the configured display name: lowercase,
|
|
290
|
+
* every run of non-alphanumerics collapsed to a single hyphen, trimmed.
|
|
291
|
+
*/
|
|
292
|
+
public static slugifyAppName(appName: string | null): string | null {
|
|
293
|
+
if (!appName || !appName.trim()) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const slug: string = appName
|
|
298
|
+
.trim()
|
|
299
|
+
.toLowerCase()
|
|
300
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
301
|
+
.replace(/^-+|-+$/g, "");
|
|
302
|
+
|
|
303
|
+
return slug || null;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// The login GitHub attributes this app's own comments to.
|
|
307
|
+
public static toBotLogin(appSlug: string): string {
|
|
308
|
+
return `${appSlug.toLowerCase()}[bot]`;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/*
|
|
312
|
+
* True when a login belongs to ANY GitHub App, not just this one. The loop
|
|
313
|
+
* guard is deliberately broad: a comment written by any bot is never a human
|
|
314
|
+
* asking for work, and two bots mentioning each other is the failure mode
|
|
315
|
+
* that burns a budget overnight.
|
|
316
|
+
*/
|
|
317
|
+
public static isBotLogin(login: string | null | undefined): boolean {
|
|
318
|
+
return Boolean(login && login.toLowerCase().endsWith("[bot]"));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
@CaptureSpan()
|
|
322
|
+
public static async createIssueComment(data: {
|
|
323
|
+
installationId: string;
|
|
324
|
+
organizationName: string;
|
|
325
|
+
repositoryName: string;
|
|
326
|
+
issueNumber: number;
|
|
327
|
+
body: string;
|
|
328
|
+
}): Promise<GitHubIssueComment> {
|
|
329
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
330
|
+
data.installationId,
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> = await API.post(
|
|
334
|
+
{
|
|
335
|
+
url: URL.fromString(
|
|
336
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/${data.issueNumber}/comments`,
|
|
337
|
+
),
|
|
338
|
+
data: { body: data.body },
|
|
339
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
340
|
+
},
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
if (result instanceof HTTPErrorResponse) {
|
|
344
|
+
throw result;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return GitHubConversation.toIssueComment(result.data);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/*
|
|
351
|
+
* Editing the app's own acknowledgement in place, rather than appending a
|
|
352
|
+
* second comment, is what keeps a long-running run from turning a thread
|
|
353
|
+
* into a status log. One comment per command, updated as the run moves.
|
|
354
|
+
*/
|
|
355
|
+
@CaptureSpan()
|
|
356
|
+
public static async updateIssueComment(data: {
|
|
357
|
+
installationId: string;
|
|
358
|
+
organizationName: string;
|
|
359
|
+
repositoryName: string;
|
|
360
|
+
commentId: number;
|
|
361
|
+
body: string;
|
|
362
|
+
}): Promise<GitHubIssueComment> {
|
|
363
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
364
|
+
data.installationId,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
368
|
+
await API.patch({
|
|
369
|
+
url: URL.fromString(
|
|
370
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/comments/${data.commentId}`,
|
|
371
|
+
),
|
|
372
|
+
data: { body: data.body },
|
|
373
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
if (result instanceof HTTPErrorResponse) {
|
|
377
|
+
throw result;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return GitHubConversation.toIssueComment(result.data);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/*
|
|
384
|
+
* Reactions are the cheapest possible acknowledgement — they appear
|
|
385
|
+
* instantly, cost the reader nothing, and cannot themselves be mistaken for
|
|
386
|
+
* a mention. A failure to react is never worth failing a command over, so
|
|
387
|
+
* this swallows its errors and reports whether it landed.
|
|
388
|
+
*/
|
|
389
|
+
@CaptureSpan()
|
|
390
|
+
public static async addReactionToComment(data: {
|
|
391
|
+
installationId: string;
|
|
392
|
+
organizationName: string;
|
|
393
|
+
repositoryName: string;
|
|
394
|
+
commentId: number;
|
|
395
|
+
reaction: GitHubReaction;
|
|
396
|
+
}): Promise<boolean> {
|
|
397
|
+
try {
|
|
398
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
399
|
+
data.installationId,
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
403
|
+
await API.post({
|
|
404
|
+
url: URL.fromString(
|
|
405
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/comments/${data.commentId}/reactions`,
|
|
406
|
+
),
|
|
407
|
+
data: { content: data.reaction },
|
|
408
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
return !(result instanceof HTTPErrorResponse);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
logger.debug(`Could not add a GitHub reaction: ${error}`);
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@CaptureSpan()
|
|
419
|
+
public static async addReactionToIssue(data: {
|
|
420
|
+
installationId: string;
|
|
421
|
+
organizationName: string;
|
|
422
|
+
repositoryName: string;
|
|
423
|
+
issueNumber: number;
|
|
424
|
+
reaction: GitHubReaction;
|
|
425
|
+
}): Promise<boolean> {
|
|
426
|
+
try {
|
|
427
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
428
|
+
data.installationId,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
432
|
+
await API.post({
|
|
433
|
+
url: URL.fromString(
|
|
434
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/${data.issueNumber}/reactions`,
|
|
435
|
+
),
|
|
436
|
+
data: { content: data.reaction },
|
|
437
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
return !(result instanceof HTTPErrorResponse);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
logger.debug(`Could not add a GitHub reaction: ${error}`);
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
@CaptureSpan()
|
|
448
|
+
public static async getIssue(data: {
|
|
449
|
+
installationId: string;
|
|
450
|
+
organizationName: string;
|
|
451
|
+
repositoryName: string;
|
|
452
|
+
issueNumber: number;
|
|
453
|
+
}): Promise<GitHubIssueDetails> {
|
|
454
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
455
|
+
data.installationId,
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> = await API.get({
|
|
459
|
+
url: URL.fromString(
|
|
460
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/${data.issueNumber}`,
|
|
461
|
+
),
|
|
462
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
if (result instanceof HTTPErrorResponse) {
|
|
466
|
+
throw result;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const issue: JSONObject = result.data;
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
issueNumber: (issue["number"] as number) || data.issueNumber,
|
|
473
|
+
title: (issue["title"] as string) || "",
|
|
474
|
+
body: (issue["body"] as string) || "",
|
|
475
|
+
state: (issue["state"] as string) || "open",
|
|
476
|
+
htmlUrl: (issue["html_url"] as string) || "",
|
|
477
|
+
authorLogin: ((issue["user"] as JSONObject)?.["login"] as string) || "",
|
|
478
|
+
labels: GitHubConversation.toLabelNames(issue["labels"] as JSONArray),
|
|
479
|
+
isPullRequest: Boolean(issue["pull_request"]),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
@CaptureSpan()
|
|
484
|
+
public static async getPullRequestDetails(data: {
|
|
485
|
+
installationId: string;
|
|
486
|
+
organizationName: string;
|
|
487
|
+
repositoryName: string;
|
|
488
|
+
pullRequestNumber: number;
|
|
489
|
+
}): Promise<GitHubPullRequestDetails> {
|
|
490
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
491
|
+
data.installationId,
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> = await API.get({
|
|
495
|
+
url: URL.fromString(
|
|
496
|
+
`${GitHubConversation.repoApiUrl(data)}/pulls/${data.pullRequestNumber}`,
|
|
497
|
+
),
|
|
498
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
if (result instanceof HTTPErrorResponse) {
|
|
502
|
+
throw result;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const pullRequest: JSONObject = result.data;
|
|
506
|
+
const head: JSONObject = (pullRequest["head"] as JSONObject) || {};
|
|
507
|
+
const base: JSONObject = (pullRequest["base"] as JSONObject) || {};
|
|
508
|
+
|
|
509
|
+
return {
|
|
510
|
+
pullRequestNumber:
|
|
511
|
+
(pullRequest["number"] as number) || data.pullRequestNumber,
|
|
512
|
+
title: (pullRequest["title"] as string) || "",
|
|
513
|
+
body: (pullRequest["body"] as string) || "",
|
|
514
|
+
state: (pullRequest["state"] as string) || "open",
|
|
515
|
+
htmlUrl: (pullRequest["html_url"] as string) || "",
|
|
516
|
+
authorLogin:
|
|
517
|
+
((pullRequest["user"] as JSONObject)?.["login"] as string) || "",
|
|
518
|
+
headRefName: (head["ref"] as string) || "",
|
|
519
|
+
headSha: (head["sha"] as string) || "",
|
|
520
|
+
baseRefName: (base["ref"] as string) || "",
|
|
521
|
+
headRepositoryFullName:
|
|
522
|
+
((head["repo"] as JSONObject)?.["full_name"] as string) || null,
|
|
523
|
+
isDraft: pullRequest["draft"] === true,
|
|
524
|
+
isMerged: Boolean(pullRequest["merged_at"]),
|
|
525
|
+
changedFilesCount: (pullRequest["changed_files"] as number) || 0,
|
|
526
|
+
additions: (pullRequest["additions"] as number) || 0,
|
|
527
|
+
deletions: (pullRequest["deletions"] as number) || 0,
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/*
|
|
532
|
+
* The pull request's diff, file by file. Capped rather than fully paginated:
|
|
533
|
+
* a review prompt that cannot fit the diff is not improved by fetching more
|
|
534
|
+
* of it, and an unbounded loop over a 5,000-file pull request is a way to
|
|
535
|
+
* spend an hour of rate limit on a review nobody can read.
|
|
536
|
+
*/
|
|
537
|
+
@CaptureSpan()
|
|
538
|
+
public static async listPullRequestFiles(data: {
|
|
539
|
+
installationId: string;
|
|
540
|
+
organizationName: string;
|
|
541
|
+
repositoryName: string;
|
|
542
|
+
pullRequestNumber: number;
|
|
543
|
+
maxFiles: number;
|
|
544
|
+
}): Promise<Array<GitHubPullRequestFile>> {
|
|
545
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
546
|
+
data.installationId,
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
const files: Array<GitHubPullRequestFile> = [];
|
|
550
|
+
const perPage: number = 100;
|
|
551
|
+
let page: number = 1;
|
|
552
|
+
|
|
553
|
+
while (files.length < data.maxFiles) {
|
|
554
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONArray> = await API.get(
|
|
555
|
+
{
|
|
556
|
+
url: URL.fromString(
|
|
557
|
+
`${GitHubConversation.repoApiUrl(data)}/pulls/${data.pullRequestNumber}/files?per_page=${perPage}&page=${page}`,
|
|
558
|
+
),
|
|
559
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
560
|
+
},
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
if (result instanceof HTTPErrorResponse) {
|
|
564
|
+
throw result;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const pageFiles: JSONArray = result.data || [];
|
|
568
|
+
|
|
569
|
+
for (const entry of pageFiles) {
|
|
570
|
+
const file: JSONObject = entry as JSONObject;
|
|
571
|
+
files.push({
|
|
572
|
+
filename: (file["filename"] as string) || "",
|
|
573
|
+
status: (file["status"] as string) || "",
|
|
574
|
+
additions: (file["additions"] as number) || 0,
|
|
575
|
+
deletions: (file["deletions"] as number) || 0,
|
|
576
|
+
patch: (file["patch"] as string) || null,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (pageFiles.length < perPage) {
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
page++;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return files.slice(0, data.maxFiles);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/*
|
|
591
|
+
* The most RECENT comments on an issue or pull request, returned oldest
|
|
592
|
+
* first so the agent reads them the way a person would.
|
|
593
|
+
*
|
|
594
|
+
* Fetched newest-first and then reversed, rather than taking the first page
|
|
595
|
+
* of GitHub's default oldest-first ordering. On a long thread those are
|
|
596
|
+
* opposite things: the first page of a 200-comment issue is the discussion
|
|
597
|
+
* from six months ago, and the review feedback that prompted this run is on
|
|
598
|
+
* the last page. Asking for the newest is the only way to get the relevant
|
|
599
|
+
* ones without paginating the whole thread.
|
|
600
|
+
*
|
|
601
|
+
* The app's OWN comments are returned too: the caller — not this reader —
|
|
602
|
+
* decides what to do with bot authorship.
|
|
603
|
+
*/
|
|
604
|
+
@CaptureSpan()
|
|
605
|
+
public static async listIssueComments(data: {
|
|
606
|
+
installationId: string;
|
|
607
|
+
organizationName: string;
|
|
608
|
+
repositoryName: string;
|
|
609
|
+
issueNumber: number;
|
|
610
|
+
maxComments: number;
|
|
611
|
+
}): Promise<Array<GitHubIssueComment>> {
|
|
612
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
613
|
+
data.installationId,
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONArray> = await API.get({
|
|
617
|
+
url: URL.fromString(
|
|
618
|
+
`${GitHubConversation.repoApiUrl(data)}/issues/${data.issueNumber}/comments?sort=created&direction=desc&per_page=${Math.min(
|
|
619
|
+
Math.max(data.maxComments, 1),
|
|
620
|
+
100,
|
|
621
|
+
)}`,
|
|
622
|
+
),
|
|
623
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
if (result instanceof HTTPErrorResponse) {
|
|
627
|
+
throw result;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return (result.data || [])
|
|
631
|
+
.map((entry: JSONObject) => {
|
|
632
|
+
return GitHubConversation.toIssueComment(entry);
|
|
633
|
+
})
|
|
634
|
+
.slice(0, data.maxComments)
|
|
635
|
+
.reverse();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/*
|
|
639
|
+
* Post a review on a pull request.
|
|
640
|
+
*
|
|
641
|
+
* ALWAYS submitted as `COMMENT`, never APPROVE or REQUEST_CHANGES. An
|
|
642
|
+
* approval from the app would satisfy a branch protection rule, which would
|
|
643
|
+
* make an automated reviewer into an automated merger — the one thing this
|
|
644
|
+
* integration must never become. Its opinion belongs in the text.
|
|
645
|
+
*
|
|
646
|
+
* Inline comments are best-effort: GitHub answers 422 for any anchor that is
|
|
647
|
+
* not part of the diff (a line the agent misjudged, a file whose patch was
|
|
648
|
+
* elided, a review racing a force-push). Losing the whole review to one bad
|
|
649
|
+
* anchor is far worse than losing the anchors, so a 422 retries with the
|
|
650
|
+
* body alone.
|
|
651
|
+
*/
|
|
652
|
+
@CaptureSpan()
|
|
653
|
+
public static async createPullRequestReview(data: {
|
|
654
|
+
installationId: string;
|
|
655
|
+
organizationName: string;
|
|
656
|
+
repositoryName: string;
|
|
657
|
+
pullRequestNumber: number;
|
|
658
|
+
body: string;
|
|
659
|
+
comments: Array<GitHubReviewComment>;
|
|
660
|
+
commitSha?: string | undefined;
|
|
661
|
+
}): Promise<string> {
|
|
662
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
663
|
+
data.installationId,
|
|
664
|
+
);
|
|
665
|
+
|
|
666
|
+
const url: URL = URL.fromString(
|
|
667
|
+
`${GitHubConversation.repoApiUrl(data)}/pulls/${data.pullRequestNumber}/reviews`,
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
const headers: Headers = GitHubConversation.buildHeaders(token);
|
|
671
|
+
|
|
672
|
+
const basePayload: JSONObject = {
|
|
673
|
+
body: data.body,
|
|
674
|
+
event: "COMMENT",
|
|
675
|
+
...(data.commitSha ? { commit_id: data.commitSha } : {}),
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
let result: HTTPErrorResponse | HTTPResponse<JSONObject> = await API.post({
|
|
679
|
+
url: url,
|
|
680
|
+
data:
|
|
681
|
+
data.comments.length > 0
|
|
682
|
+
? {
|
|
683
|
+
...basePayload,
|
|
684
|
+
comments: data.comments.map((comment: GitHubReviewComment) => {
|
|
685
|
+
return {
|
|
686
|
+
path: comment.path,
|
|
687
|
+
line: comment.line,
|
|
688
|
+
side: "RIGHT",
|
|
689
|
+
body: comment.body,
|
|
690
|
+
};
|
|
691
|
+
}),
|
|
692
|
+
}
|
|
693
|
+
: basePayload,
|
|
694
|
+
headers: headers,
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
if (
|
|
698
|
+
result instanceof HTTPErrorResponse &&
|
|
699
|
+
data.comments.length > 0 &&
|
|
700
|
+
result.statusCode === 422
|
|
701
|
+
) {
|
|
702
|
+
logger.debug(
|
|
703
|
+
`GitHub rejected the inline comments on the review for ${data.organizationName}/${data.repositoryName}#${data.pullRequestNumber}; posting the review body on its own.`,
|
|
704
|
+
);
|
|
705
|
+
|
|
706
|
+
result = await API.post({
|
|
707
|
+
url: url,
|
|
708
|
+
data: basePayload,
|
|
709
|
+
headers: headers,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
if (result instanceof HTTPErrorResponse) {
|
|
714
|
+
throw result;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
return (result.data["html_url"] as string) || "";
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/*
|
|
721
|
+
* What a GitHub user may do in this repository.
|
|
722
|
+
*
|
|
723
|
+
* This is the authorization question for every command: a repository's
|
|
724
|
+
* conversation is open to anyone with a GitHub account, so `author_association`
|
|
725
|
+
* on the webhook payload ("CONTRIBUTOR", "NONE") is a description of past
|
|
726
|
+
* activity, not a permission. Only this endpoint answers the actual one.
|
|
727
|
+
*
|
|
728
|
+
* A failure answers None. Denying a command because GitHub was unreachable
|
|
729
|
+
* is a bad minute; running one because GitHub was unreachable is a breach.
|
|
730
|
+
*/
|
|
731
|
+
@CaptureSpan()
|
|
732
|
+
public static async getUserRepositoryPermission(data: {
|
|
733
|
+
installationId: string;
|
|
734
|
+
organizationName: string;
|
|
735
|
+
repositoryName: string;
|
|
736
|
+
username: string;
|
|
737
|
+
}): Promise<GitHubRepositoryPermission> {
|
|
738
|
+
try {
|
|
739
|
+
const token: string = await GitHubConversation.getConversationToken(
|
|
740
|
+
data.installationId,
|
|
741
|
+
);
|
|
742
|
+
|
|
743
|
+
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
744
|
+
await API.get({
|
|
745
|
+
url: URL.fromString(
|
|
746
|
+
`${GitHubConversation.repoApiUrl(data)}/collaborators/${encodeURIComponent(
|
|
747
|
+
data.username,
|
|
748
|
+
)}/permission`,
|
|
749
|
+
),
|
|
750
|
+
headers: GitHubConversation.buildHeaders(token),
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
if (result instanceof HTTPErrorResponse) {
|
|
754
|
+
/*
|
|
755
|
+
* 404 is GitHub's answer for "not a collaborator" as well as for
|
|
756
|
+
* "no such user" — both mean no permission, and neither is an error
|
|
757
|
+
* worth logging as one.
|
|
758
|
+
*/
|
|
759
|
+
if (result.statusCode !== 404) {
|
|
760
|
+
logger.warn(
|
|
761
|
+
`Could not read the GitHub repository permission for ${data.username} on ${data.organizationName}/${data.repositoryName}: ${result.statusCode}`,
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return GitHubRepositoryPermission.None;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
const permission: string = (
|
|
769
|
+
(result.data["permission"] as string) || "none"
|
|
770
|
+
).toLowerCase();
|
|
771
|
+
|
|
772
|
+
/*
|
|
773
|
+
* The top-level `permission` field collapses "maintain" to "write" and
|
|
774
|
+
* "triage" to "read" for backwards compatibility. `role_name` carries
|
|
775
|
+
* the real role, so prefer it when GitHub sends one.
|
|
776
|
+
*/
|
|
777
|
+
const roleName: string = (
|
|
778
|
+
(result.data["role_name"] as string) || permission
|
|
779
|
+
).toLowerCase();
|
|
780
|
+
|
|
781
|
+
if (
|
|
782
|
+
Object.values(GitHubRepositoryPermission).includes(
|
|
783
|
+
roleName as GitHubRepositoryPermission,
|
|
784
|
+
)
|
|
785
|
+
) {
|
|
786
|
+
return roleName as GitHubRepositoryPermission;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (
|
|
790
|
+
Object.values(GitHubRepositoryPermission).includes(
|
|
791
|
+
permission as GitHubRepositoryPermission,
|
|
792
|
+
)
|
|
793
|
+
) {
|
|
794
|
+
return permission as GitHubRepositoryPermission;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
return GitHubRepositoryPermission.None;
|
|
798
|
+
} catch (error) {
|
|
799
|
+
logger.warn(
|
|
800
|
+
`Could not read the GitHub repository permission for ${data.username}: ${error}`,
|
|
801
|
+
);
|
|
802
|
+
return GitHubRepositoryPermission.None;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Permission levels that may command the app. Read and Triage may not.
|
|
807
|
+
public static canCommandApp(permission: GitHubRepositoryPermission): boolean {
|
|
808
|
+
return (
|
|
809
|
+
permission === GitHubRepositoryPermission.Write ||
|
|
810
|
+
permission === GitHubRepositoryPermission.Maintain ||
|
|
811
|
+
permission === GitHubRepositoryPermission.Admin
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
private static toLabelNames(labels: JSONArray | undefined): Array<string> {
|
|
816
|
+
if (!labels) {
|
|
817
|
+
return [];
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return labels
|
|
821
|
+
.map((label: JSONObject) => {
|
|
822
|
+
return typeof label === "string"
|
|
823
|
+
? (label as unknown as string)
|
|
824
|
+
: ((label as JSONObject)?.["name"] as string) || "";
|
|
825
|
+
})
|
|
826
|
+
.filter((name: string) => {
|
|
827
|
+
return Boolean(name);
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
private static toIssueComment(comment: JSONObject): GitHubIssueComment {
|
|
832
|
+
const authorLogin: string =
|
|
833
|
+
((comment["user"] as JSONObject)?.["login"] as string) || "";
|
|
834
|
+
|
|
835
|
+
return {
|
|
836
|
+
commentId: (comment["id"] as number) || 0,
|
|
837
|
+
htmlUrl: (comment["html_url"] as string) || "",
|
|
838
|
+
body: (comment["body"] as string) || "",
|
|
839
|
+
authorLogin: authorLogin,
|
|
840
|
+
isBot:
|
|
841
|
+
((comment["user"] as JSONObject)?.["type"] as string) === "Bot" ||
|
|
842
|
+
GitHubConversation.isBotLogin(authorLogin),
|
|
843
|
+
createdAt: (comment["created_at"] as string) || "",
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
}
|