Skip to content

Commit

Permalink
Merge branch 'master' into remove-filter-based-card-content
Browse files Browse the repository at this point in the history
  • Loading branch information
thmsobrmlr committed Jul 25, 2024
2 parents 70ec111 + 51a4b31 commit a8a5910
Show file tree
Hide file tree
Showing 192 changed files with 4,313 additions and 882 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-plugin-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
- 'plugin-server/**'
- 'posthog/clickhouse/migrations/**'
- 'ee/migrations/**'
- 'ee/management/commands/setup_test_environment.py'
- 'posthog/management/commands/setup_test_environment.py'
- 'posthog/migrations/**'
- 'posthog/plugins/**'
- 'docker*.yml'
Expand Down
62 changes: 59 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
- '.github/workflows/rust.yml'
- '.github/workflows/rust-docker-build.yml'
- '.github/workflows/rust-hook-migrator-docker.yml'
- 'posthog/management/commands/setup_test_environment.py'
- 'posthog/migrations/**'
- 'ee/migrations/**'
build:
name: Build rust services
Expand Down Expand Up @@ -73,6 +76,11 @@ jobs:

test:
name: Test rust services
strategy:
matrix:
package:
- feature-flags
- others
needs: changes
runs-on: depot-ubuntu-22.04-4
timeout-minutes: 10
Expand All @@ -86,11 +94,15 @@ jobs:
# Use sparse checkout to only select files in rust directory
# Turning off cone mode ensures that files in the project root are not included during checkout
- uses: actions/checkout@v3
if: needs.changes.outputs.rust == 'true'
if: needs.changes.outputs.rust == 'true' && matrix.package == 'others'
with:
sparse-checkout: 'rust/'
sparse-checkout-cone-mode: false

# For flags checkout entire repository
- uses: actions/checkout@v3
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'

- name: Login to DockerHub
if: needs.changes.outputs.rust == 'true'
uses: docker/login-action@v2
Expand All @@ -99,8 +111,15 @@ jobs:
username: posthog
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Setup main repo dependencies for flags
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'
run: |
docker compose -f ../docker-compose.dev.yml down
docker compose -f ../docker-compose.dev.yml up -d
echo "127.0.0.1 kafka" | sudo tee -a /etc/hosts
- name: Setup dependencies
if: needs.changes.outputs.rust == 'true'
if: needs.changes.outputs.rust == 'true' && matrix.package == 'others'
run: |
docker compose up kafka redis db echo_server -d --wait
docker compose up setup_test_db
Expand All @@ -119,9 +138,46 @@ jobs:
rust/target
key: ${ runner.os }-cargo-debug-${{ hashFiles('**/Cargo.lock') }}

- name: Set up Python
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'
uses: actions/setup-python@v5
with:
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

# uv is a fast pip alternative: https://github.com/astral-sh/uv/
- run: pip install uv
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'

- name: Install SAML (python3-saml) dependencies
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'
run: |
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
- name: Install python dependencies
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'
run: |
uv pip install --system -r ../requirements-dev.txt
uv pip install --system -r ../requirements.txt
- name: Set up databases
if: needs.changes.outputs.rust == 'true' && matrix.package == 'feature-flags'
env:
DEBUG: 'true'
TEST: 'true'
SECRET_KEY: 'abcdef' # unsafe - for testing only
DATABASE_URL: 'postgres://posthog:posthog@localhost:5432/posthog'
run: cd ../ && python manage.py setup_test_environment --only-postgres

- name: Run cargo test
if: needs.changes.outputs.rust == 'true'
run: cargo test --all-features
run: |
echo "Starting cargo test"
cargo test --all-features ${{ matrix.package == 'feature-flags' && '--package feature-flags' || '--workspace --exclude feature-flags' }}
echo "Cargo test completed"
linting:
name: Lint rust services
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
remove-issue-stale-when-updated: true
days-before-pr-stale: 7
days-before-pr-close: 7
stale-pr-message: "This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the `stale` label – otherwise this will be closed in another week."
stale-pr-message: "This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the `stale` label – otherwise this will be closed in another week. If you want to permanentely keep it open, use the `waiting` label."
close-pr-message: "This PR was closed due to lack of activity. Feel free to reopen if it's still relevant."
stale-pr-label: stale
remove-pr-stale-when-updated: true
Expand Down
6 changes: 2 additions & 4 deletions .storybook/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ async function expectStoryToMatchSnapshot(
})

// Wait for all images to load
await page.waitForFunction(() => Array.from(document.images).every((i: HTMLImageElement) => i.complete))
await waitForPageReady(page)
await page.waitForLoadState('networkidle')
await page.waitForFunction(() => Array.from(document.images).every((i: HTMLImageElement) => !!i.naturalWidth))
await page.waitForTimeout(2000)

await check(page, context, browser, 'light', storyContext.parameters?.testOptions?.snapshotTargetSelector)
Expand All @@ -174,9 +173,8 @@ async function expectStoryToMatchSnapshot(
})

// Wait for all images to load
await page.waitForFunction(() => Array.from(document.images).every((i: HTMLImageElement) => i.complete))
await waitForPageReady(page)
await page.waitForLoadState('networkidle')
await page.waitForFunction(() => Array.from(document.images).every((i: HTMLImageElement) => !!i.naturalWidth))
await page.waitForTimeout(100)

await check(page, context, browser, 'dark', storyContext.parameters?.testOptions?.snapshotTargetSelector)
Expand Down
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.
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/services/mysql.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 25 additions & 1 deletion frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import posthog from 'posthog-js'
import { SavedSessionRecordingPlaylistsResult } from 'scenes/session-recordings/saved-playlists/savedSessionRecordingPlaylistsLogic'

import { getCurrentExporterData } from '~/exporter/exporterViewLogic'
import { DatabaseSerializedFieldType, QuerySchema, QueryStatusResponse, RefreshType } from '~/queries/schema'
import {
DatabaseSerializedFieldType,
ErrorTrackingGroup,
QuerySchema,
QueryStatusResponse,
RefreshType,
} from '~/queries/schema'
import {
ActionType,
ActivityScope,
Expand Down Expand Up @@ -658,6 +664,15 @@ class ApiRequest {
return this.surveys(teamId).addPathComponent('activity')
}

// Error tracking
public errorTracking(teamId?: TeamType['id']): ApiRequest {
return this.projectsDetail(teamId).addPathComponent('error_tracking')
}

public errorTrackingGroup(fingerprint: ErrorTrackingGroup['fingerprint'], teamId?: TeamType['id']): ApiRequest {
return this.errorTracking(teamId).addPathComponent(fingerprint)
}

// # Warehouse
public dataWarehouseTables(teamId?: TeamType['id']): ApiRequest {
return this.projectsDetail(teamId).addPathComponent('warehouse_tables')
Expand Down Expand Up @@ -1698,6 +1713,15 @@ const api = {
},
},

errorTracking: {
async update(
fingerprint: ErrorTrackingGroup['fingerprint'],
data: Partial<Pick<ErrorTrackingGroup, 'assignee'>>
): Promise<ErrorTrackingGroup> {
return await new ApiRequest().errorTrackingGroup(fingerprint).update({ data })
},
},

recordings: {
async list(params: Record<string, any>): Promise<SessionRecordingsResponse> {
return await new ApiRequest().recordings().withQueryString(toParams(params)).get()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { render } from '@testing-library/react'
import { MOCK_TEAM_ID } from 'lib/api.mock'
import { makeTestSetup } from 'lib/components/ActivityLog/activityLogLogic.test.setup'

import { BreakdownFilter } from '~/queries/schema'
import { ActivityScope } from '~/types'

jest.mock('lib/colors')
Expand Down Expand Up @@ -84,81 +85,104 @@ describe('the activity log logic', () => {
})

it('can handle change of insight query', async () => {
const logic = await insightTestSetup('test insight', 'updated', [
{
type: ActivityScope.INSIGHT,
action: 'changed',
field: 'query',
after: {
kind: 'TrendsQuery',
properties: {
type: 'AND',
values: [
{
type: 'OR',
values: [
{
type: 'event',
key: '$current_url',
operator: 'exact',
value: ['https://hedgebox.net/files/'],
},
{
type: 'event',
key: '$geoip_country_code',
operator: 'exact',
value: ['US', 'AU'],
},
],
},
],
},
filterTestAccounts: false,
interval: 'day',
dateRange: {
date_from: '-7d',
},
series: [
const insightMock = {
type: ActivityScope.INSIGHT,
action: 'changed',
field: 'query',
after: {
kind: 'TrendsQuery',
properties: {
type: 'AND',
values: [
{
kind: 'EventsNode',
name: '$pageview',
custom_name: 'Views',
event: '$pageview',
properties: [
type: 'OR',
values: [
{
type: 'event',
key: '$browser',
key: '$current_url',
operator: 'exact',
value: 'Chrome',
value: ['https://hedgebox.net/files/'],
},
{
type: 'cohort',
key: 'id',
value: 2,
type: 'event',
key: '$geoip_country_code',
operator: 'exact',
value: ['US', 'AU'],
},
],
limit: 100,
},
],
trendsFilter: {
display: 'ActionsAreaGraph',
},
breakdownFilter: {
breakdown: '$geoip_country_code',
breakdown_type: 'event',
},
filterTestAccounts: false,
interval: 'day',
dateRange: {
date_from: '-7d',
},
series: [
{
kind: 'EventsNode',
name: '$pageview',
custom_name: 'Views',
event: '$pageview',
properties: [
{
type: 'event',
key: '$browser',
operator: 'exact',
value: 'Chrome',
},
{
type: 'cohort',
key: 'id',
value: 2,
},
],
limit: 100,
},
],
trendsFilter: {
display: 'ActionsAreaGraph',
},
breakdownFilter: {
breakdown: '$geoip_country_code',
breakdown_type: 'event',
},
},
])
const actual = logic.values.humanizedActivity
}

const renderedDescription = render(<>{actual[0].description}</>).container
let logic = await insightTestSetup('test insight', 'updated', [insightMock as any])
let actual = logic.values.humanizedActivity

let renderedDescription = render(<>{actual[0].description}</>).container
expect(renderedDescription).toHaveTextContent('peter changed query definition on test insight')

const renderedExtendedDescription = render(<>{actual[0].extendedDescription}</>).container
let renderedExtendedDescription = render(<>{actual[0].extendedDescription}</>).container
expect(renderedExtendedDescription).toHaveTextContent(
"Query summaryAShowing \"Views\"Pageviewcounted by total countwhere event'sBrowser= equals Chromeand person belongs to cohortID 2FiltersEvent'sCurrent URL= equals https://hedgebox.net/files/or event'sCountry Code= equals US or AUBreakdown byCountry Code"
)
;(insightMock.after.breakdownFilter as BreakdownFilter) = {
breakdowns: [
{
property: '$geoip_country_code',
type: 'event',
},
{
property: '$session_duration',
type: 'session',
},
],
}

logic = await insightTestSetup('test insight', 'updated', [insightMock as any])
actual = logic.values.humanizedActivity

renderedDescription = render(<>{actual[0].description}</>).container
expect(renderedDescription).toHaveTextContent('peter changed query definition on test insight')

renderedExtendedDescription = render(<>{actual[0].extendedDescription}</>).container
expect(renderedExtendedDescription).toHaveTextContent(
"Query summaryAShowing \"Views\"Pageviewcounted by total countwhere event'sBrowser= equals Chromeand person belongs to cohortID 2FiltersEvent'sCurrent URL= equals https://hedgebox.net/files/or event'sCountry Code= equals US or AUBreakdown byCountry CodeSession duration"
)
})

it('can handle change of filters on a retention graph', async () => {
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/lib/components/ActivityLog/complex.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
SELECT
count() AS total,
toStartOfDay(min_timestamp) AS day_start,
breakdown_value AS breakdown_value
FROM
(SELECT
min(timestamp) AS min_timestamp,
argMin(breakdown_value, timestamp) AS breakdown_value
FROM
(SELECT
person_id,
timestamp,
ifNull(nullIf(toString(properties.$browser), ''), '$$_posthog_breakdown_null_$$') AS breakdown_value
FROM
events AS e SAMPLE 1
WHERE
and(equals(event, '$pageview'), lessOrEquals(timestamp, assumeNotNull(toDateTime('2025-01-20 23:59:59'))))
)
GROUP BY
person_id
)
WHERE
greaterOrEquals(min_timestamp, toStartOfDay(assumeNotNull(toDateTime('2020-01-09 00:00:00'))))
GROUP BY
day_start,
breakdown_value
LIMIT 50000
Loading

0 comments on commit a8a5910

Please sign in to comment.