Skip to content

Commit

Permalink
Merge branch 'master' into pipeline-ui-spark-graph
Browse files Browse the repository at this point in the history
  • Loading branch information
Twixes authored Jan 16, 2024
2 parents 36df94c + d759793 commit 232164f
Show file tree
Hide file tree
Showing 103 changed files with 1,607 additions and 576 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/container-images-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ jobs:
- name: Check for changes in plugins directory
id: check_changes_plugins
run: |
echo "changed=$(git diff --name-only HEAD^ HEAD | grep '^plugin-server/' || true)" >> $GITHUB_OUTPUT
echo "changed=$((git diff --name-only HEAD^ HEAD | grep -q '^plugin-server/' && echo true) || echo false)" >> $GITHUB_OUTPUT
- name: Trigger Ingestion Cloud deployment
if: steps.check_changes_plugins.outputs.changed != ''
if: steps.check_changes_plugins.outputs.changed == 'true'
uses: mvasigh/dispatch-action@main
with:
token: ${{ steps.deployer.outputs.token }}
Expand All @@ -116,10 +116,10 @@ jobs:
- name: Check for changes that affect batch exports temporal worker
id: check_changes_batch_exports_temporal_worker
run: |
echo "changed=$(git diff --name-only HEAD^ HEAD | grep -E '^posthog/temporal/common|^posthog/temporal/batch_exports|^posthog/batch_exports/|^posthog/management/commands/start_temporal_worker.py$' || true)" >> $GITHUB_OUTPUT
echo "changed=$((git diff --name-only HEAD^ HEAD | grep -qE '^posthog/temporal/common|^posthog/temporal/batch_exports|^posthog/batch_exports/|^posthog/management/commands/start_temporal_worker.py$' && echo true) || echo false)" >> $GITHUB_OUTPUT
- name: Trigger Batch Exports Temporal Worker Cloud deployment
if: steps.check_changes_batch_exports_temporal_worker.outputs.changed != ''
if: steps.check_changes_batch_exports_temporal_worker.outputs.changed == 'true'
uses: mvasigh/dispatch-action@main
with:
token: ${{ steps.deployer.outputs.token }}
Expand All @@ -135,10 +135,10 @@ jobs:
- name: Check for changes that affect data warehouse temporal worker
id: check_changes_data_warehouse_temporal_worker
run: |
echo "changed=$(git diff --name-only HEAD^ HEAD | grep -E '^posthog/temporal/common|^posthog/temporal/data_imports|^posthog/warehouse/|^posthog/management/commands/start_temporal_worker.py$' || true)" >> $GITHUB_OUTPUT
echo "changed=$((git diff --name-only HEAD^ HEAD | grep -qE '^posthog/temporal/common|^posthog/temporal/data_imports|^posthog/warehouse/|^posthog/management/commands/start_temporal_worker.py$' && echo true) || echo false)" >> $GITHUB_OUTPUT
- name: Trigger Data Warehouse Temporal Worker Cloud deployment
if: steps.check_changes_data_warehouse_temporal_worker.outputs.changed != ''
if: steps.check_changes_data_warehouse_temporal_worker.outputs.changed == 'true'
uses: mvasigh/dispatch-action@main
with:
token: ${{ steps.deployer.outputs.token }}
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/systemStatus.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { urls } from 'scenes/urls'

describe('System Status', () => {
it('System Status loaded', () => {
cy.location('pathname').should('eq', urls.savedInsights())
cy.location('pathname').should('eq', '/project/1/insights')
cy.wait(500)
cy.get('[data-attr=menu-item-me]').click()
cy.get('[data-attr=system-status-badge]').click()
Expand Down
Binary file modified frontend/__snapshots__/scenes-app-apps--installed--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-apps--installed--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 34 additions & 3 deletions frontend/src/layout/navigation-3000/navigationLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@ import {
IconTestTube,
IconToggle,
} from '@posthog/icons'
import { lemonToast } from '@posthog/lemon-ui'
import { lemonToast, Spinner } from '@posthog/lemon-ui'
import { captureException } from '@sentry/react'
import { actions, connect, events, kea, listeners, path, props, reducers, selectors } from 'kea'
import { router } from 'kea-router'
import { subscriptions } from 'kea-subscriptions'
import { FEATURE_FLAGS } from 'lib/constants'
import { IconPlusMini } from 'lib/lemon-ui/icons'
import { LemonMenuOverlay } from 'lib/lemon-ui/LemonMenu/LemonMenu'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { isNotNil } from 'lib/utils'
import React from 'react'
import { sceneLogic } from 'scenes/sceneLogic'
import { Scene } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'

import { dashboardsModel } from '~/models/dashboardsModel'

import { navigationLogic } from '../navigation/navigationLogic'
import type { navigation3000LogicType } from './navigationLogicType'
import { dashboardsSidebarLogic } from './sidebars/dashboards'
Expand Down Expand Up @@ -312,8 +315,12 @@ export const navigation3000Logic = kea<navigation3000LogicType>([
(isNavCollapsedDesktop, mobileLayout): boolean => !mobileLayout && isNavCollapsedDesktop,
],
navbarItems: [
() => [featureFlagLogic.selectors.featureFlags],
(featureFlags): NavbarItem[][] => {
() => [
featureFlagLogic.selectors.featureFlags,
dashboardsModel.selectors.dashboardsLoading,
dashboardsModel.selectors.pinnedDashboards,
],
(featureFlags, dashboardsLoading, pinnedDashboards): NavbarItem[][] => {
const isUsingSidebar = featureFlags[FEATURE_FLAGS.POSTHOG_3000_NAV]
return [
[
Expand All @@ -329,6 +336,30 @@ export const navigation3000Logic = kea<navigation3000LogicType>([
icon: <IconDashboard />,
logic: isUsingSidebar ? dashboardsSidebarLogic : undefined,
to: isUsingSidebar ? undefined : urls.dashboards(),
sideAction: {
identifier: 'pinned-dashboards-dropdown',
dropdown: {
overlay: (
<LemonMenuOverlay
items={[
{
title: 'Pinned dashboards',
items: pinnedDashboards.map((dashboard) => ({
label: dashboard.name,
to: urls.dashboard(dashboard.id),
})),
footer: dashboardsLoading && (
<div className="px-2 py-1 text-text-secondary-3000">
<Spinner /> Loading…
</div>
),
},
]}
/>
),
placement: 'bottom-end',
},
},
},
{
identifier: Scene.Notebooks,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/layout/navigation-3000/sidepanel/SidePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { SidePanelActivation, SidePanelActivationIcon } from './panels/SidePanel
import { SidePanelDocs } from './panels/SidePanelDocs'
import { SidePanelFeaturePreviews } from './panels/SidePanelFeaturePreviews'
import { SidePanelSettings } from './panels/SidePanelSettings'
import { SidePanelStatus, SidePanelStatusIcon } from './panels/SidePanelStatus'
import { SidePanelSupport } from './panels/SidePanelSupport'
import { SidePanelWelcome } from './panels/SidePanelWelcome'
import { sidePanelLogic } from './sidePanelLogic'
Expand Down Expand Up @@ -71,6 +72,11 @@ export const SIDE_PANEL_TABS: Record<SidePanelTab, { label: string; Icon: any; C
Icon: IconConfetti,
Content: SidePanelWelcome,
},
[SidePanelTab.Status]: {
label: 'System status',
Icon: SidePanelStatusIcon,
Content: SidePanelStatus,
},
}

const DEFAULT_WIDTH = 512
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Menu = {
url?: string
}

function SidePanelDocsSkeleton(): JSX.Element {
export function SidePanelDocsSkeleton(): JSX.Element {
return (
<div className="absolute inset-0 p-4 space-y-2">
<LemonSkeleton className="w-full h-10 mb-12" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { IconCloud, IconExternal } from '@posthog/icons'
import { LemonButton, Tooltip } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useActions, useValues } from 'kea'
import { IconWithBadge } from 'lib/lemon-ui/icons'
import { useState } from 'react'

import { SidePanelPaneHeader } from '../components/SidePanelPaneHeader'
import { sidePanelLogic } from '../sidePanelLogic'
import { SidePanelDocsSkeleton } from './SidePanelDocs'
import { sidePanelStatusLogic, STATUS_PAGE_BASE } from './sidePanelStatusLogic'

export const SidePanelStatusIcon = (props: { className?: string }): JSX.Element => {
const { status, statusPage } = useValues(sidePanelStatusLogic)

let title = statusPage?.status.description
if (statusPage?.status.description === 'All Systems Operational') {
title = 'All systems operational' // Sentence-case Statuspage.io default message, which can't be changed
}

return (
<Tooltip title={title} placement="left">
<span {...props}>
<IconWithBadge
content={status !== 'operational' ? '!' : '✓'}
status={status.includes('outage') ? 'danger' : status.includes('degraded') ? 'warning' : 'success'}
>
<IconCloud />
</IconWithBadge>
</span>
</Tooltip>
)
}

export const SidePanelStatus = (): JSX.Element => {
const { closeSidePanel } = useActions(sidePanelLogic)
const [ready, setReady] = useState(false)

return (
<>
<SidePanelPaneHeader>
<div className="flex-1" />
<LemonButton
size="small"
sideIcon={<IconExternal />}
targetBlank
// We can't use the normal `to` property as that is intercepted to open this panel :D
onClick={() => {
window.open(STATUS_PAGE_BASE, '_blank')?.focus()
closeSidePanel()
}}
>
Open in new tab
</LemonButton>
</SidePanelPaneHeader>
<div className="relative flex-1 overflow-hidden">
<iframe
src={STATUS_PAGE_BASE}
title="Status"
className={clsx('w-full h-full', !ready && 'hidden')}
onLoad={() => setReady(true)}
/>

{!ready && <SidePanelDocsSkeleton />}
</div>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { actions, afterMount, beforeUnmount, connect, kea, listeners, path, reducers } from 'kea'
import { loaders } from 'kea-loaders'
import { FEATURE_FLAGS } from 'lib/constants'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'

import { sidePanelStateLogic } from '../sidePanelStateLogic'
import type { sidePanelStatusLogicType } from './sidePanelStatusLogicType'

export type SPIndicator = 'none' | 'minor' | 'major'

export type SPComponentStatus = 'operational' | 'degraded_performance' | 'partial_outage' | 'major_outage'

export interface SPSummary {
// page: SPPage
components: SPComponent[]
incidents: SPIncident[]
scheduled_maintenances: any[]
status: SPStatus
}

export interface SPComponent {
id: string
name: string
status: SPComponentStatus
created_at: Date
updated_at: Date
position: number
description: null | string
showcase: boolean
start_date: Date | null
group_id: null | string
page_id: string
group: boolean
only_show_if_degraded: boolean
components?: string[]
}

export interface SPIncident {
id: string
name: string
status: string
created_at: Date
updated_at: Date
monitoring_at: null
resolved_at: null
impact: string
shortlink: string
started_at: Date
page_id: string
incident_updates: SPIncidentUpdate[]
components: SPComponent[]
reminder_intervals: string
}

export interface SPIncidentUpdate {
id: string
status: string
body: string
incident_id: string
created_at: Date
updated_at: Date
display_at: Date
affected_components: SPAffectedComponent[]
deliver_notifications: boolean
custom_tweet: null
tweet_id: null
}

export interface SPAffectedComponent {
code: string
name: string
old_status: string
new_status: string
}

export interface SPStatus {
indicator: SPIndicator
description: string
}

export const STATUS_PAGE_BASE = 'https://status.posthog.com'

// NOTE: Test account with some incidents - ask @benjackwhite for access
// export const STATUS_PAGE_BASE = 'https://posthogtesting.statuspage.io'

// Map the hostname to relevant groups (found via the summary.json endpoint)
const RELEVANT_GROUPS_MAP = {
'us.posthog.com': ['41df083ftqt6', 'z0y6m9kyvy3j'],
'eu.posthog.com': ['c4d9jd1jcx3f', 'nfknrn2bf3yz'],
localhost: ['f58xx1143yvt', 't3rdjq2z0x7p'], // localhost has IDs for the test status page - that way we really only show it if local dev and overridden to use the other status page
}

export const REFRESH_INTERVAL = 60 * 1000 * 5 // 5 minutes

export const sidePanelStatusLogic = kea<sidePanelStatusLogicType>([
path(['scenes', 'navigation', 'sidepanel', 'sidePanelStatusLogic']),
connect({
values: [featureFlagLogic, ['featureFlags']],
actions: [sidePanelStateLogic, ['openSidePanel', 'closeSidePanel']],
}),

actions({
loadStatusPage: true,
}),

reducers(() => ({
// Persisted copy to avoid flash effect on page load
status: [
'operational' as SPComponentStatus,
{ persist: true },
{
loadStatusPageSuccess: (_, { statusPage }) => {
const relevantGroups = RELEVANT_GROUPS_MAP[window.location.hostname]
if (!relevantGroups) {
return 'operational'
}

return (
statusPage.components.find(
({ group_id, status }) => relevantGroups.includes(group_id) && status !== 'operational'
)?.status || 'operational'
)
},
loadStatusPageFailure: () => 'operational',
},
],
})),

loaders(() => ({
statusPage: [
null as SPSummary | null,
{
loadStatusPage: async () => {
const response = await fetch(`${STATUS_PAGE_BASE}/api/v2/summary.json`)
const data: SPSummary = await response.json()

return data
},
},
],
})),

listeners(({ actions, cache }) => ({
loadStatusPageSuccess: () => {
clearTimeout(cache.timeout)
cache.timeout = setTimeout(() => actions.loadStatusPage(), REFRESH_INTERVAL)
},
})),

afterMount(({ actions, values }) => {
if (values.featureFlags[FEATURE_FLAGS.SIDEPANEL_STATUS]) {
actions.loadStatusPage()
}
}),

beforeUnmount(({ cache }) => {
clearTimeout(cache.timeout)
}),
])
Loading

0 comments on commit 232164f

Please sign in to comment.