Skip to content

Commit

Permalink
Merge branch 'master' into ch-24.3
Browse files Browse the repository at this point in the history
* master: (66 commits)
  feat: display line context in stack frames (#26254)
  fix(experiments HogQL): fix funnels filter in prepare_query (#26327)
  fix(hogql): Support parsing dw properties with nested values (#26321)
  fix(err): include raw js frame on frame content in pg (#26326)
  fix: mobile project settings network labels (#26318)
  fix: reduce perms from 3 to 2 for test perf (#26322)
  feat: add new alerts feature for product_analytics (#26320)
  feat(experiments): Enable holdouts for everyone (#26301)
  feat: reorg inspector list rows (#26243)
  feat: Split-up batch exports into sync and async (#26294)
  fix(data-warehouse): Fix custom series colors in chart tooltips (#26310)
  feat(cdp): adjust zapier destination description (#26313)
  fix(insights): prevent race condition (#26265)
  feat(product-assistant): evaluation pipeline (#26179)
  chore: session replay project config for mobile - what is possible (#26289)
  feat(cdp): make hash functions return null if the input is null (#26311)
  feat(err): cymbal for all teams (#26312)
  feat(hogql): Allow breakdowns for lazy-joined tables (#26302)
  feat: create events table to store last 7 days of data (#26239)
  chore: Bump batch exports start jitter (#26278)
  ...
  • Loading branch information
fuziontech committed Nov 21, 2024
2 parents 7b59b2d + fb17df2 commit c2176eb
Show file tree
Hide file tree
Showing 491 changed files with 20,558 additions and 4,716 deletions.
23 changes: 22 additions & 1 deletion .github/workflows/container-images-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:
run: |
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$|^requirements.txt$' && echo true) || echo false)" >> $GITHUB_OUTPUT
- name: Trigger Batch Exports Temporal Worker Cloud deployment
- name: Trigger Batch Exports Sync Temporal Worker Cloud deployment
if: steps.check_changes_batch_exports_temporal_worker.outputs.changed == 'true'
uses: peter-evans/repository-dispatch@v3
with:
Expand All @@ -155,6 +155,27 @@ jobs:
"timestamp": "${{ github.event.head_commit.timestamp }}"
}
- name: Trigger Batch Exports Temporal Worker Cloud deployment
if: steps.check_changes_batch_exports_temporal_worker.outputs.changed == 'true'
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ steps.deployer.outputs.token }}
repository: PostHog/charts
event-type: commit_state_update
client-payload: |
{
"values": {
"image": {
"sha": "${{ steps.build.outputs.digest }}"
}
},
"release": "temporal-worker-batch-exports",
"commit": ${{ toJson(github.event.head_commit) }},
"repository": ${{ toJson(github.repository) }},
"labels": ${{ steps.labels.outputs.labels }},
"timestamp": "${{ github.event.head_commit.timestamp }}"
}
- name: Check for changes that affect general purpose temporal worker
id: check_changes_general_purpose_temporal_worker
run: |
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,10 @@ plugin-transpiler/dist
*.log
# pyright config (keep this until we have a standardized one)
pyrightconfig.json
.temporal-worker-settings
# Assistant Evaluation with Deepeval
.deepeval
.deepeval-cache.json
.deepeval_telemtry.txt
.temporal-worker-settings
temp_test_run_data.json
.temp-deepeval-cache.json
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"env": {
"SKIP_ASYNC_MIGRATIONS_SETUP": "0",
"SKIP_ASYNC_MIGRATIONS_SETUP": "1",
"DEBUG": "1",
"BILLING_SERVICE_URL": "https://billing.dev.posthog.dev",
"SKIP_SERVICE_VERSION_REQUIREMENTS": "1"
Expand Down
3 changes: 3 additions & 0 deletions bin/hoge
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ set -e

if [[ "$@" == *".hog"* ]]; then
exec python3 -m posthog.hogql.cli --compile "$@"
elif [[ "$@" == *".js"* ]]; then
exec python3 -m posthog.hogql.cli --compile "$@"
else
echo "$0 - the Hog compilër! 🦔+🕶️= Hoge"
echo ""
echo "Usage: bin/hoge <file.hog> [output.hoge] compile .hog into .hoge"
echo " bin/hoge <file.hog> <output.js> compile .hog into .js"
echo " bin/hog <file.hog> run .hog source code"
echo " bin/hog <file.hoge> run compiled .hoge bytecode"
exit 1
Expand Down
2 changes: 0 additions & 2 deletions cypress/e2e/experiments.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ describe('Experiments', () => {
// Wait for the goal modal to open and click the confirmation button
cy.get('.LemonModal__layout').should('be.visible')
cy.contains('Change experiment goal').should('be.visible')
cy.get('.LemonModal__footer').contains('button', 'Save').should('have.attr', 'aria-disabled', 'true')
cy.get('.LemonModal__content').contains('button', 'Add funnel step').click()
cy.get('.LemonModal__footer').contains('button', 'Save').should('not.have.attr', 'aria-disabled', 'true')
cy.get('.LemonModal__footer').contains('button', 'Save').click()
}

Expand Down
20 changes: 16 additions & 4 deletions cypress/e2e/featureFlags.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ describe('Feature Flags', () => {
})

it('Display product introduction when no feature flags exist', () => {
// ensure unique names to avoid clashes
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
cy.get('[data-attr=new-feature-flag]').click()
cy.contains('Create your first feature flag').should('exist')
cy.contains('Welcome to Feature flags!').should('exist')
})

it('Create feature flag', () => {
Expand Down Expand Up @@ -104,6 +102,7 @@ describe('Feature Flags', () => {
cy.get('[data-attr=feature-flag-key]').focus().type(name).should('have.value', name)
cy.get('[data-attr=rollout-percentage]').type('{selectall}50').should('have.value', '50')
cy.get('[data-attr=save-feature-flag]').first().click()
cy.get('[data-attr=toast-close-button]').click()

// after save there should be a delete button
cy.get('[data-attr="more-button"]').click()
Expand Down Expand Up @@ -308,7 +307,8 @@ describe('Feature Flags', () => {
cy.get('.operator-value-option').contains('> after').should('not.exist')
})

it('Allow setting multivariant rollout percentage to zero', () => {
it('Allows setting multivariant rollout percentage to zero', () => {
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
// Start creating a multivariant flag
cy.get('[data-attr=new-feature-flag]').click()
cy.get('[data-attr=feature-flag-served-value-segmented-button]')
Expand All @@ -328,6 +328,18 @@ describe('Feature Flags', () => {
cy.get('[data-attr=feature-flag-variant-rollout-percentage-input]').click().type(`4.5`).should('have.value', 4)
})

it('Sets URL properly when switching between tabs', () => {
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
cy.get('[data-attr=feature-flags-tab-navigation]').contains('History').click()
cy.url().should('include', `tab=history`)

cy.get('[data-attr=feature-flags-tab-navigation]').contains('Overview').click()
cy.url().should('include', `tab=overview`)

cy.get('[data-attr=feature-flags-tab-navigation]').contains('History').click()
cy.url().should('include', `tab=history`)
})

it('Renders flags in FlagSelector', () => {
// Create flag name
cy.get('[data-attr=top-bar-name]').should('contain', 'Feature flags')
Expand Down
3 changes: 2 additions & 1 deletion cypress/e2e/surveys.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,15 @@ describe('Surveys', () => {

// Set responses limit
cy.get('.LemonCollapsePanel').contains('Completion conditions').click()
cy.get('[data-attr=survey-collection-until-limit]').first().click()
cy.get('[data-attr=survey-responses-limit-input]').focus().type('228').click()

// Save the survey
cy.get('[data-attr=save-survey]').first().click()
cy.get('button[data-attr="launch-survey"]').should('have.text', 'Launch')

cy.reload()
cy.contains('The survey will be stopped once 228 responses are received.').should('be.visible')
cy.contains('The survey will be stopped once 100228 responses are received.').should('be.visible')
})

it('creates a new survey with branching logic', () => {
Expand Down
2 changes: 1 addition & 1 deletion ee/clickhouse/models/test/test_action.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dataclasses

from posthog.client import sync_execute
from posthog.hogql.bytecode import create_bytecode
from posthog.hogql.compiler.bytecode import create_bytecode
from posthog.hogql.hogql import HogQLContext
from posthog.hogql.property import action_to_expr
from posthog.models.action import Action
Expand Down
64 changes: 16 additions & 48 deletions ee/clickhouse/views/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
from posthog.constants import INSIGHT_TRENDS
from posthog.models.experiment import Experiment, ExperimentHoldout, ExperimentSavedMetric
from posthog.models.filters.filter import Filter
from posthog.schema import ExperimentFunnelsQuery, ExperimentTrendsQuery
from posthog.utils import generate_cache_key, get_safe_cache

EXPERIMENT_RESULTS_CACHE_DEFAULT_TTL = 60 * 60 # 1 hour
Expand Down Expand Up @@ -194,6 +193,7 @@ class Meta:
"updated_at",
"type",
"metrics",
"metrics_secondary",
]
read_only_fields = [
"id",
Expand Down Expand Up @@ -235,36 +235,7 @@ def validate_saved_metrics_ids(self, value):
return value

def validate_metrics(self, value):
# TODO: This isn't correct most probably, we wouldn't have experiment_id inside ExperimentTrendsQuery
# on creation. Not sure how this is supposed to work yet.
if not value:
return value

if not isinstance(value, list):
raise ValidationError("Metrics must be a list")

if len(value) > 10:
raise ValidationError("Experiments can have a maximum of 10 metrics")

for metric in value:
if not isinstance(metric, dict):
raise ValidationError("Metrics must be objects")
if not metric.get("query"):
raise ValidationError("Metric query is required")

if metric.get("type") not in ["primary", "secondary"]:
raise ValidationError("Metric type must be 'primary' or 'secondary'")

metric_query = metric["query"]

if metric_query.get("kind") not in ["ExperimentTrendsQuery", "ExperimentFunnelsQuery"]:
raise ValidationError("Metric query kind must be 'ExperimentTrendsQuery' or 'ExperimentFunnelsQuery'")

# pydantic models are used to validate the query
if metric_query["kind"] == "ExperimentTrendsQuery":
ExperimentTrendsQuery(**metric_query)
else:
ExperimentFunnelsQuery(**metric_query)
# TODO 2024-11-15: commented code will be addressed when persistent metrics are implemented.

return value

Expand All @@ -285,8 +256,8 @@ def validate_parameters(self, value):
def create(self, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:
is_draft = "start_date" not in validated_data or validated_data["start_date"] is None

if not validated_data.get("filters") and not is_draft:
raise ValidationError("Filters are required when creating a launched experiment")
# if not validated_data.get("filters") and not is_draft:
# raise ValidationError("Filters are required when creating a launched experiment")

saved_metrics_data = validated_data.pop("saved_metrics_ids", [])

Expand All @@ -301,11 +272,6 @@ def create(self, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:

feature_flag_key = validated_data.pop("get_feature_flag_key")

properties = validated_data["filters"].get("properties", [])

if properties:
raise ValidationError("Experiments do not support global filter properties")

holdout_groups = None
if validated_data.get("holdout"):
holdout_groups = validated_data["holdout"].filters
Expand All @@ -315,8 +281,8 @@ def create(self, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:
{"key": "test", "name": "Test Variant", "rollout_percentage": 50},
]

filters = {
"groups": [{"properties": properties, "rollout_percentage": 100}],
feature_flag_filters = {
"groups": [{"properties": [], "rollout_percentage": 100}],
"multivariate": {"variants": variants or default_variants},
"aggregation_group_type_index": aggregation_group_type_index,
"holdout_groups": holdout_groups,
Expand All @@ -326,7 +292,7 @@ def create(self, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:
data={
"key": feature_flag_key,
"name": f'Feature Flag for Experiment {validated_data["name"]}',
"filters": filters,
"filters": feature_flag_filters,
"active": not is_draft,
"creation_context": "experiments",
},
Expand Down Expand Up @@ -370,13 +336,13 @@ def create(self, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:
return experiment

def update(self, instance: Experiment, validated_data: dict, *args: Any, **kwargs: Any) -> Experiment:
if (
not instance.filters.get("events")
and not instance.filters.get("actions")
and validated_data.get("start_date")
and not validated_data.get("filters")
):
raise ValidationError("Filters are required when launching an experiment")
# if (
# not instance.filters.get("events")
# and not instance.filters.get("actions")
# and validated_data.get("start_date")
# and not validated_data.get("filters")
# ):
# raise ValidationError("Filters are required when launching an experiment")

update_saved_metrics = "saved_metrics_ids" in validated_data
saved_metrics_data = validated_data.pop("saved_metrics_ids", []) or []
Expand Down Expand Up @@ -409,6 +375,8 @@ def update(self, instance: Experiment, validated_data: dict, *args: Any, **kwarg
"archived",
"secondary_metrics",
"holdout",
"metrics",
"metrics_secondary",
}
given_keys = set(validated_data.keys())
extra_keys = given_keys - expected_keys
Expand Down
Loading

0 comments on commit c2176eb

Please sign in to comment.