Compare commits
2 Commits
tests/e2e/
...
openapi-ge
Author | SHA1 | Date | |
---|---|---|---|
b8c96c88f5 | |||
16019b8585 |
94
Makefile
94
Makefile
@ -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
19
scripts/gen-client-py.mjs
Executable 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
22
scripts/gen-client-ts.mjs
Executable 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}`],
|
||||
});
|
@ -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}")
|
100
scripts/openapi-generator.mjs
Normal file
100
scripts/openapi-generator.mjs
Normal 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}`);
|
||||
}
|
Reference in New Issue
Block a user