Skip to content

Commit

Permalink
Merge branch 'master' into experiments/support-person-distinct-ids
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbachhuber committed Dec 17, 2024
2 parents f247b1f + c12b6fd commit c7b33e0
Show file tree
Hide file tree
Showing 269 changed files with 4,586 additions and 15,365 deletions.
170 changes: 155 additions & 15 deletions .github/workflows/ci-hog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,23 @@ jobs:
hog-tests:
needs: changes
timeout-minutes: 30

name: Hog tests
runs-on: ubuntu-24.04
if: needs.changes.outputs.hog == 'true'

steps:
# If this run wasn't initiated by the bot (meaning: snapshot update) and we've determined
# there are backend changes, cancel previous runs
- uses: n1hility/cancel-previous-runs@v3
if: github.actor != 'posthog-bot' && needs.changes.outputs.hog == 'true'
if: github.actor != 'posthog-bot'
with:
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v3
if: needs.changes.outputs.hog == 'true'
with:
fetch-depth: 1

- name: Set up Python
if: needs.changes.outputs.hog == 'true'
uses: actions/setup-python@v5
with:
python-version: 3.11.9
Expand All @@ -76,31 +74,25 @@ jobs:

# uv is a fast pip alternative: https://github.com/astral-sh/uv/
- run: pip install uv
if: needs.changes.outputs.hog == 'true'

- name: Install SAML (python3-saml) dependencies
if: needs.changes.outputs.hog == 'true'
run: |
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1 libxmlsec1-dev libxmlsec1-openssl
- name: Install Python dependencies
if: needs.changes.outputs.hog == 'true'
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Install pnpm
if: needs.changes.outputs.hog == 'true'
uses: pnpm/action-setup@v4

- name: Set up Node.js
if: needs.changes.outputs.hog == 'true'
uses: actions/setup-node@v4
with:
node-version: 18.12.1
node-version: 18

- name: Check if ANTLR definitions are up to date
if: needs.changes.outputs.hog == 'true'
run: |
cd ..
sudo apt-get install default-jre
Expand All @@ -123,27 +115,175 @@ jobs:
ANTLR_VERSION: '4.13.2'

- name: Check if STL bytecode is up to date
if: needs.changes.outputs.hog == 'true'
run: |
python -m hogvm.stl.compile
git diff --exit-code
- name: Run HogVM Python tests
if: needs.changes.outputs.hog == 'true'
run: |
pytest hogvm
- name: Run HogVM TypeScript tests
if: needs.changes.outputs.hog == 'true'
run: |
cd hogvm/typescript
pnpm install --frozen-lockfile
pnpm run test
- name: Run Hog tests
if: needs.changes.outputs.hog == 'true'
run: |
cd hogvm/typescript
pnpm run build
cd ../
./test.sh && git diff --exit-code
check-package-version:
name: Check HogVM TypeScript package version and detect an update
needs: hog-tests
if: needs.hog-tests.result == 'success' && needs.changes.outputs.hog == 'true'
runs-on: ubuntu-24.04
outputs:
committed-version: ${{ steps.check-package-version.outputs.committed-version }}
published-version: ${{ steps.check-package-version.outputs.published-version }}
is-new-version: ${{ steps.check-package-version.outputs.is-new-version }}
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Check package version and detect an update
id: check-package-version
uses: PostHog/check-package-version@v2
with:
path: hogvm/typescript

release-hogvm:
name: Release new HogVM TypeScript version
runs-on: ubuntu-24.04
needs: check-package-version
if: needs.changes.outputs.hog == 'true' && needs.check-package-version.outputs.is-new-version == 'true'
env:
COMMITTED_VERSION: ${{ needs.check-package-version.outputs.committed-version }}
PUBLISHED_VERSION: ${{ needs.check-package-version.outputs.published-version }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
fetch-depth: 1
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
- run: pip install uv
- name: Install SAML (python3-saml) dependencies
run: |
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1 libxmlsec1-dev libxmlsec1-openssl
- name: Install Python dependencies
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Set up Node 18
uses: actions/setup-node@v4
with:
node-version: 18
registry-url: https://registry.npmjs.org
- name: Install package.json dependencies
run: cd hogvm/typescript && pnpm install
- name: Publish the package in the npm registry
run: cd hogvm/typescript && npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Sleep 60 seconds to allow npm to update the package
run: sleep 60

update-versions:
name: Update versions in package.json
runs-on: ubuntu-24.04
needs: release-hogvm
if: always() # This ensures the job runs regardless of the result of release-hogvm
steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
fetch-depth: 1
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Set up Node 18
uses: actions/setup-node@v4
with:
node-version: 18
registry-url: https://registry.npmjs.org

- name: Check for version mismatches
id: check-mismatch
run: |
# Extract committed version
HOGVM_VERSION=$(jq -r '.version' hogvm/typescript/package.json)
# Compare dependencies in package.json
MAIN_VERSION=$(jq -r '.dependencies."@posthog/hogvm"' package.json | tr -d '^')
PLUGIN_VERSION=$(jq -r '.dependencies."@posthog/hogvm"' plugin-server/package.json | tr -d '^')
echo "HOGVM_VERSION=$HOGVM_VERSION"
echo "MAIN_VERSION=$MAIN_VERSION"
echo "PLUGIN_VERSION=$PLUGIN_VERSION"
# Set output if mismatches exist
if [[ "$HOGVM_VERSION" != "$MAIN_VERSION" || "$HOGVM_VERSION" != "$PLUGIN_VERSION" ]]; then
echo "mismatch=true" >> "$GITHUB_ENV"
else
echo "mismatch=false" >> "$GITHUB_ENV"
fi
- name: Update package.json versions
if: env.mismatch == 'true'
run: |
VERSION=$(jq ".version" hogvm/typescript/package.json -r)
retry_pnpm_install() {
local retries=0
local max_retries=20 # 10 minutes total
local delay=30
while [[ $retries -lt $max_retries ]]; do
echo "Attempting pnpm install (retry $((retries+1))/$max_retries)..."
pnpm install --no-frozen-lockfile && break
echo "Install failed. Retrying in $delay seconds..."
sleep $delay
retries=$((retries + 1))
done
if [[ $retries -eq $max_retries ]]; then
echo "pnpm install failed after $max_retries attempts."
exit 1
fi
}
# Update main package.json
mv package.json package.old.json
jq --indent 4 '.dependencies."@posthog/hogvm" = "^'$VERSION'"' package.old.json > package.json
rm package.old.json
retry_pnpm_install
# Update plugin-server/package.json
cd plugin-server
mv package.json package.old.json
jq --indent 4 '.dependencies."@posthog/hogvm" = "^'$VERSION'"' package.old.json > package.json
rm package.old.json
retry_pnpm_install
- name: Commit updated package.json files
if: env.mismatch == 'true'
uses: EndBug/add-and-commit@v9
with:
add: '["package.json", "pnpm-lock.yaml", "plugin-server/package.json", "plugin-server/pnpm-lock.yaml", "hogvm/typescript/package.json"]'
message: 'Update @posthog/hogvm version in package.json'
default_author: github_actions
github_token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
52 changes: 0 additions & 52 deletions .github/workflows/release-hogvm.yml

This file was deleted.

2 changes: 2 additions & 0 deletions cypress/e2e/dashboard.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ describe('Dashboard', () => {
cy.get('[data-attr="date-filter"]').click()
cy.contains('span', 'Last 14 days').click()

cy.wait(2000)

// insight meta should be updated to show new date range
cy.get('h5').contains('Last 14 days').should('exist')

Expand Down
6 changes: 3 additions & 3 deletions cypress/e2e/surveys.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('Surveys', () => {
cy.get('.LemonCollapsePanel').contains('Display conditions').click()
cy.contains('All users').click()
cy.get('.Popover__content').contains('Users who match').click()
cy.contains('Add user targeting').click()
cy.contains('Add property targeting').click()

// select the first property
cy.get('[data-attr="property-select-toggle-0"]').click()
Expand Down Expand Up @@ -144,7 +144,7 @@ describe('Surveys', () => {

// remove user targeting properties
cy.get('.LemonCollapsePanel').contains('Display conditions').click()
cy.contains('Remove all user properties').click()
cy.contains('Remove all property targeting').click()

// save
cy.get('[data-attr="save-survey"]').eq(0).click()
Expand Down Expand Up @@ -197,7 +197,7 @@ describe('Surveys', () => {
cy.get('.LemonCollapsePanel').contains('Display conditions').click()
cy.contains('All users').click()
cy.get('.Popover__content').contains('Users who match').click()
cy.contains('Add user targeting').click()
cy.contains('Add property targeting').click()
cy.get('[data-attr="property-select-toggle-0"]').click()
cy.get('[data-attr="prop-filter-person_properties-0"]').click()
cy.get('[data-attr=prop-val]').click({ force: true })
Expand Down
69 changes: 69 additions & 0 deletions ee/api/conversation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from typing import cast

from django.http import StreamingHttpResponse
from pydantic import ValidationError
from rest_framework import serializers
from rest_framework.renderers import BaseRenderer
from rest_framework.request import Request
from rest_framework.viewsets import GenericViewSet

from ee.hogai.assistant import Assistant
from ee.models.assistant import Conversation
from posthog.api.routing import TeamAndOrgViewSetMixin
from posthog.models.user import User
from posthog.rate_limit import AIBurstRateThrottle, AISustainedRateThrottle
from posthog.schema import HumanMessage


class MessageSerializer(serializers.Serializer):
content = serializers.CharField(required=True, max_length=1000)
conversation = serializers.UUIDField(required=False)

def validate(self, data):
try:
message = HumanMessage(content=data["content"])
data["message"] = message
except ValidationError:
raise serializers.ValidationError("Invalid message content.")
return data


class ServerSentEventRenderer(BaseRenderer):
media_type = "text/event-stream"
format = "txt"

def render(self, data, accepted_media_type=None, renderer_context=None):
return data


class ConversationViewSet(TeamAndOrgViewSetMixin, GenericViewSet):
scope_object = "INTERNAL"
serializer_class = MessageSerializer
renderer_classes = [ServerSentEventRenderer]
queryset = Conversation.objects.all()
lookup_url_kwarg = "conversation"

def safely_get_queryset(self, queryset):
# Only allow access to conversations created by the current user
return queryset.filter(user=self.request.user)

def get_throttles(self):
return [AIBurstRateThrottle(), AISustainedRateThrottle()]

def create(self, request: Request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
conversation_id = serializer.validated_data.get("conversation")
if conversation_id:
self.kwargs[self.lookup_url_kwarg] = conversation_id
conversation = self.get_object()
else:
conversation = self.get_queryset().create(user=request.user, team=self.team)
assistant = Assistant(
self.team,
conversation,
serializer.validated_data["message"],
user=cast(User, request.user),
is_new_conversation=not conversation_id,
)
return StreamingHttpResponse(assistant.stream(), content_type=ServerSentEventRenderer.media_type)
Loading

0 comments on commit c7b33e0

Please sign in to comment.