Compare commits

...

2 Commits

Author SHA1 Message Date
b8c96c88f5 Update Makefile
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
2025-05-26 16:55:39 +02:00
16019b8585 core: Prep OpenAPI generators for NPM Workspaces. 2025-05-03 01:57:12 +02:00
5 changed files with 174 additions and 76 deletions

View File

@ -1,6 +1,7 @@
.PHONY: gen dev-reset all clean test web website
.SHELLFLAGS += ${SHELLFLAGS} -e
SHELL := /usr/bin/env bash
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
PWD = $(shell pwd)
UID = $(shell id -u)
GID = $(shell id -g)
@ -8,9 +9,9 @@ NPM_VERSION = $(shell python -m scripts.generate_semver)
PY_SOURCES = authentik tests scripts lifecycle .github
DOCKER_IMAGE ?= "authentik:test"
GEN_API_TS = "gen-ts-api"
GEN_API_PY = "gen-py-api"
GEN_API_GO = "gen-go-api"
GEN_API_TS = gen-ts-api
GEN_API_PY = gen-py-api
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)
@ -117,63 +118,45 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
npx prettier --write diff.md
gen-clean-ts: ## Remove generated API client for Typescript
rm -rf ./${GEN_API_TS}/
rm -rf ./web/node_modules/@goauthentik/api/
rm -rf ${PWD}/${GEN_API_TS}/
rm -rf ${PWD}/web/node_modules/@goauthentik/api/
gen-clean-go: ## Remove generated API client for Go
rm -rf ./${GEN_API_GO}/
gen-clean-go: ## Remove generated API client for Go
mkdir -p ${PWD}/${GEN_API_GO}
ifneq ($(wildcard ${PWD}/${GEN_API_GO}/.*),)
make -C ${PWD}/${GEN_API_GO} clean
else
rm -rf ${PWD}/${GEN_API_GO}
endif
gen-clean-py: ## Remove generated API client for Python
rm -rf ./${GEN_API_PY}/
gen-clean-py: ## Remove generated API client for Python
rm -rf ${PWD}/${GEN_API_PY}/
gen-clean: gen-clean-ts gen-clean-go gen-clean-py ## Remove generated API clients
gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescript into the authentik UI Application
docker run \
--rm -v ${PWD}:/local \
--user ${UID}:${GID} \
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
-i /local/schema.yml \
-g typescript-fetch \
-o /local/${GEN_API_TS} \
-c /local/scripts/api-ts-config.yaml \
--additional-properties=npmVersion=${NPM_VERSION} \
--git-repo-id authentik \
--git-user-id goauthentik
mkdir -p web/node_modules/@goauthentik/api
cd ./${GEN_API_TS} && npm i
\cp -rf ./${GEN_API_TS}/* web/node_modules/@goauthentik/api
./scripts/gen-client-ts.mjs
npm i --prefix ${GEN_API_TS}
cd ./${GEN_API_TS} && npm link
cd ./web && npm link @goauthentik/api
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
docker run \
--rm -v ${PWD}:/local \
--user ${UID}:${GID} \
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
-i /local/schema.yml \
-g python \
-o /local/${GEN_API_PY} \
-c /local/scripts/api-py-config.yaml \
--additional-properties=packageVersion=${NPM_VERSION} \
--git-repo-id authentik \
--git-user-id goauthentik
./scripts/gen-client-py.mjs
pip install ./${GEN_API_PY}
gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
mkdir -p ./${GEN_API_GO} ./${GEN_API_GO}/templates
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./${GEN_API_GO}/config.yaml
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./${GEN_API_GO}/templates/README.mustache
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O ./${GEN_API_GO}/templates/go.mod.mustache
cp schema.yml ./${GEN_API_GO}/
docker run \
--rm -v ${PWD}/${GEN_API_GO}:/local \
--user ${UID}:${GID} \
docker.io/openapitools/openapi-generator-cli:v6.5.0 generate \
-i /local/schema.yml \
-g go \
-o /local/ \
-c /local/config.yaml
mkdir -p ${PWD}/${GEN_API_GO}
ifeq ($(wildcard ${PWD}/${GEN_API_GO}/.*),)
git clone --depth 1 https://github.com/goauthentik/client-go.git ${PWD}/${GEN_API_GO}
else
cd ${PWD}/${GEN_API_GO} && git pull
endif
cp ${PWD}/schema.yml ${PWD}/${GEN_API_GO}
make -C ${PWD}/${GEN_API_GO} build
go mod edit -replace goauthentik.io/api/v3=./${GEN_API_GO}
rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/
gen-dev-config: ## Generate a local development config file
uv run scripts/generate_config.py
@ -244,7 +227,7 @@ docker: ## Build a docker image of the current source tree
DOCKER_BUILDKIT=1 docker build . --progress plain --tag ${DOCKER_IMAGE}
test-docker:
BUILD=true ./scripts/test_docker.sh
BUILD=true ${PWD}/scripts/test_docker.sh
#########################
## CI
@ -264,14 +247,3 @@ ci-ruff: ci--meta-debug
ci-codespell: ci--meta-debug
uv run codespell -s
ci-bandit: ci--meta-debug
uv run bandit -r $(PY_SOURCES)
ci-pending-migrations: ci--meta-debug
uv run ak makemigrations --check
ci-test: ci--meta-debug
uv run coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik
uv run coverage report
uv run coverage xml

19
scripts/gen-client-py.mjs Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env node
/**
* @file Generates the authentik API client for Python.
*/
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { generateOpenAPIClient } from "./openapi-generator.mjs";
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDirectory, "..");
generateOpenAPIClient({
cwd: repoRoot,
outputDirectory: resolve(repoRoot, "gen-py-api"),
generatorName: "python",
config: resolve(scriptDirectory, "api-py-config.yaml"),
});

22
scripts/gen-client-ts.mjs Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env node
/**
* @file Generates the authentik API client for TypeScript.
*/
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import PackageJSON from "../package.json" with { type: "json" };
import { generateOpenAPIClient } from "./openapi-generator.mjs";
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDirectory, "..");
const npmVersion = [PackageJSON.version, Date.now()].join("-");
generateOpenAPIClient({
cwd: repoRoot,
outputDirectory: resolve(repoRoot, "gen-ts-api"),
generatorName: "typescript-fetch",
config: resolve(scriptDirectory, "api-ts-config.yaml"),
commandArgs: [`--additional-properties=npmVersion=${npmVersion}`],
});

View File

@ -1,15 +0,0 @@
#!/usr/bin/env python3
"""
Generates a Semantic Versioning identifier, suffixed with a timestamp.
"""
from time import time
from authentik import __version__ as package_version
"""
See: https://semver.org/#spec-item-9 (Pre-release spec)
"""
pre_release_timestamp = int(time())
print(f"{package_version}-{pre_release_timestamp}")

View File

@ -0,0 +1,100 @@
/**
* @file OpenAPI generator utilities.
*/
import { execFileSync, execSync } from "node:child_process";
import { existsSync, rmSync } from "node:fs";
import { userInfo } from "node:os";
import { join, relative, resolve } from "node:path";
const OPENAPI_CONTAINER_IMAGE = "docker.io/openapitools/openapi-generator-cli:v7.11.0";
/**
* Checks if a command exists in the PATH.
*
* @template {string} T
* @param {T} command
* @returns {T | null}
*/
function commandExists(command) {
if (execSync(`command -v ${command} || echo ''`).toString().trim()) {
return command;
}
return null;
}
/**
* Given a path relative to the current working directory,
* resolves it to a path relative to the local volume.
*
* @param {string} cwd
* @param {...string} pathSegments
*/
function resolveLocalPath(cwd, ...pathSegments) {
return resolve("/local", relative(cwd, join(...pathSegments)));
}
/**
* @typedef {object} GenerateOpenAPIClientOptions
* @property {string} cwd The working directory to run the generator in.
* @property {string} outputDirectory The path to the output directory.
* @property {string} generatorName The name of the generator.
* @property {string} config The path to the generator configuration.
* @property {string} [inputSpec] The path to the OpenAPI specification.
* @property {Array<string | string[]>} [commandArgs] Additional arguments to pass to the generator.
*/
/**
* Generates an OpenAPI client using the `openapi-generator-cli` Docker image.
*
* @param {GenerateOpenAPIClientOptions} options
* @see {@link https://openapi-generator.tech/docs/usage}
*/
export function generateOpenAPIClient({
cwd,
outputDirectory,
generatorName,
config,
inputSpec = resolve(cwd, "schema.yml"),
commandArgs = [],
}) {
if (existsSync(outputDirectory)) {
console.log(`Removing existing generated API client from ${outputDirectory}`);
rmSync(outputDirectory, { recursive: true, force: true });
}
const containerEngine = commandExists("docker") || commandExists("podman");
if (!containerEngine) {
throw new Error("Container engine not found. Is Docker or Podman available in the PATH?");
}
const { gid, uid } = userInfo();
const args = [
"run",
[`--user`, `${uid}:${gid}`],
`--rm`,
[`-v`, `${cwd}:/local`],
OPENAPI_CONTAINER_IMAGE,
"generate",
["--input-spec", resolveLocalPath(cwd, inputSpec)],
[`--generator-name`, generatorName],
["--config", resolveLocalPath(cwd, config)],
["--git-repo-id", `authentik`],
["--git-user-id", `goauthentik`],
["--output", resolveLocalPath(cwd, outputDirectory)],
...commandArgs,
];
console.debug(`Running command: ${containerEngine}`, args);
execFileSync(containerEngine, args.flat(), {
cwd,
stdio: "inherit",
});
console.log(`Generated API client to ${outputDirectory}`);
}