mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
root: Better version bump (#14905)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
[bumpversion]
|
||||
current_version = 2025.6.4
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||
serialize =
|
||||
{major}.{minor}.{patch}-{rc_t}{rc_n}
|
||||
{major}.{minor}.{patch}
|
||||
message = release: {new_version}
|
||||
tag_name = version/{new_version}
|
||||
|
||||
[bumpversion:part:rc_t]
|
||||
values =
|
||||
rc
|
||||
final
|
||||
optional_value = final
|
||||
|
||||
[bumpversion:file:pyproject.toml]
|
||||
|
||||
[bumpversion:file:uv.lock]
|
||||
|
||||
[bumpversion:file:package.json]
|
||||
|
||||
[bumpversion:file:package-lock.json]
|
||||
|
||||
[bumpversion:file:docker-compose.yml]
|
||||
|
||||
[bumpversion:file:schema.yml]
|
||||
|
||||
[bumpversion:file:blueprints/schema.json]
|
||||
|
||||
[bumpversion:file:authentik/__init__.py]
|
||||
|
||||
[bumpversion:file:internal/constants/constants.go]
|
||||
|
||||
[bumpversion:file:lifecycle/aws/template.yaml]
|
||||
@@ -1,5 +1,6 @@
|
||||
htmlcov
|
||||
*.env.yml
|
||||
node_modules
|
||||
**/node_modules
|
||||
dist/**
|
||||
build/**
|
||||
|
||||
@@ -54,6 +54,10 @@ outputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
dependencies: "python"
|
||||
- name: Generate config
|
||||
id: ev
|
||||
shell: bash
|
||||
@@ -64,4 +68,4 @@ runs:
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
REF: ${{ github.ref }}
|
||||
run: |
|
||||
python3 ${{ github.action_path }}/push_vars.py
|
||||
uv run python3 ${{ github.action_path }}/push_vars.py
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
"""Helper script to get the actual branch name, docker safe"""
|
||||
|
||||
import configparser
|
||||
import os
|
||||
from importlib.metadata import version as package_version
|
||||
from json import dumps
|
||||
from time import time
|
||||
|
||||
parser = configparser.ConfigParser()
|
||||
parser.read(".bumpversion.cfg")
|
||||
|
||||
# Decide if we should push the image or not
|
||||
should_push = True
|
||||
if len(os.environ.get("DOCKER_USERNAME", "")) < 1:
|
||||
@@ -31,7 +28,7 @@ is_release = "dev" not in image_names[0]
|
||||
sha = os.environ["GITHUB_SHA"] if not is_pull_request else os.getenv("PR_HEAD_SHA")
|
||||
|
||||
# 2042.1.0 or 2042.1.0-rc1
|
||||
version = parser.get("bumpversion", "current_version")
|
||||
version = package_version("authentik")
|
||||
# 2042.1
|
||||
version_family = ".".join(version.split("-", 1)[0].split(".")[:-1])
|
||||
prerelease = "-" in version
|
||||
|
||||
12
.github/actions/setup/action.yml
vendored
12
.github/actions/setup/action.yml
vendored
@@ -2,6 +2,9 @@ name: "Setup authentik testing environment"
|
||||
description: "Setup authentik testing environment"
|
||||
|
||||
inputs:
|
||||
dependencies:
|
||||
description: "List of dependencies to setup"
|
||||
default: "system,python,node,go,runtime"
|
||||
postgresql_version:
|
||||
description: "Optional postgresql image tag"
|
||||
default: "16"
|
||||
@@ -10,42 +13,51 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install apt deps
|
||||
if: ${{ contains(inputs.dependencies, 'system') || contains(inputs.dependencies, 'python') }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext libkrb5-dev krb5-kdc krb5-user krb5-admin-server
|
||||
- name: Install uv
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Setup python
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: "pyproject.toml"
|
||||
- name: Install Python deps
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
shell: bash
|
||||
run: uv sync --all-extras --dev --frozen
|
||||
- name: Setup node
|
||||
if: ${{ contains(inputs.dependencies, 'node') }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- name: Setup go
|
||||
if: ${{ contains(inputs.dependencies, 'go') }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Setup docker cache
|
||||
if: ${{ contains(inputs.dependencies, 'runtime') }}
|
||||
uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7
|
||||
with:
|
||||
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/docker-compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
|
||||
- name: Setup dependencies
|
||||
if: ${{ contains(inputs.dependencies, 'runtime') }}
|
||||
shell: bash
|
||||
run: |
|
||||
export PSQL_TAG=${{ inputs.postgresql_version }}
|
||||
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}
|
||||
run: |
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
20
Makefile
20
Makefile
@@ -16,6 +16,7 @@ GEN_API_GO = gen-go-api
|
||||
pg_user := $(shell uv run python -m authentik.lib.config postgresql.user 2>/dev/null)
|
||||
pg_host := $(shell uv run python -m authentik.lib.config postgresql.host 2>/dev/null)
|
||||
pg_name := $(shell uv run python -m authentik.lib.config postgresql.name 2>/dev/null)
|
||||
redis_db := $(shell uv run python -m authentik.lib.config redis.db 2>/dev/null)
|
||||
|
||||
all: lint-fix lint test gen web ## Lint, build, and test everything
|
||||
|
||||
@@ -57,7 +58,7 @@ migrate: ## Run the Authentik Django server's migrations
|
||||
i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service
|
||||
|
||||
aws-cfn:
|
||||
cd lifecycle/aws && npm run aws-cfn
|
||||
cd lifecycle/aws && npm i && npm run aws-cfn
|
||||
|
||||
run-server: ## Run the main authentik server process
|
||||
uv run ak server
|
||||
@@ -79,10 +80,10 @@ core-i18n-extract:
|
||||
install: node-install docs-install core-install ## Install all requires dependencies for `node`, `docs` and `core`
|
||||
|
||||
dev-drop-db:
|
||||
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
|
||||
dropdb -U ${pg_user} -h ${pg_host} ${pg_name} || true
|
||||
# Also remove the test-db if it exists
|
||||
dropdb -U ${pg_user} -h ${pg_host} test_${pg_name} || true
|
||||
redis-cli -n 0 flushall
|
||||
redis-cli -n ${redis_db} flushall
|
||||
|
||||
dev-create-db:
|
||||
createdb -U ${pg_user} -h ${pg_host} ${pg_name}
|
||||
@@ -93,6 +94,16 @@ update-test-mmdb: ## Update test GeoIP and ASN Databases
|
||||
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-ASN-Test.mmdb -o ${PWD}/tests/GeoLite2-ASN-Test.mmdb
|
||||
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-City-Test.mmdb -o ${PWD}/tests/GeoLite2-City-Test.mmdb
|
||||
|
||||
bump: ## Bump authentik version. Usage: make bump version=20xx.xx.xx
|
||||
ifndef version
|
||||
$(error Usage: make bump version=20xx.xx.xx )
|
||||
endif
|
||||
uv version $(version)
|
||||
$(MAKE) gen-build gen-compose aws-cfn
|
||||
npm version --no-git-tag-version --allow-same-version $(version)
|
||||
cd ${PWD}/web && npm version --no-git-tag-version --allow-same-version $(version)
|
||||
echo -n $(version) > ${PWD}/internal/constants/VERSION
|
||||
|
||||
#########################
|
||||
## API Schema
|
||||
#########################
|
||||
@@ -107,6 +118,9 @@ gen-build: ## Extract the schema from the database
|
||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||
uv run ak spectacular --file schema.yml
|
||||
|
||||
gen-compose:
|
||||
uv run scripts/generate_docker_compose.py
|
||||
|
||||
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
|
||||
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
|
||||
npx prettier --write changelog.md
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
"""authentik root module"""
|
||||
|
||||
from functools import lru_cache
|
||||
from importlib.metadata import version
|
||||
from os import environ
|
||||
|
||||
__version__ = "2025.6.4"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
def get_build_hash(fallback: str | None = None) -> str:
|
||||
@lru_cache
|
||||
def authentik_version() -> str:
|
||||
return version("authentik")
|
||||
|
||||
|
||||
@lru_cache
|
||||
def authentik_build_hash(fallback: str | None = None) -> str:
|
||||
"""Get build hash"""
|
||||
build_hash = environ.get(ENV_GIT_HASH_KEY, fallback if fallback else "")
|
||||
return fallback if build_hash == "" and fallback else build_hash
|
||||
|
||||
|
||||
def get_full_version() -> str:
|
||||
@lru_cache
|
||||
def authentik_full_version() -> str:
|
||||
"""Get full version, with build hash appended"""
|
||||
version = __version__
|
||||
if (build_hash := get_build_hash()) != "":
|
||||
version = authentik_version()
|
||||
if (build_hash := authentik_build_hash()) != "":
|
||||
return f"{version}+{build_hash}"
|
||||
return version
|
||||
|
||||
@@ -16,7 +16,7 @@ from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
from authentik.lib.config import CONFIG
|
||||
@@ -78,7 +78,7 @@ class SystemInfoSerializer(PassiveSerializer):
|
||||
"""Get versions"""
|
||||
return {
|
||||
"architecture": platform.machine(),
|
||||
"authentik_version": get_full_version(),
|
||||
"authentik_version": authentik_full_version(),
|
||||
"environment": get_env(),
|
||||
"openssl_fips_enabled": (
|
||||
backend._fips_enabled if LicenseKey.get_total().status().is_valid else None
|
||||
|
||||
@@ -10,7 +10,7 @@ from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_build_hash, authentik_version
|
||||
from authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.outposts.models import Outpost
|
||||
@@ -29,20 +29,20 @@ class VersionSerializer(PassiveSerializer):
|
||||
|
||||
def get_build_hash(self, _) -> str:
|
||||
"""Get build hash, if version is not latest or released"""
|
||||
return get_build_hash()
|
||||
return authentik_build_hash()
|
||||
|
||||
def get_version_current(self, _) -> str:
|
||||
"""Get current version"""
|
||||
return __version__
|
||||
return authentik_version()
|
||||
|
||||
def get_version_latest(self, _) -> str:
|
||||
"""Get latest version from cache"""
|
||||
if get_current_tenant().schema_name == get_public_schema_name():
|
||||
return __version__
|
||||
return authentik_version()
|
||||
version_in_cache = cache.get(VERSION_CACHE_KEY)
|
||||
if not version_in_cache: # pragma: no cover
|
||||
update_latest_version.send()
|
||||
return __version__
|
||||
return authentik_version()
|
||||
return version_in_cache
|
||||
|
||||
def get_version_latest_valid(self, _) -> bool:
|
||||
|
||||
@@ -8,7 +8,7 @@ from packaging.version import parse
|
||||
from requests import RequestException
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_build_hash, authentik_version
|
||||
from authentik.admin.apps import PROM_INFO
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.config import CONFIG
|
||||
@@ -19,16 +19,16 @@ LOGGER = get_logger()
|
||||
VERSION_NULL = "0.0.0"
|
||||
VERSION_CACHE_KEY = "authentik_latest_version"
|
||||
VERSION_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours
|
||||
LOCAL_VERSION = parse(__version__)
|
||||
LOCAL_VERSION = parse(authentik_version())
|
||||
|
||||
|
||||
def _set_prom_info():
|
||||
"""Set prometheus info for version"""
|
||||
PROM_INFO.info(
|
||||
{
|
||||
"version": __version__,
|
||||
"version": authentik_version(),
|
||||
"latest": cache.get(VERSION_CACHE_KEY, ""),
|
||||
"build_hash": get_build_hash(),
|
||||
"build_hash": authentik_build_hash(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from json import loads
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.blueprints.tests import reconcile_app
|
||||
from authentik.core.models import Group, User
|
||||
from authentik.lib.generators import generate_id
|
||||
@@ -27,7 +27,7 @@ class TestAdminAPI(TestCase):
|
||||
response = self.client.get(reverse("authentik_api:admin_version"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
body = loads(response.content)
|
||||
self.assertEqual(body["version_current"], __version__)
|
||||
self.assertEqual(body["version_current"], authentik_version())
|
||||
|
||||
def test_apps(self):
|
||||
"""Test apps API"""
|
||||
|
||||
@@ -11,7 +11,7 @@ from rest_framework.relations import PrimaryKeyRelatedField
|
||||
from rest_framework.serializers import Serializer
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.blueprints.v1.common import BlueprintEntryDesiredState
|
||||
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, is_model_allowed
|
||||
from authentik.blueprints.v1.meta.registry import BaseMetaModel, registry
|
||||
@@ -48,7 +48,7 @@ class Command(BaseCommand):
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||
"type": "object",
|
||||
"title": f"authentik {__version__} Blueprint schema",
|
||||
"title": f"authentik {authentik_version()} Blueprint schema",
|
||||
"required": ["version", "entries"],
|
||||
"properties": {
|
||||
"version": {
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.http.request import HttpRequest
|
||||
from django.utils.html import _json_script_escapes
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.lib.sentry import get_http_meta
|
||||
from authentik.tenants.models import Tenant
|
||||
@@ -44,5 +44,5 @@ def context_processor(request: HttpRequest) -> dict[str, Any]:
|
||||
"brand_css": brand_css,
|
||||
"footer_links": tenant.footer_links,
|
||||
"html_meta": {**get_http_meta()},
|
||||
"version": get_full_version(),
|
||||
"version": authentik_full_version(),
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.core.management.base import BaseCommand
|
||||
from django.db.models import Model
|
||||
from django.db.models.signals import post_save, pre_delete
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.core.models import User
|
||||
from authentik.events.middleware import should_log_model
|
||||
from authentik.events.models import Event, EventAction
|
||||
@@ -19,7 +19,7 @@ from authentik.events.utils import model_to_dict
|
||||
|
||||
|
||||
def get_banner_text(shell_type="shell") -> str:
|
||||
return f"""### authentik {shell_type} ({get_full_version()})
|
||||
return f"""### authentik {shell_type} ({authentik_full_version()})
|
||||
### Node {platform.node()} | Arch {platform.machine()} | Python {platform.python_version()} """
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from django import template
|
||||
from django.templatetags.static import static as static_loader
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -11,4 +11,4 @@ register = template.Library()
|
||||
@register.simple_tag()
|
||||
def versioned_script(path: str) -> str:
|
||||
"""Wrapper around {% static %} tag that supports setting the version"""
|
||||
return static_loader(path.replace("%v", get_full_version()))
|
||||
return static_loader(path.replace("%v", authentik_full_version()))
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.utils.translation import gettext as _
|
||||
from django.views.generic.base import RedirectView, TemplateView
|
||||
from rest_framework.request import Request
|
||||
|
||||
from authentik import get_build_hash
|
||||
from authentik import authentik_build_hash
|
||||
from authentik.admin.tasks import LOCAL_VERSION
|
||||
from authentik.api.v3.config import ConfigView
|
||||
from authentik.brands.api import CurrentBrandSerializer
|
||||
@@ -52,7 +52,7 @@ class InterfaceView(TemplateView):
|
||||
kwargs["brand_json"] = dumps(brand.data)
|
||||
kwargs["version_family"] = f"{LOCAL_VERSION.major}.{LOCAL_VERSION.minor}"
|
||||
kwargs["version_subdomain"] = f"version-{LOCAL_VERSION.major}-{LOCAL_VERSION.minor}"
|
||||
kwargs["build"] = get_build_hash()
|
||||
kwargs["build"] = authentik_build_hash()
|
||||
kwargs["url_kwargs"] = self.kwargs
|
||||
kwargs["base_url"] = self.request.build_absolute_uri(CONFIG.get("web.path", "/"))
|
||||
kwargs["base_url_rel"] = CONFIG.get("web.path", "/")
|
||||
|
||||
@@ -12,7 +12,7 @@ from cryptography.x509.oid import NameOID
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ class CertificateBuilder:
|
||||
.issuer_name(
|
||||
x509.Name(
|
||||
[
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, f"authentik {__version__}"),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, f"authentik {authentik_version()}"),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ from requests import RequestException
|
||||
from rest_framework.serializers import Serializer
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.brands.utils import DEFAULT_BRAND
|
||||
from authentik.core.middleware import (
|
||||
@@ -434,7 +434,7 @@ class NotificationTransport(TasksModel, SerializerModel):
|
||||
"title": notification.body,
|
||||
"color": "#fd4b2d",
|
||||
"fields": fields,
|
||||
"footer": f"authentik {get_full_version()}",
|
||||
"footer": f"authentik {authentik_full_version()}",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.core.mail.backends.locmem import EmailBackend
|
||||
from django.test import TestCase
|
||||
from requests_mock import Mocker
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.events.models import (
|
||||
Event,
|
||||
@@ -118,7 +118,7 @@ class TestEventTransports(TestCase):
|
||||
{"short": True, "title": "Event user", "value": self.user.username},
|
||||
{"title": "foo", "value": "bar,"},
|
||||
],
|
||||
"footer": f"authentik {get_full_version()}",
|
||||
"footer": f"authentik {authentik_full_version()}",
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.core.management.base import BaseCommand
|
||||
from django.test import RequestFactory
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
|
||||
@@ -99,7 +99,7 @@ class Command(BaseCommand):
|
||||
total_min: int = min(min(inner) for inner in values)
|
||||
total_avg = sum(sum(inner) for inner in values) / sum(len(inner) for inner in values)
|
||||
|
||||
print(f"Version: {__version__}")
|
||||
print(f"Version: {authentik_version()}")
|
||||
print(f"Processes: {len(values)}")
|
||||
print(f"\tMax: {total_max * 100}ms")
|
||||
print(f"\tMin: {total_min * 100}ms")
|
||||
|
||||
@@ -30,7 +30,7 @@ from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME
|
||||
from structlog.stdlib import get_logger
|
||||
from websockets.exceptions import WebSocketException
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_build_hash, authentik_version
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.http import authentik_user_agent
|
||||
from authentik.lib.utils.reflection import get_env
|
||||
@@ -117,11 +117,11 @@ def sentry_init(**sentry_init_kwargs):
|
||||
],
|
||||
before_send=before_send,
|
||||
traces_sampler=traces_sampler,
|
||||
release=f"authentik@{__version__}",
|
||||
release=f"authentik@{authentik_version()}",
|
||||
transport=SentryTransport,
|
||||
**kwargs,
|
||||
)
|
||||
set_tag("authentik.build_hash", get_build_hash("tagged"))
|
||||
set_tag("authentik.build_hash", authentik_build_hash("tagged"))
|
||||
set_tag("authentik.env", get_env())
|
||||
set_tag("authentik.component", "backend")
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from uuid import uuid4
|
||||
from requests.sessions import PreparedRequest, Session
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
LOGGER = get_logger()
|
||||
@@ -13,7 +13,7 @@ LOGGER = get_logger()
|
||||
|
||||
def authentik_user_agent() -> str:
|
||||
"""Get a common user agent"""
|
||||
return f"authentik@{get_full_version()}"
|
||||
return f"authentik@{authentik_full_version()}"
|
||||
|
||||
|
||||
class TimeoutSession(Session):
|
||||
|
||||
@@ -13,7 +13,7 @@ from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik import get_build_hash
|
||||
from authentik import authentik_build_hash
|
||||
from authentik.core.api.providers import ProviderSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer
|
||||
@@ -194,7 +194,7 @@ class OutpostViewSet(UsedByMixin, ModelViewSet):
|
||||
"openssl_version": state.openssl_version,
|
||||
"fips_enabled": state.fips_enabled,
|
||||
"hostname": state.hostname,
|
||||
"build_hash_should": get_build_hash(),
|
||||
"build_hash_should": authentik_build_hash(),
|
||||
}
|
||||
)
|
||||
return Response(OutpostHealthSerializer(states, many=True).data)
|
||||
|
||||
@@ -4,7 +4,7 @@ from dataclasses import dataclass
|
||||
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_build_hash, authentik_version
|
||||
from authentik.events.logs import LogEvent, capture_logs
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
@@ -99,6 +99,6 @@ class BaseController:
|
||||
image_name_template: str = CONFIG.get("outposts.container_image_base")
|
||||
return image_name_template % {
|
||||
"type": self.outpost.type,
|
||||
"version": __version__,
|
||||
"build_hash": get_build_hash(),
|
||||
"version": authentik_version(),
|
||||
"build_hash": authentik_build_hash(),
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ from paramiko.ssh_exception import SSHException
|
||||
from structlog.stdlib import get_logger
|
||||
from yaml import safe_dump
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.outposts.apps import MANAGED_OUTPOST
|
||||
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
|
||||
from authentik.outposts.docker_ssh import DockerInlineSSH, SSHManagedExternallyException
|
||||
@@ -185,7 +185,7 @@ class DockerController(BaseController):
|
||||
try:
|
||||
self.client.images.pull(image)
|
||||
except DockerException: # pragma: no cover
|
||||
image = f"ghcr.io/goauthentik/{self.outpost.type}:{__version__}"
|
||||
image = f"ghcr.io/goauthentik/{self.outpost.type}:{authentik_version()}"
|
||||
self.client.images.pull(image)
|
||||
return image
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from requests import Response
|
||||
from structlog.stdlib import get_logger
|
||||
from urllib3.exceptions import HTTPError
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.outposts.apps import MANAGED_OUTPOST
|
||||
from authentik.outposts.controllers.base import ControllerException
|
||||
from authentik.outposts.controllers.k8s.triggers import NeedsRecreate, NeedsUpdate
|
||||
@@ -29,8 +29,8 @@ T = TypeVar("T", V1Pod, V1Deployment)
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
"""Wrapper for __version__ to make testing easier"""
|
||||
return __version__
|
||||
"""Wrapper for authentik_version() to make testing easier"""
|
||||
return authentik_version()
|
||||
|
||||
|
||||
class KubernetesObjectReconciler(Generic[T]):
|
||||
|
||||
@@ -23,7 +23,7 @@ from kubernetes.client import (
|
||||
V1SecurityContext,
|
||||
)
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.outposts.controllers.base import FIELD_MANAGER
|
||||
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
|
||||
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
|
||||
@@ -94,7 +94,7 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
|
||||
meta = self.get_object_meta(name=self.name)
|
||||
image_name = self.controller.get_container_image()
|
||||
image_pull_secrets = self.outpost.config.kubernetes_image_pull_secrets
|
||||
version = get_full_version().replace("+", "-")
|
||||
version = authentik_full_version().replace("+", "-")
|
||||
return V1Deployment(
|
||||
metadata=meta,
|
||||
spec=V1DeploymentSpec(
|
||||
|
||||
@@ -19,7 +19,7 @@ from packaging.version import Version, parse
|
||||
from rest_framework.serializers import Serializer
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_build_hash, authentik_version
|
||||
from authentik.blueprints.models import ManagedModel
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.models import (
|
||||
@@ -40,7 +40,7 @@ from authentik.outposts.controllers.k8s.utils import get_namespace
|
||||
from authentik.tasks.schedules.common import ScheduleSpec
|
||||
from authentik.tasks.schedules.models import ScheduledModel
|
||||
|
||||
OUR_VERSION = parse(__version__)
|
||||
OUR_VERSION = parse(authentik_version())
|
||||
OUTPOST_HELLO_INTERVAL = 10
|
||||
LOGGER = get_logger()
|
||||
|
||||
@@ -481,7 +481,7 @@ class OutpostState:
|
||||
"""Check if outpost version matches our version"""
|
||||
if not self.version:
|
||||
return False
|
||||
if self.build_hash != get_build_hash():
|
||||
if self.build_hash != authentik_build_hash():
|
||||
return False
|
||||
return parse(self.version) != OUR_VERSION
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from channels.routing import URLRouter
|
||||
from channels.testing import WebsocketCommunicator
|
||||
from django.test import TransactionTestCase
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.core.tests.utils import create_test_flow
|
||||
from authentik.outposts.consumer import WebsocketMessage, WebsocketMessageInstruction
|
||||
from authentik.outposts.models import Outpost, OutpostType
|
||||
@@ -65,7 +65,7 @@ class TestOutpostWS(TransactionTestCase):
|
||||
WebsocketMessage(
|
||||
instruction=WebsocketMessageInstruction.HELLO,
|
||||
args={
|
||||
"version": __version__,
|
||||
"version": authentik_version(),
|
||||
"buildHash": "foo",
|
||||
"uuid": "123",
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import orjson
|
||||
from sentry_sdk import set_tag
|
||||
from xmlsec import enable_debug_trace
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.lib.config import CONFIG, django_db_config, redis_url
|
||||
from authentik.lib.logging import get_logger_config, structlog_configure
|
||||
from authentik.lib.sentry import sentry_init
|
||||
@@ -144,7 +144,7 @@ GUARDIAN_MONKEY_PATCH_USER = False
|
||||
SPECTACULAR_SETTINGS = {
|
||||
"TITLE": "authentik",
|
||||
"DESCRIPTION": "Making authentication simple.",
|
||||
"VERSION": __version__,
|
||||
"VERSION": authentik_version(),
|
||||
"COMPONENT_SPLIT_REQUEST": True,
|
||||
"SCHEMA_PATH_PREFIX": "/api/v([0-9]+(beta)?)",
|
||||
"SCHEMA_PATH_PREFIX_TRIM": True,
|
||||
@@ -567,7 +567,7 @@ if DEBUG:
|
||||
enable_debug_trace(True)
|
||||
|
||||
|
||||
CONFIG.log("info", "Booting authentik", version=__version__)
|
||||
CONFIG.log("info", "Booting authentik", version=authentik_version())
|
||||
|
||||
# Load subapps's settings
|
||||
_filter_and_update(SHARED_APPS + TENANT_APPS)
|
||||
|
||||
@@ -5,7 +5,7 @@ from ssl import OPENSSL_VERSION
|
||||
import pytest
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
|
||||
IS_CI = "CI" in environ
|
||||
|
||||
@@ -22,7 +22,7 @@ def pytest_sessionstart(*_, **__):
|
||||
def pytest_report_header(*_, **__):
|
||||
"""Add authentik version to pytest output"""
|
||||
return [
|
||||
f"authentik version: {get_full_version()}",
|
||||
f"authentik version: {authentik_full_version()}",
|
||||
f"OpenSSL version: {OPENSSL_VERSION}, FIPS: {backend._fips_enabled}",
|
||||
]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from django.http.response import Http404
|
||||
from requests.exceptions import RequestException
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version
|
||||
from authentik.core.sources.flow_manager import SourceFlowManager
|
||||
from authentik.lib.utils.http import get_http_session
|
||||
from authentik.sources.plex.models import (
|
||||
@@ -38,7 +38,7 @@ class PlexAuth:
|
||||
"""Get common headers"""
|
||||
return {
|
||||
"X-Plex-Product": "authentik",
|
||||
"X-Plex-Version": __version__,
|
||||
"X-Plex-Version": authentik_version(),
|
||||
"X-Plex-Device-Vendor": "goauthentik.io",
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.rbac.permissions import HasPermission
|
||||
from authentik.tasks.models import WorkerStatus
|
||||
|
||||
@@ -30,7 +30,7 @@ class WorkerView(APIView):
|
||||
)
|
||||
def get(self, request: Request) -> Response:
|
||||
response = []
|
||||
our_version = parse(get_full_version())
|
||||
our_version = parse(authentik_full_version())
|
||||
for status in WorkerStatus.objects.filter(last_seen__gt=now() - timedelta(minutes=2)):
|
||||
lock_id = f"goauthentik.io/worker/status/{status.pk}"
|
||||
with pglock.advisory(lock_id, timeout=0, side_effect=pglock.Return) as acquired:
|
||||
|
||||
@@ -7,7 +7,9 @@ import pglock
|
||||
from django.db import OperationalError, connections
|
||||
from django.utils.timezone import now
|
||||
from django_dramatiq_postgres.middleware import HTTPServer
|
||||
from django_dramatiq_postgres.middleware import MetricsMiddleware as BaseMetricsMiddleware
|
||||
from django_dramatiq_postgres.middleware import (
|
||||
MetricsMiddleware as BaseMetricsMiddleware,
|
||||
)
|
||||
from django_redis import get_redis_connection
|
||||
from dramatiq.broker import Broker
|
||||
from dramatiq.message import Message
|
||||
@@ -15,7 +17,7 @@ from dramatiq.middleware import Middleware
|
||||
from redis.exceptions import RedisError
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.sentry import should_ignore_exception
|
||||
from authentik.tasks.models import Task, TaskStatus, WorkerStatus
|
||||
@@ -208,7 +210,7 @@ class WorkerStatusMiddleware(Middleware):
|
||||
def run():
|
||||
status = WorkerStatus.objects.create(
|
||||
hostname=socket.gethostname(),
|
||||
version=get_full_version(),
|
||||
version=authentik_full_version(),
|
||||
)
|
||||
lock_id = f"goauthentik.io/worker/status/{status.pk}"
|
||||
with pglock.advisory(lock_id, side_effect=pglock.Raise):
|
||||
|
||||
@@ -6,7 +6,7 @@ from django.utils.timezone import now, timedelta
|
||||
from packaging.version import parse
|
||||
from prometheus_client import Gauge
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.root.monitoring import monitoring_set
|
||||
from authentik.tasks.models import WorkerStatus
|
||||
|
||||
@@ -22,7 +22,7 @@ GAUGE_WORKERS = Gauge(
|
||||
)
|
||||
|
||||
|
||||
_version = parse(get_full_version())
|
||||
_version = parse(authentik_full_version())
|
||||
|
||||
|
||||
@receiver(monitoring_set)
|
||||
|
||||
@@ -36,7 +36,7 @@ var rootCmd = &cobra.Command{
|
||||
AttachStacktrace: true,
|
||||
EnableTracing: true,
|
||||
TracesSampler: sentryutils.SamplerFunc(config.Get().ErrorReporting.SampleRate),
|
||||
Release: fmt.Sprintf("authentik@%s", constants.VERSION),
|
||||
Release: fmt.Sprintf("authentik@%s", constants.VERSION()),
|
||||
Environment: config.Get().ErrorReporting.Environment,
|
||||
HTTPTransport: webutils.NewUserAgentTransport(constants.UserAgent(), http.DefaultTransport),
|
||||
IgnoreErrors: []string{
|
||||
|
||||
@@ -1,90 +1,85 @@
|
||||
---
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 5s
|
||||
volumes:
|
||||
- database:/var/lib/postgresql/data
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
|
||||
POSTGRES_USER: ${PG_USER:-authentik}
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
env_file:
|
||||
- .env
|
||||
redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
command: --save 60 1 --loglevel warning
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 3s
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
start_period: 20s
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
|
||||
timeout: 5s
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
volumes:
|
||||
- ./media:/media
|
||||
- ./custom-templates:/templates
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "${COMPOSE_PORT_HTTP:-9000}:9000"
|
||||
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
|
||||
- database:/var/lib/postgresql/data
|
||||
redis:
|
||||
command: --save 60 1 --loglevel warning
|
||||
healthcheck:
|
||||
interval: 30s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- redis-cli ping | grep PONG
|
||||
timeout: 3s
|
||||
image: docker.io/library/redis:alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
command: server
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
# `user: root` and the docker socket volume are optional.
|
||||
# See more for the docker socket integration here:
|
||||
# https://goauthentik.io/docs/outposts/integrations/docker
|
||||
# Removing `user: root` also prevents the worker from fixing the permissions
|
||||
# on the mounted folders, so when removing this make sure the folders have the correct UID/GID
|
||||
# (1000:1000 by default)
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
ports:
|
||||
- ${COMPOSE_PORT_HTTP:-9000}:9000
|
||||
- ${COMPOSE_PORT_HTTPS:-9443}:9443
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./media:/media
|
||||
- ./custom-templates:/templates
|
||||
worker:
|
||||
command: worker
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
restart: unless-stopped
|
||||
user: root
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./media:/media
|
||||
- ./certs:/certs
|
||||
- ./custom-templates:/templates
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./media:/media
|
||||
- ./certs:/certs
|
||||
- ./custom-templates:/templates
|
||||
volumes:
|
||||
database:
|
||||
driver: local
|
||||
|
||||
1
internal/constants/VERSION
Normal file
1
internal/constants/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
2025.6.4
|
||||
@@ -1,10 +1,14 @@
|
||||
package constants
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
//go:embed VERSION
|
||||
var version string
|
||||
|
||||
func BUILD(def string) string {
|
||||
build := os.Getenv("GIT_BUILD_HASH")
|
||||
if build == "" {
|
||||
@@ -13,12 +17,15 @@ func BUILD(def string) string {
|
||||
return build
|
||||
}
|
||||
|
||||
func VERSION() string {
|
||||
return version
|
||||
}
|
||||
|
||||
func FullVersion() string {
|
||||
ver := VERSION
|
||||
if b := BUILD(""); b != "" {
|
||||
return fmt.Sprintf("%s+%s", ver, b)
|
||||
return fmt.Sprintf("%s+%s", version, b)
|
||||
}
|
||||
return ver
|
||||
return version
|
||||
}
|
||||
|
||||
func UserAgentOutpost() string {
|
||||
@@ -32,5 +39,3 @@ func UserAgentIPC() string {
|
||||
func UserAgent() string {
|
||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2025.6.4"
|
||||
|
||||
@@ -198,7 +198,7 @@ func (a *APIController) OnRefresh() error {
|
||||
|
||||
func (a *APIController) getEventPingArgs() map[string]interface{} {
|
||||
args := map[string]interface{}{
|
||||
"version": constants.VERSION,
|
||||
"version": constants.VERSION(),
|
||||
"buildHash": constants.BUILD(""),
|
||||
"uuid": a.instanceUUID.String(),
|
||||
"golangVersion": runtime.Version(),
|
||||
@@ -218,7 +218,7 @@ func (a *APIController) StartBackgroundTasks() error {
|
||||
"outpost_name": a.Outpost.Name,
|
||||
"outpost_type": a.Server.Type(),
|
||||
"uuid": a.instanceUUID.String(),
|
||||
"version": constants.VERSION,
|
||||
"version": constants.VERSION(),
|
||||
"build": constants.BUILD(""),
|
||||
}).Set(1)
|
||||
go func() {
|
||||
|
||||
@@ -163,7 +163,7 @@ func (ac *APIController) startEventHandler() {
|
||||
"outpost_name": ac.Outpost.Name,
|
||||
"outpost_type": ac.Server.Type(),
|
||||
"uuid": ac.instanceUUID.String(),
|
||||
"version": constants.VERSION,
|
||||
"version": constants.VERSION(),
|
||||
"build": constants.BUILD(""),
|
||||
}).SetToCurrentTime()
|
||||
}
|
||||
@@ -228,7 +228,7 @@ func (ac *APIController) startIntervalUpdater() {
|
||||
"outpost_name": ac.Outpost.Name,
|
||||
"outpost_type": ac.Server.Type(),
|
||||
"uuid": ac.instanceUUID.String(),
|
||||
"version": constants.VERSION,
|
||||
"version": constants.VERSION(),
|
||||
"build": constants.BUILD(""),
|
||||
}).SetToCurrentTime()
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func doGlobalSetup(outpost api.Outpost, globalConfig *api.Config) {
|
||||
Environment: globalConfig.ErrorReporting.Environment,
|
||||
EnableTracing: true,
|
||||
TracesSampler: sentryutils.SamplerFunc(float64(globalConfig.ErrorReporting.TracesSampleRate)),
|
||||
Release: fmt.Sprintf("authentik@%s", constants.VERSION),
|
||||
Release: fmt.Sprintf("authentik@%s", constants.VERSION()),
|
||||
HTTPTransport: webutils.NewUserAgentTransport(constants.UserAgentOutpost(), http.DefaultTransport),
|
||||
IgnoreErrors: []string{
|
||||
http.ErrAbortHandler.Error(),
|
||||
@@ -66,7 +66,7 @@ func doGlobalSetup(outpost api.Outpost, globalConfig *api.Config) {
|
||||
}
|
||||
|
||||
if !initialSetup {
|
||||
l.WithField("hash", constants.BUILD("tagged")).WithField("version", constants.VERSION).Info("Starting authentik outpost")
|
||||
l.WithField("hash", constants.BUILD("tagged")).WithField("version", constants.VERSION()).Info("Starting authentik outpost")
|
||||
initialSetup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func (ws *WebServer) staticHeaderMiddleware(h http.Handler) http.Handler {
|
||||
etagHandler := etag.Handler(h, false)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "public, no-transform")
|
||||
w.Header().Set("X-authentik-version", constants.VERSION)
|
||||
w.Header().Set("X-authentik-version", constants.VERSION())
|
||||
w.Header().Set("Vary", "X-authentik-version, Etag")
|
||||
etagHandler.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@ from aws_cdk import (
|
||||
)
|
||||
from constructs import Construct
|
||||
|
||||
from authentik import __version__
|
||||
from authentik import authentik_version as ak_version
|
||||
|
||||
|
||||
class AuthentikStack(Stack):
|
||||
@@ -88,7 +88,7 @@ class AuthentikStack(Stack):
|
||||
self,
|
||||
"AuthentikVersion",
|
||||
type="String",
|
||||
default=__version__,
|
||||
default=ak_version(),
|
||||
description="authentik Docker image tag",
|
||||
)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from prometheus_client.values import MultiProcessValue
|
||||
|
||||
from authentik import get_full_version
|
||||
from authentik import authentik_full_version
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.debug import start_debug_server
|
||||
from authentik.lib.logging import get_logger_config
|
||||
@@ -127,9 +127,9 @@ if not CONFIG.get_bool("disable_startup_analytics", False):
|
||||
json={
|
||||
"domain": "authentik",
|
||||
"name": "pageview",
|
||||
"referrer": get_full_version(),
|
||||
"referrer": authentik_full_version(),
|
||||
"url": (
|
||||
f"http://localhost/{env}?utm_source={get_full_version()}&utm_medium={env}"
|
||||
f"http://localhost/{env}?utm_source={authentik_full_version()}&utm_medium={env}"
|
||||
),
|
||||
},
|
||||
headers={
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
from lifecycle.migrate import BaseMigration
|
||||
from datetime import datetime
|
||||
|
||||
from authentik import __version__, get_build_hash
|
||||
from authentik import authentik_version, authentik_build_hash
|
||||
|
||||
|
||||
class Migration(BaseMigration):
|
||||
@@ -14,7 +14,7 @@ class Migration(BaseMigration):
|
||||
ORDER BY "timestamp" DESC
|
||||
LIMIT 1
|
||||
""",
|
||||
(__version__, get_build_hash()),
|
||||
(authentik_version(), authentik_build_hash()),
|
||||
)
|
||||
return not bool(self.cur.rowcount)
|
||||
|
||||
@@ -24,7 +24,7 @@ class Migration(BaseMigration):
|
||||
INSERT INTO authentik_version_history ("timestamp", version, build)
|
||||
VALUES (%s, %s, %s)
|
||||
""",
|
||||
(datetime.now(), __version__, get_build_hash()),
|
||||
(datetime.now(), authentik_version(), authentik_build_hash()),
|
||||
)
|
||||
self.cur.execute(
|
||||
"""
|
||||
|
||||
317
pyproject.toml
317
pyproject.toml
@@ -5,112 +5,111 @@ description = ""
|
||||
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
|
||||
requires-python = "==3.13.*"
|
||||
dependencies = [
|
||||
"argon2-cffi==25.1.0",
|
||||
"channels==4.3.0",
|
||||
"channels-redis==4.3.0",
|
||||
"cryptography==45.0.5",
|
||||
"dacite==1.9.2",
|
||||
"deepmerge==2.0",
|
||||
"defusedxml==0.7.1",
|
||||
"django==5.1.11",
|
||||
"django-countries==7.6.1",
|
||||
"django-cte==2.0.0",
|
||||
"django-dramatiq-postgres",
|
||||
"django-filter==25.1",
|
||||
"django-guardian==3.0.3",
|
||||
"django-model-utils==5.0.0",
|
||||
"django-pglock==1.7.2",
|
||||
"django-pgtrigger==4.15.2",
|
||||
"django-prometheus==2.4.1",
|
||||
"django-redis==6.0.0",
|
||||
"django-storages[s3]==1.14.6",
|
||||
"django-tenants==3.8.0",
|
||||
"djangoql==0.18.1",
|
||||
"djangorestframework-guardian==0.4.0",
|
||||
"djangorestframework==3.16.0",
|
||||
"docker==7.1.0",
|
||||
"drf-orjson-renderer==1.7.3",
|
||||
"drf-spectacular==0.28.0",
|
||||
"dumb-init==1.2.5.post1",
|
||||
"duo-client==5.5.0",
|
||||
"fido2==2.0.0",
|
||||
"geoip2==5.1.0",
|
||||
"geopy==2.4.1",
|
||||
"google-api-python-client==2.177.0",
|
||||
"gssapi==1.9.0",
|
||||
"gunicorn==23.0.0",
|
||||
"jsonpatch==1.33",
|
||||
"jwcrypto==1.5.6",
|
||||
"kubernetes==33.1.0",
|
||||
"ldap3==2.9.1",
|
||||
"lxml==6.0.0",
|
||||
"msgraph-sdk==1.39.0",
|
||||
"opencontainers==0.0.15",
|
||||
"packaging==25.0",
|
||||
"paramiko==3.5.1",
|
||||
"psycopg[c,pool]==3.2.9",
|
||||
"pydantic==2.11.7",
|
||||
"pydantic-scim==0.0.8",
|
||||
"pyjwt==2.10.1",
|
||||
"pyrad==2.4",
|
||||
"python-kadmin-rs==0.6.1",
|
||||
"pyyaml==6.0.2",
|
||||
"requests-oauthlib==2.0.0",
|
||||
"scim2-filter-parser==0.7.0",
|
||||
"sentry-sdk==2.33.2",
|
||||
"service-identity==24.2.0",
|
||||
"setproctitle==1.3.6",
|
||||
"structlog==25.4.0",
|
||||
"swagger-spec-validator==3.0.4",
|
||||
"twilio==9.7.0",
|
||||
"ua-parser==1.0.1",
|
||||
"unidecode==1.4.0",
|
||||
"urllib3<3",
|
||||
"uvicorn[standard]==0.35.0",
|
||||
"watchdog==6.0.0",
|
||||
"webauthn==2.6.0",
|
||||
"wsproto==1.2.0",
|
||||
"xmlsec==1.3.16",
|
||||
"zxcvbn==4.5.0",
|
||||
"argon2-cffi==25.1.0",
|
||||
"channels==4.3.0",
|
||||
"channels-redis==4.3.0",
|
||||
"cryptography==45.0.5",
|
||||
"dacite==1.9.2",
|
||||
"deepmerge==2.0",
|
||||
"defusedxml==0.7.1",
|
||||
"django==5.1.11",
|
||||
"django-countries==7.6.1",
|
||||
"django-cte==2.0.0",
|
||||
"django-dramatiq-postgres",
|
||||
"django-filter==25.1",
|
||||
"django-guardian==3.0.3",
|
||||
"django-model-utils==5.0.0",
|
||||
"django-pglock==1.7.2",
|
||||
"django-pgtrigger==4.15.2",
|
||||
"django-prometheus==2.4.1",
|
||||
"django-redis==6.0.0",
|
||||
"django-storages[s3]==1.14.6",
|
||||
"django-tenants==3.8.0",
|
||||
"djangoql==0.18.1",
|
||||
"djangorestframework-guardian==0.4.0",
|
||||
"djangorestframework==3.16.0",
|
||||
"docker==7.1.0",
|
||||
"drf-orjson-renderer==1.7.3",
|
||||
"drf-spectacular==0.28.0",
|
||||
"dumb-init==1.2.5.post1",
|
||||
"duo-client==5.5.0",
|
||||
"fido2==2.0.0",
|
||||
"geoip2==5.1.0",
|
||||
"geopy==2.4.1",
|
||||
"google-api-python-client==2.177.0",
|
||||
"gssapi==1.9.0",
|
||||
"gunicorn==23.0.0",
|
||||
"jsonpatch==1.33",
|
||||
"jwcrypto==1.5.6",
|
||||
"kubernetes==33.1.0",
|
||||
"ldap3==2.9.1",
|
||||
"lxml==6.0.0",
|
||||
"msgraph-sdk==1.39.0",
|
||||
"opencontainers==0.0.15",
|
||||
"packaging==25.0",
|
||||
"paramiko==3.5.1",
|
||||
"psycopg[c,pool]==3.2.9",
|
||||
"pydantic==2.11.7",
|
||||
"pydantic-scim==0.0.8",
|
||||
"pyjwt==2.10.1",
|
||||
"pyrad==2.4",
|
||||
"python-kadmin-rs==0.6.1",
|
||||
"pyyaml==6.0.2",
|
||||
"requests-oauthlib==2.0.0",
|
||||
"scim2-filter-parser==0.7.0",
|
||||
"sentry-sdk==2.33.2",
|
||||
"service-identity==24.2.0",
|
||||
"setproctitle==1.3.6",
|
||||
"structlog==25.4.0",
|
||||
"swagger-spec-validator==3.0.4",
|
||||
"twilio==9.7.0",
|
||||
"ua-parser==1.0.1",
|
||||
"unidecode==1.4.0",
|
||||
"urllib3<3",
|
||||
"uvicorn[standard]==0.35.0",
|
||||
"watchdog==6.0.0",
|
||||
"webauthn==2.6.0",
|
||||
"wsproto==1.2.0",
|
||||
"xmlsec==1.3.16",
|
||||
"zxcvbn==4.5.0",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"aws-cdk-lib==2.188.0",
|
||||
"bandit==1.8.3",
|
||||
"black==25.1.0",
|
||||
"bump2version==1.0.1",
|
||||
"channels[daphne]==4.3.0",
|
||||
"codespell==2.4.1",
|
||||
"colorama==0.4.6",
|
||||
"constructs==10.4.2",
|
||||
"coverage[toml]==7.8.0",
|
||||
"debugpy==1.8.14",
|
||||
"drf-jsonschema-serializer==3.0.0",
|
||||
"freezegun==1.5.1",
|
||||
"importlib-metadata==8.6.1",
|
||||
"k5test==0.10.4",
|
||||
"pdoc==15.0.3",
|
||||
"pytest==8.3.5",
|
||||
"pytest-django==4.11.1",
|
||||
"pytest-github-actions-annotate-failures==0.3.0",
|
||||
"pytest-randomly==3.16.0",
|
||||
"pytest-timeout==2.4.0",
|
||||
"requests-mock==1.12.1",
|
||||
"ruff==0.11.9",
|
||||
"selenium==4.32.0",
|
||||
"aws-cdk-lib==2.188.0",
|
||||
"bandit==1.8.3",
|
||||
"black==25.1.0",
|
||||
"channels[daphne]==4.3.0",
|
||||
"codespell==2.4.1",
|
||||
"colorama==0.4.6",
|
||||
"constructs==10.4.2",
|
||||
"coverage[toml]==7.8.0",
|
||||
"debugpy==1.8.14",
|
||||
"drf-jsonschema-serializer==3.0.0",
|
||||
"freezegun==1.5.1",
|
||||
"importlib-metadata==8.6.1",
|
||||
"k5test==0.10.4",
|
||||
"pdoc==15.0.3",
|
||||
"pytest==8.3.5",
|
||||
"pytest-django==4.11.1",
|
||||
"pytest-github-actions-annotate-failures==0.3.0",
|
||||
"pytest-randomly==3.16.0",
|
||||
"pytest-timeout==2.4.0",
|
||||
"requests-mock==1.12.1",
|
||||
"ruff==0.11.9",
|
||||
"selenium==4.32.0",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
no-binary-package = [
|
||||
# This differs from the no-binary packages in the Dockerfile. This is due to the fact
|
||||
# that these packages are built from source for different reasons than cryptography and kadmin.
|
||||
# These packages are built from source to link against the libxml2 on the system which is
|
||||
# required for functionality and to stay up-to-date on both libraries.
|
||||
# The other packages specified in the dockerfile are compiled from source to link against the
|
||||
# correct FIPS OpenSSL libraries
|
||||
"lxml",
|
||||
"xmlsec",
|
||||
# This differs from the no-binary packages in the Dockerfile. This is due to the fact
|
||||
# that these packages are built from source for different reasons than cryptography and kadmin.
|
||||
# These packages are built from source to link against the libxml2 on the system which is
|
||||
# required for functionality and to stay up-to-date on both libraries.
|
||||
# The other packages specified in the dockerfile are compiled from source to link against the
|
||||
# correct FIPS OpenSSL libraries
|
||||
"lxml",
|
||||
"xmlsec",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
@@ -133,29 +132,29 @@ exclude_dirs = ["**/node_modules/**"]
|
||||
|
||||
[tool.codespell]
|
||||
skip = [
|
||||
"**/node_modules",
|
||||
"**/package-lock.json",
|
||||
"schema.yml",
|
||||
"unittest.xml",
|
||||
"./blueprints/schema.json",
|
||||
"go.sum",
|
||||
"locale",
|
||||
"**/web/src/locales",
|
||||
"**/dist", # Distributed build output
|
||||
"**/storybook-static",
|
||||
"**/web/xliff",
|
||||
"**/out", # TypeScript type-checking output
|
||||
"./web/custom-elements.json", # TypeScript custom element definitions
|
||||
"./website/build", # TODO: Remove this after moving website to docs
|
||||
"./website/**/build", # TODO: Remove this after moving website to docs
|
||||
"./docs/build", # Docusaurus Topic docs build output
|
||||
"./docs/**/build", # Docusaurus workspaces output
|
||||
"*.api.mdx", # Generated API docs
|
||||
"./gen-ts-api",
|
||||
"./gen-py-api",
|
||||
"./gen-go-api",
|
||||
"./htmlcov",
|
||||
"./media",
|
||||
"**/node_modules",
|
||||
"**/package-lock.json",
|
||||
"schema.yml",
|
||||
"unittest.xml",
|
||||
"./blueprints/schema.json",
|
||||
"go.sum",
|
||||
"locale",
|
||||
"**/web/src/locales",
|
||||
"**/dist", # Distributed build output
|
||||
"**/storybook-static",
|
||||
"**/web/xliff",
|
||||
"**/out", # TypeScript type-checking output
|
||||
"./web/custom-elements.json", # TypeScript custom element definitions
|
||||
"./website/build", # TODO: Remove this after moving website to docs
|
||||
"./website/**/build", # TODO: Remove this after moving website to docs
|
||||
"./docs/build", # Docusaurus Topic docs build output
|
||||
"./docs/**/build", # Docusaurus workspaces output
|
||||
"*.api.mdx", # Generated API docs
|
||||
"./gen-ts-api",
|
||||
"./gen-py-api",
|
||||
"./gen-go-api",
|
||||
"./htmlcov",
|
||||
"./media",
|
||||
]
|
||||
dictionary = ".github/codespell-dictionary.txt,-"
|
||||
ignore-words = ".github/codespell-words.txt"
|
||||
@@ -172,23 +171,23 @@ exclude = ["**/migrations/**", "**/node_modules/**"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
# pycodestyle
|
||||
"E",
|
||||
# Pyflakes
|
||||
"F",
|
||||
# isort
|
||||
"I",
|
||||
# pyupgrade
|
||||
"UP",
|
||||
# flake8-bugbear
|
||||
"B",
|
||||
# django
|
||||
"DJ",
|
||||
# pylint
|
||||
"PL",
|
||||
# pycodestyle
|
||||
"E",
|
||||
# Pyflakes
|
||||
"F",
|
||||
# isort
|
||||
"I",
|
||||
# pyupgrade
|
||||
"UP",
|
||||
# flake8-bugbear
|
||||
"B",
|
||||
# django
|
||||
"DJ",
|
||||
# pylint
|
||||
"PL",
|
||||
]
|
||||
ignore = [
|
||||
"DJ001", # Avoid using `null=True` on string-based fields,
|
||||
"DJ001", # Avoid using `null=True` on string-based fields,
|
||||
]
|
||||
|
||||
[tool.ruff.lint.pylint]
|
||||
@@ -200,14 +199,14 @@ max-returns = 10
|
||||
source = ["authentik"]
|
||||
relative_files = true
|
||||
omit = [
|
||||
"*/asgi.py",
|
||||
"manage.py",
|
||||
"*/migrations/*",
|
||||
"*/management/commands/*",
|
||||
"*/apps.py",
|
||||
# TODO: Remove this after moving website to docs
|
||||
"website/",
|
||||
"docs/",
|
||||
"*/asgi.py",
|
||||
"manage.py",
|
||||
"*/migrations/*",
|
||||
"*/management/commands/*",
|
||||
"*/apps.py",
|
||||
# TODO: Remove this after moving website to docs
|
||||
"website/",
|
||||
"docs/",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
@@ -215,19 +214,19 @@ sort = "Cover"
|
||||
skip_covered = true
|
||||
precision = 2
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
# Don't complain about missing debug-only code:
|
||||
"def __unicode__",
|
||||
"def __str__",
|
||||
"def __repr__",
|
||||
"if self.debug",
|
||||
"if TYPE_CHECKING",
|
||||
# Don't complain if tests don't hit defensive assertion code:
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
"if 0:",
|
||||
"if __name__ == .__main__.:",
|
||||
"pragma: no cover",
|
||||
# Don't complain about missing debug-only code:
|
||||
"def __unicode__",
|
||||
"def __str__",
|
||||
"def __repr__",
|
||||
"if self.debug",
|
||||
"if TYPE_CHECKING",
|
||||
# Don't complain if tests don't hit defensive assertion code:
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
"if 0:",
|
||||
"if __name__ == .__main__.:",
|
||||
]
|
||||
show_missing = true
|
||||
|
||||
@@ -237,6 +236,6 @@ python_files = ["tests.py", "test_*.py", "*_tests.py"]
|
||||
junit_family = "xunit2"
|
||||
addopts = "-p authentik.root.test_plugin --junitxml=unittest.xml -vv --full-trace --doctest-modules --import-mode=importlib --ignore=authentik/tasks/setup.py"
|
||||
filterwarnings = [
|
||||
"ignore:defusedxml.lxml is no longer supported and will be removed in a future release.:DeprecationWarning",
|
||||
"ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning",
|
||||
"ignore:defusedxml.lxml is no longer supported and will be removed in a future release.:DeprecationWarning",
|
||||
"ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning",
|
||||
]
|
||||
|
||||
92
scripts/generate_docker_compose.py
Normal file
92
scripts/generate_docker_compose.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from yaml import safe_dump
|
||||
|
||||
from authentik import authentik_version
|
||||
|
||||
authentik_image = (
|
||||
f"${{AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}}:${{AUTHENTIK_TAG:-{authentik_version()}}}"
|
||||
)
|
||||
|
||||
base = {
|
||||
"services": {
|
||||
"postgresql": {
|
||||
"env_file": [".env"],
|
||||
"environment": {
|
||||
"POSTGRES_DB": "${PG_DB:-authentik}",
|
||||
"POSTGRES_PASSWORD": "${PG_PASS:?database " "password " "required}",
|
||||
"POSTGRES_USER": "${PG_USER:-authentik}",
|
||||
},
|
||||
"healthcheck": {
|
||||
"interval": "30s",
|
||||
"retries": 5,
|
||||
"start_period": "20s",
|
||||
"test": ["CMD-SHELL", "pg_isready -d " "$${POSTGRES_DB} -U " "$${POSTGRES_USER}"],
|
||||
"timeout": "5s",
|
||||
},
|
||||
"image": "docker.io/library/postgres:16-alpine",
|
||||
"restart": "unless-stopped",
|
||||
"volumes": ["database:/var/lib/postgresql/data"],
|
||||
},
|
||||
"redis": {
|
||||
"command": "--save 60 1 --loglevel warning",
|
||||
"healthcheck": {
|
||||
"interval": "30s",
|
||||
"retries": 5,
|
||||
"start_period": "20s",
|
||||
"test": ["CMD-SHELL", "redis-cli ping | grep PONG"],
|
||||
"timeout": "3s",
|
||||
},
|
||||
"image": "docker.io/library/redis:alpine",
|
||||
"restart": "unless-stopped",
|
||||
"volumes": ["redis:/data"],
|
||||
},
|
||||
"server": {
|
||||
"command": "server",
|
||||
"depends_on": {
|
||||
"postgresql": {"condition": "service_healthy"},
|
||||
"redis": {"condition": "service_healthy"},
|
||||
},
|
||||
"env_file": [".env"],
|
||||
"environment": {
|
||||
"AUTHENTIK_POSTGRESQL__HOST": "postgresql",
|
||||
"AUTHENTIK_POSTGRESQL__NAME": "${PG_DB:-authentik}",
|
||||
"AUTHENTIK_POSTGRESQL__PASSWORD": "${PG_PASS}",
|
||||
"AUTHENTIK_POSTGRESQL__USER": "${PG_USER:-authentik}",
|
||||
"AUTHENTIK_REDIS__HOST": "redis",
|
||||
"AUTHENTIK_SECRET_KEY": "${AUTHENTIK_SECRET_KEY:?secret " "key " "required}",
|
||||
},
|
||||
"image": authentik_image,
|
||||
"ports": ["${COMPOSE_PORT_HTTP:-9000}:9000", "${COMPOSE_PORT_HTTPS:-9443}:9443"],
|
||||
"restart": "unless-stopped",
|
||||
"volumes": ["./media:/media", "./custom-templates:/templates"],
|
||||
},
|
||||
"worker": {
|
||||
"command": "worker",
|
||||
"depends_on": {
|
||||
"postgresql": {"condition": "service_healthy"},
|
||||
"redis": {"condition": "service_healthy"},
|
||||
},
|
||||
"env_file": [".env"],
|
||||
"environment": {
|
||||
"AUTHENTIK_POSTGRESQL__HOST": "postgresql",
|
||||
"AUTHENTIK_POSTGRESQL__NAME": "${PG_DB:-authentik}",
|
||||
"AUTHENTIK_POSTGRESQL__PASSWORD": "${PG_PASS}",
|
||||
"AUTHENTIK_POSTGRESQL__USER": "${PG_USER:-authentik}",
|
||||
"AUTHENTIK_REDIS__HOST": "redis",
|
||||
"AUTHENTIK_SECRET_KEY": "${AUTHENTIK_SECRET_KEY:?secret " "key " "required}",
|
||||
},
|
||||
"image": authentik_image,
|
||||
"restart": "unless-stopped",
|
||||
"user": "root",
|
||||
"volumes": [
|
||||
"/var/run/docker.sock:/var/run/docker.sock",
|
||||
"./media:/media",
|
||||
"./certs:/certs",
|
||||
"./custom-templates:/templates",
|
||||
],
|
||||
},
|
||||
},
|
||||
"volumes": {"database": {"driver": "local"}, "redis": {"driver": "local"}},
|
||||
}
|
||||
|
||||
with open("docker-compose.yml", "w") as _compose:
|
||||
safe_dump(base, _compose)
|
||||
@@ -5,11 +5,11 @@ Generates a Semantic Versioning identifier, suffixed with a timestamp.
|
||||
|
||||
from time import time
|
||||
|
||||
from authentik import __version__ as package_version
|
||||
from authentik import authentik_version
|
||||
|
||||
"""
|
||||
See: https://semver.org/#spec-item-9 (Pre-release spec)
|
||||
"""
|
||||
pre_release_timestamp = int(time())
|
||||
|
||||
print(f"{package_version}-{pre_release_timestamp}")
|
||||
print(f"{authentik_version()}-{pre_release_timestamp}")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""LDAP and Outpost e2e tests"""
|
||||
|
||||
from dataclasses import asdict
|
||||
from time import sleep
|
||||
|
||||
from guardian.shortcuts import assign_perm
|
||||
from ldap3 import ALL, ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE, Connection, Server
|
||||
@@ -56,17 +55,6 @@ class TestProviderLDAP(SeleniumTestCase):
|
||||
outpost.providers.add(ldap)
|
||||
|
||||
self.start_ldap(outpost)
|
||||
|
||||
# Wait until outpost healthcheck succeeds
|
||||
healthcheck_retries = 0
|
||||
while healthcheck_retries < 50: # noqa: PLR2004
|
||||
if len(outpost.state) > 0:
|
||||
state = outpost.state[0]
|
||||
if state.last_seen:
|
||||
break
|
||||
healthcheck_retries += 1
|
||||
sleep(0.5)
|
||||
sleep(5)
|
||||
return outpost
|
||||
|
||||
@retry()
|
||||
|
||||
@@ -88,15 +88,6 @@ class TestProviderProxy(SeleniumTestCase):
|
||||
|
||||
self.start_proxy(outpost)
|
||||
|
||||
# Wait until outpost healthcheck succeeds
|
||||
healthcheck_retries = 0
|
||||
while healthcheck_retries < 50: # noqa: PLR2004
|
||||
if len(outpost.state) > 0:
|
||||
state = outpost.state[0]
|
||||
if state.last_seen:
|
||||
break
|
||||
healthcheck_retries += 1
|
||||
sleep(0.5)
|
||||
sleep(5)
|
||||
|
||||
self.driver.get("http://localhost:9000/api")
|
||||
@@ -170,15 +161,6 @@ class TestProviderProxy(SeleniumTestCase):
|
||||
|
||||
self.start_proxy(outpost)
|
||||
|
||||
# Wait until outpost healthcheck succeeds
|
||||
healthcheck_retries = 0
|
||||
while healthcheck_retries < 50: # noqa: PLR2004
|
||||
if len(outpost.state) > 0:
|
||||
state = outpost.state[0]
|
||||
if state.last_seen:
|
||||
break
|
||||
healthcheck_retries += 1
|
||||
sleep(0.5)
|
||||
sleep(5)
|
||||
|
||||
self.driver.get("http://localhost:9000/api")
|
||||
|
||||
@@ -77,17 +77,6 @@ class TestProviderProxyForward(SeleniumTestCase):
|
||||
|
||||
self.start_outpost(outpost)
|
||||
|
||||
# Wait until outpost healthcheck succeeds
|
||||
healthcheck_retries = 0
|
||||
while healthcheck_retries < 50: # noqa: PLR2004
|
||||
if len(outpost.state) > 0:
|
||||
state = outpost.state[0]
|
||||
if state.last_seen:
|
||||
break
|
||||
healthcheck_retries += 1
|
||||
sleep(0.5)
|
||||
sleep(5)
|
||||
|
||||
@retry()
|
||||
def test_traefik(self):
|
||||
"""Test traefik"""
|
||||
|
||||
@@ -51,15 +51,6 @@ class TestProviderRadius(SeleniumTestCase):
|
||||
|
||||
self.start_radius(outpost)
|
||||
|
||||
# Wait until outpost healthcheck succeeds
|
||||
healthcheck_retries = 0
|
||||
while healthcheck_retries < 50: # noqa: PLR2004
|
||||
if len(outpost.state) > 0:
|
||||
state = outpost.state[0]
|
||||
if state.last_seen:
|
||||
break
|
||||
healthcheck_retries += 1
|
||||
sleep(0.5)
|
||||
sleep(5)
|
||||
return outpost
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_local_ip() -> str:
|
||||
class DockerTestCase(TestCase):
|
||||
"""Mixin for dealing with containers"""
|
||||
|
||||
max_healthcheck_attempts = 30
|
||||
max_healthcheck_attempts = 45
|
||||
|
||||
__client: DockerClient
|
||||
__network: Network
|
||||
@@ -88,7 +88,7 @@ class DockerTestCase(TestCase):
|
||||
sleep(1)
|
||||
attempt += 1
|
||||
if attempt >= self.max_healthcheck_attempts:
|
||||
self.failureException("Container failed to start")
|
||||
raise self.failureException("Container failed to start")
|
||||
|
||||
def get_container_image(self, base: str) -> str:
|
||||
"""Try to pull docker image based on git branch, fallback to main if not found."""
|
||||
|
||||
11
uv.lock
generated
11
uv.lock
generated
@@ -236,7 +236,6 @@ dev = [
|
||||
{ name = "aws-cdk-lib" },
|
||||
{ name = "bandit" },
|
||||
{ name = "black" },
|
||||
{ name = "bump2version" },
|
||||
{ name = "channels", extra = ["daphne"] },
|
||||
{ name = "codespell" },
|
||||
{ name = "colorama" },
|
||||
@@ -334,7 +333,6 @@ dev = [
|
||||
{ name = "aws-cdk-lib", specifier = "==2.188.0" },
|
||||
{ name = "bandit", specifier = "==1.8.3" },
|
||||
{ name = "black", specifier = "==25.1.0" },
|
||||
{ name = "bump2version", specifier = "==1.0.1" },
|
||||
{ name = "channels", extras = ["daphne"], specifier = "==4.3.0" },
|
||||
{ name = "codespell", specifier = "==2.4.1" },
|
||||
{ name = "colorama", specifier = "==0.4.6" },
|
||||
@@ -583,15 +581,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/16/56/dd25fb9e47060e8f7e353208678fefb65d1b06704ea30983cad8bdd81370/botocore-1.40.2-py3-none-any.whl", hash = "sha256:a31e6269af05498f8dc1c7f2b3f34448a0f16c79a8601c0389ecddab51b2c2ab", size = 13944886, upload-time = "2025-08-04T19:31:37.027Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bump2version"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/29/2a/688aca6eeebfe8941235be53f4da780c6edee05dbbea5d7abaa3aab6fad2/bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6", size = 36236, upload-time = "2020-10-07T18:38:40.119Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/e3/fa60c47d7c344533142eb3af0b73234ef8ea3fb2da742ab976b947e717df/bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410", size = 22030, upload-time = "2020-10-07T18:38:38.148Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "5.5.2"
|
||||
|
||||
4
web/package-lock.json
generated
4
web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/web",
|
||||
"version": "0.0.0",
|
||||
"version": "2025.6.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/web",
|
||||
"version": "0.0.0",
|
||||
"version": "2025.6.4",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"./packages/*"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/web",
|
||||
"version": "0.0.0",
|
||||
"version": "2025.6.4",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -41,7 +41,7 @@ export function readGitBuildHash() {
|
||||
/**
|
||||
* Reads the build identifier for the current environment.
|
||||
*
|
||||
* This must match the behavior defined in authentik's server-side `get_full_version` function.
|
||||
* This must match the behavior defined in authentik's server-side `authentik_full_version` function.
|
||||
*
|
||||
* @runtime node
|
||||
* @see {@link "authentik\_\_init\_\_.py"}
|
||||
|
||||
Reference in New Issue
Block a user