0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-24 09:14:46 +01:00
posthog/.github/workflows/ci-backend.yml
Michael Matloka 84db60babb
ci: Split Temporal backend suite into three (#25880)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-30 16:15:46 +00:00

420 lines
19 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# This workflow runs all of our backend django tests.
#
# If these tests get too slow, look at increasing concurrency and re-timing the tests by manually dispatching
# .github/workflows/ci-backend-update-test-timing.yml action
name: Backend CI
on:
push:
branches:
- master
workflow_dispatch:
inputs:
clickhouseServerVersion:
description: ClickHouse server version. Leave blank for default
type: string
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
# This is so that the workflow run isn't canceled when a snapshot update is pushed within it by posthog-bot
# We do however cancel from container-images-ci.yml if a commit is pushed by someone OTHER than posthog-bot
cancel-in-progress: false
env:
SECRET_KEY: '6b01eee4f945ca25045b5aab440b953461faf08693a9abbf1166dc7c6b9772da' # unsafe - for testing only
DATABASE_URL: 'postgres://posthog:posthog@localhost:5432/posthog'
REDIS_URL: 'redis://localhost'
CLICKHOUSE_HOST: 'localhost'
CLICKHOUSE_SECURE: 'False'
CLICKHOUSE_VERIFY: 'False'
TEST: 1
CLICKHOUSE_SERVER_IMAGE_VERSION: ${{ github.event.inputs.clickhouseServerVersion || '' }}
OBJECT_STORAGE_ENABLED: 'True'
OBJECT_STORAGE_ENDPOINT: 'http://localhost:19000'
OBJECT_STORAGE_ACCESS_KEY_ID: 'object_storage_root_user'
OBJECT_STORAGE_SECRET_ACCESS_KEY: 'object_storage_root_password'
# tests would intermittently fail in GH actions
# with exit code 134 _after passing_ all tests
# this appears to fix it
# absolute wild tbh https://stackoverflow.com/a/75503402
DISPLAY: ':99.0'
jobs:
# Job to decide if we should run backend ci
# See https://github.com/dorny/paths-filter#conditional-execution for more details
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
name: Determine need to run backend checks
# Set job outputs to values from filter step
outputs:
backend: ${{ steps.filter.outputs.backend }}
steps:
# For pull requests it's not necessary to checkout the code, but we
# also want this to run on master so we need to checkout
- uses: actions/checkout@v3
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
backend:
# Avoid running backend tests for irrelevant changes
# NOTE: we are at risk of missing a dependency here. We could make
# the dependencies more clear if we separated the backend/frontend
# code completely
# really we should ignore ee/frontend/** but dorny doesn't support that
# - '!ee/frontend/**'
# including the negated rule appears to work
# but makes it always match because the checked file always isn't `ee/frontend/**` 🙈
- 'ee/**/*'
- 'hogvm/**/*'
- 'posthog/**/*'
- 'bin/*.py'
- requirements.txt
- requirements-dev.txt
- mypy.ini
- pytest.ini
- frontend/src/queries/schema.json # Used for generating schema.py
- plugin-transpiler/src # Used for transpiling plugins
# Make sure we run if someone is explicitly change the workflow
- .github/workflows/ci-backend.yml
- .github/actions/run-backend-tests/action.yml
# We use docker compose for tests, make sure we rerun on
# changes to docker-compose.dev.yml e.g. dependency
# version changes
- docker-compose.dev.yml
- frontend/public/email/*
# These scripts are used in the CI
- bin/check_temporal_up
- bin/check_kafka_clickhouse_up
backend-code-quality:
needs: changes
timeout-minutes: 30
name: Python code quality checks
runs-on: ubuntu-latest
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.backend == 'true'
with:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v3
with:
fetch-depth: 1
- 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 }}
# uv is a fast pip alternative: https://github.com/astral-sh/uv/
- 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: Check for syntax errors, import sort, and code style violations
run: |
ruff check .
- name: Check formatting
run: |
ruff format --check --diff .
- name: Add Problem Matcher
run: echo "::add-matcher::.github/mypy-problem-matcher.json"
- name: Check static typing
run: |
mypy -p posthog | mypy-baseline filter
- name: Check if "schema.py" is up to date
run: |
npm run schema:build:python && git diff --exit-code
check-migrations:
needs: changes
if: needs.changes.outputs.backend == 'true'
timeout-minutes: 10
name: Validate Django and CH migrations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Stop/Start stack with Docker Compose
run: |
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml up -d
- 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 }}
# uv is a fast pip alternative: https://github.com/astral-sh/uv/
- run: pip install uv
- name: Install SAML (python3-saml) dependencies
run: |
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
# First running migrations from master, to simulate the real-world scenario
- name: Checkout master
uses: actions/checkout@v3
with:
ref: master
- name: Install python dependencies for master
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Run migrations up to master
run: |
python manage.py migrate
# Now we can consider this PR's migrations
- name: Checkout this PR
uses: actions/checkout@v3
- name: Install python dependencies for this PR
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Run migrations for this PR
run: |
python manage.py migrate
- name: Check migrations
run: |
python manage.py makemigrations --check --dry-run
git fetch origin master
# `git diff --name-only` returns a list of files that were changed - added OR deleted OR modified
# With `--name-status` we get the same, but including a column for status, respectively: A, D, M
# In this check we exclusively care about files that were
# added (A) in posthog/migrations/. We also want to ignore
# initial migrations (0001_*) as these are guaranteed to be
# run on initial setup where there is no data.
git diff --name-status origin/master..HEAD | grep "A\sposthog/migrations/" | awk '{print $2}' | grep -v migrations/0001_ | python manage.py test_migrations_are_safe
- name: Check CH migrations
run: |
# Same as above, except now for CH looking at files that were added in posthog/clickhouse/migrations/
git diff --name-status origin/master..HEAD | grep "A\sposthog/clickhouse/migrations/" | awk '{print $2}' | python manage.py test_ch_migrations_are_safe
django:
needs: changes
# increase for tmate testing
timeout-minutes: 30
name: Django tests ${{ matrix.segment }} (persons-on-events ${{ matrix.person-on-events && 'on' || 'off' }}), Py ${{ matrix.python-version }}, ${{ matrix.clickhouse-server-image }} (${{matrix.group}}/${{ matrix.concurrency }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.11.9']
clickhouse-server-image: ['clickhouse/clickhouse-server:23.12.6.19']
segment: ['Core']
person-on-events: [false, true]
# :NOTE: Keep concurrency and groups in sync
concurrency: [10]
group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
include:
- segment: 'Temporal'
person-on-events: false
clickhouse-server-image: 'clickhouse/clickhouse-server:23.12.6.19'
python-version: '3.11.9'
concurrency: 3
group: 1
- segment: 'Temporal'
person-on-events: false
clickhouse-server-image: 'clickhouse/clickhouse-server:23.12.6.19'
python-version: '3.11.9'
concurrency: 3
group: 2
- segment: 'Temporal'
person-on-events: false
clickhouse-server-image: 'clickhouse/clickhouse-server:23.12.6.19'
python-version: '3.11.9'
concurrency: 3
group: 3
steps:
# The first step is the only one that should run if `needs.changes.outputs.backend == 'false'`.
# All the other ones should rely on `needs.changes.outputs.backend` directly or indirectly, so that they're
# effectively skipped if backend code is unchanged. See https://github.com/PostHog/posthog/pull/15174.
- uses: actions/checkout@v3
with:
fetch-depth: 1
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
# Use PostHog Bot token when not on forks to enable proper snapshot updating
token: ${{ github.event.pull_request.head.repo.full_name == github.repository && secrets.POSTHOG_BOT_GITHUB_TOKEN || github.token }}
- uses: ./.github/actions/run-backend-tests
if: needs.changes.outputs.backend == 'true'
with:
segment: ${{ matrix.segment }}
person-on-events: ${{ matrix.person-on-events }}
python-version: ${{ matrix.python-version }}
clickhouse-server-image: ${{ matrix.clickhouse-server-image }}
concurrency: ${{ matrix.concurrency }}
group: ${{ matrix.group }}
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
- uses: EndBug/add-and-commit@v9
# Skip on forks
# Also skip for persons-on-events runs, as we want to ignore snapshots diverging there
if: ${{ github.event.pull_request.head.repo.full_name == 'PostHog/posthog' && needs.changes.outputs.backend == 'true' && !matrix.person-on-events }}
with:
add: '["ee", "./**/*.ambr", "posthog/queries/", "posthog/migrations", "posthog/tasks", "posthog/hogql/"]'
message: 'Update query snapshots'
pull: --rebase --autostash # Make sure we're up-to-date with other segments' updates
default_author: github_actions
github_token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
- name: Check if any snapshot changes were left uncomitted
id: changed-files
if: ${{ github.event.pull_request.head.repo.full_name == 'PostHog/posthog' && needs.changes.outputs.backend == 'true' && !matrix.person-on-events }}
run: |
if [[ -z $(git status -s | grep -v ".test_durations" | tr -d "\n") ]]
then
echo 'files_found=false' >> $GITHUB_OUTPUT
else
echo 'diff=$(git status --porcelain)' >> $GITHUB_OUTPUT
echo 'files_found=true' >> $GITHUB_OUTPUT
fi
- name: Fail CI if some snapshots have been updated but not committed
if: steps.changed-files.outputs.files_found == 'true' && steps.add-and-commit.outcome == 'success'
run: |
echo "${{ steps.changed-files.outputs.diff }}"
exit 1
- name: Archive email renders
uses: actions/upload-artifact@v3
if: needs.changes.outputs.backend == 'true' && matrix.segment == 'Core' && matrix.person-on-events == false
with:
name: email_renders
path: posthog/tasks/test/__emails__
retention-days: 5
async-migrations:
name: Async migrations tests - ${{ matrix.clickhouse-server-image }}
needs: changes
strategy:
fail-fast: false
matrix:
clickhouse-server-image: ['clickhouse/clickhouse-server:23.12.6.19']
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
steps:
- name: 'Checkout repo'
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Start stack with Docker Compose
run: |
export CLICKHOUSE_SERVER_IMAGE_VERSION=${{ matrix.clickhouse-server-image }}
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml up -d
- 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 }}
# uv is a fast pip alternative: https://github.com/astral-sh/uv/
- run: pip install uv
- name: Install SAML (python3-saml) dependencies
run: |
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
- name: Install python dependencies
shell: bash
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Add kafka host to /etc/hosts for kafka connectivity
run: sudo echo "127.0.0.1 kafka" | sudo tee -a /etc/hosts
- name: Set up needed files
run: |
mkdir -p frontend/dist
touch frontend/dist/index.html
touch frontend/dist/layout.html
touch frontend/dist/exporter.html
- name: Wait for Clickhouse & Kafka
run: bin/check_kafka_clickhouse_up
- name: Run async migrations tests
run: |
pytest -m "async_migrations"
calculate-running-time:
name: Calculate running time
needs: [django, async-migrations]
runs-on: ubuntu-latest
if: # Run on pull requests to PostHog/posthog + on PostHog/posthog outside of PRs - but never on forks
needs.changes.outputs.backend == 'true' &&
(
github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository
) == 'PostHog/posthog'
steps:
- name: Calculate running time
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
run_id=${GITHUB_RUN_ID}
repo=${GITHUB_REPOSITORY}
run_info=$(gh api repos/${repo}/actions/runs/${run_id})
echo run_info: ${run_info}
# name is the name of the workflow file
# run_started_at is the start time of the workflow
# we want to get the number of seconds between the start time and now
name=$(echo ${run_info} | jq -r '.name')
run_url=$(echo ${run_info} | jq -r '.url')
run_started_at=$(echo ${run_info} | jq -r '.run_started_at')
run_attempt=$(echo ${run_info} | jq -r '.run_attempt')
start_seconds=$(date -d "${run_started_at}" +%s)
now_seconds=$(date +%s)
duration=$((now_seconds-start_seconds))
echo running_time_duration_seconds=${duration} >> $GITHUB_ENV
echo running_time_run_url=${run_url} >> $GITHUB_ENV
echo running_time_run_attempt=${run_attempt} >> $GITHUB_ENV
echo running_time_run_id=${run_id} >> $GITHUB_ENV
echo running_time_run_started_at=${run_started_at} >> $GITHUB_ENV
- name: Capture running time to PostHog
uses: PostHog/posthog-github-action@v0.1
with:
posthog-token: ${{secrets.POSTHOG_API_TOKEN}}
event: 'posthog-ci-running-time'
properties: '{"duration_seconds": ${{ env.running_time_duration_seconds }}, "run_url": "${{ env.running_time_run_url }}", "run_attempt": "${{ env.running_time_run_attempt }}", "run_id": "${{ env.running_time_run_id }}", "run_started_at": "${{ env.running_time_run_started_at }}"}'