mirror of
https://github.com/goauthentik/authentik
synced 2026-04-26 01:25:02 +02:00
Compare commits
8 Commits
version-20
...
ci/test-po
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b04f13561 | ||
|
|
f14f362180 | ||
|
|
5ae3186030 | ||
|
|
3a9d81f459 | ||
|
|
c0ec5cf63c | ||
|
|
bbfcc9c6ab | ||
|
|
6e802356ce | ||
|
|
6e362212ec |
21
.github/actions/setup/action.yml
vendored
21
.github/actions/setup/action.yml
vendored
@@ -8,6 +8,9 @@ inputs:
|
||||
postgresql_version:
|
||||
description: "Optional postgresql image tag"
|
||||
default: "16"
|
||||
profiles:
|
||||
description: "Extra profiles of supporting services to start"
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -55,21 +58,13 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
export PSQL_TAG=${{ inputs.postgresql_version }}
|
||||
export COMPOSE_PROFILES=${{ inputs.profiles }}
|
||||
docker compose -f .github/actions/setup/docker-compose.yml up -d
|
||||
cd web && npm ci
|
||||
- name: Generate config
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
shell: uv run python {0}
|
||||
shell: bash
|
||||
env:
|
||||
PROFILES: ${{ inputs.profiles }}
|
||||
run: |
|
||||
from authentik.lib.generators import generate_id
|
||||
from yaml import safe_dump
|
||||
|
||||
with open("local.env.yml", "w") as _config:
|
||||
safe_dump(
|
||||
{
|
||||
"log_level": "debug",
|
||||
"secret_key": generate_id(),
|
||||
},
|
||||
_config,
|
||||
default_flow_style=False,
|
||||
)
|
||||
uv run python3 ${{ github.action_path }}/ci_config.py
|
||||
|
||||
18
.github/actions/setup/ci_config.py
vendored
Normal file
18
.github/actions/setup/ci_config.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
from os import getenv
|
||||
from typing import Any
|
||||
|
||||
from yaml import safe_dump
|
||||
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
config: dict[str, Any] = {
|
||||
"log_level": "debug",
|
||||
"secret_key": generate_id(),
|
||||
}
|
||||
|
||||
profiles = getenv("PROFILES")
|
||||
if profiles and "postgres_replica" in profiles:
|
||||
config["postgresql"] = {"read_replicas": {"0": {"host": "localhost", "port": 5433}}}
|
||||
|
||||
with open("local.env.yml", "w") as _config:
|
||||
safe_dump(config, _config, default_flow_style=False)
|
||||
41
.github/actions/setup/docker-compose.yml
vendored
41
.github/actions/setup/docker-compose.yml
vendored
@@ -1,8 +1,17 @@
|
||||
services:
|
||||
postgresql:
|
||||
redis:
|
||||
image: docker.io/library/redis:7
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
|
||||
postgres:
|
||||
image: docker.io/library/postgres:${PSQL_TAG:-16}
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
- ./primary/00-replication.sql:/docker-entrypoint-initdb.d/00-replication.sql
|
||||
- ./primary/01-replication-hba.sh:/docker-entrypoint-initdb.d/01-replication-hba.sh
|
||||
command: postgres -c 'wal_level=replica' -c 'max_wal_senders=10' -c 'max_replication_slots=10' -c 'listen_addresses=*'
|
||||
environment:
|
||||
POSTGRES_USER: authentik
|
||||
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
|
||||
@@ -10,12 +19,34 @@ services:
|
||||
ports:
|
||||
- 5432:5432
|
||||
restart: always
|
||||
redis:
|
||||
image: docker.io/library/redis:7
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
postgres_replica:
|
||||
profiles:
|
||||
- postgres_replica
|
||||
image: docker.io/library/postgres:${PSQL_TAG:-16}
|
||||
environment:
|
||||
POSTGRES_USER: authentik
|
||||
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
|
||||
POSTGRES_DB: authentik
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- db-data-replica:/var/lib/postgresql/data
|
||||
- ./replica:/replica
|
||||
command: /replica/start.sh
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
driver: local
|
||||
db-data-replica:
|
||||
driver: local
|
||||
|
||||
9
.github/actions/setup/primary/00-replication.sql
vendored
Normal file
9
.github/actions/setup/primary/00-replication.sql
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
-- Create replication role if it doesn't exist
|
||||
DO $$ BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'replica') THEN
|
||||
CREATE ROLE replica WITH REPLICATION LOGIN PASSWORD 'EK-5jnKfjrGRm<77';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Create replication slot if it doesn't exist
|
||||
SELECT pg_create_physical_replication_slot('replica_slot', true);
|
||||
3
.github/actions/setup/primary/01-replication-hba.sh
vendored
Executable file
3
.github/actions/setup/primary/01-replication-hba.sh
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
echo "host replication all all scram-sha-256" >> /var/lib/postgresql/data/pg_hba.conf
|
||||
9
.github/actions/setup/replica/start.sh
vendored
Executable file
9
.github/actions/setup/replica/start.sh
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
echo 'Waiting for primary to be ready...'
|
||||
while ! pg_isready -h postgres -p 5432 -U replica; do sleep 1; done;
|
||||
echo 'Primary is ready, starting replica...'
|
||||
rm -rf /var/lib/postgresql/data/* 2>/dev/null || true
|
||||
PGPASSWORD=${POSTGRES_PASSWORD} pg_basebackup -h postgres -U replica -D /var/lib/postgresql/data -Fp -Xs -R -P
|
||||
echo 'Replication setup complete, starting PostgreSQL...'
|
||||
docker-entrypoint.sh postgres
|
||||
8
.github/workflows/ci-main.yml
vendored
8
.github/workflows/ci-main.yml
vendored
@@ -67,7 +67,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
psql:
|
||||
- 15-alpine
|
||||
- 16-alpine
|
||||
- 17-alpine
|
||||
run_id: [1, 2, 3, 4, 5]
|
||||
@@ -114,7 +113,7 @@ jobs:
|
||||
run: |
|
||||
uv run make ci-test
|
||||
test-unittest:
|
||||
name: test-unittest - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5
|
||||
name: test-unittest - PostgreSQL ${{ matrix.psql }} (${{ matrix.profiles }}) - Run ${{ matrix.run_id }}/5
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
needs: test-make-seed
|
||||
@@ -122,9 +121,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
psql:
|
||||
- 15-alpine
|
||||
- 16-alpine
|
||||
- 17-alpine
|
||||
profiles:
|
||||
- ""
|
||||
- postgres_replica
|
||||
run_id: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
@@ -132,6 +133,7 @@ jobs:
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
profiles: ${{ matrix.profiles }}
|
||||
- name: run unittest
|
||||
env:
|
||||
CI_TEST_SEED: ${{ needs.test-make-seed.outputs.seed }}
|
||||
|
||||
@@ -444,6 +444,10 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
|
||||
f"postgresql.read_replicas.{replica}.conn_options", default={}
|
||||
)
|
||||
_database["OPTIONS"].update(replica_conn_options)
|
||||
_database["TEST"] = {
|
||||
"MIRROR": "default",
|
||||
"NAME": config.get("postgresql.test.name"),
|
||||
}
|
||||
|
||||
db[f"replica_{replica}"] = _database
|
||||
return db
|
||||
|
||||
@@ -8,6 +8,7 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase as DjangoTestCase
|
||||
from django.test.runner import DiscoverRunner
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
@@ -20,6 +21,8 @@ from authentik.tasks.test import use_test_broker
|
||||
|
||||
# globally set maxDiff to none to show full assert error
|
||||
TestCase.maxDiff = None
|
||||
# allow testing with read-replicas
|
||||
DjangoTestCase.databases = "__all__"
|
||||
|
||||
|
||||
def get_docker_tag() -> str:
|
||||
@@ -63,6 +66,15 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
settings.TEST = True
|
||||
settings.DRAMATIQ["test"] = True
|
||||
|
||||
# Set any other test databases's name to their test name early
|
||||
# django does this itself, however only _after_ migrating the default alias
|
||||
# which triggers some reads that might go to the read replica, which
|
||||
# would be routed to the wrong database
|
||||
for alias, db in settings.DATABASES.items():
|
||||
if alias == "default":
|
||||
continue
|
||||
db["NAME"] = db["TEST"]["NAME"]
|
||||
|
||||
# Test-specific configuration
|
||||
test_config = {
|
||||
"events.context_processors.geoip": "tests/GeoLite2-City-Test.mmdb",
|
||||
|
||||
Reference in New Issue
Block a user