Compare commits
2 Commits
main
...
openapi-ge
Author | SHA1 | Date | |
---|---|---|---|
b8c96c88f5 | |||
16019b8585 |
94
Makefile
94
Makefile
@ -1,6 +1,7 @@
|
|||||||
.PHONY: gen dev-reset all clean test web website
|
.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)
|
PWD = $(shell pwd)
|
||||||
UID = $(shell id -u)
|
UID = $(shell id -u)
|
||||||
GID = $(shell id -g)
|
GID = $(shell id -g)
|
||||||
@ -8,9 +9,9 @@ NPM_VERSION = $(shell python -m scripts.generate_semver)
|
|||||||
PY_SOURCES = authentik tests scripts lifecycle .github
|
PY_SOURCES = authentik tests scripts lifecycle .github
|
||||||
DOCKER_IMAGE ?= "authentik:test"
|
DOCKER_IMAGE ?= "authentik:test"
|
||||||
|
|
||||||
GEN_API_TS = "gen-ts-api"
|
GEN_API_TS = gen-ts-api
|
||||||
GEN_API_PY = "gen-py-api"
|
GEN_API_PY = gen-py-api
|
||||||
GEN_API_GO = "gen-go-api"
|
GEN_API_GO = gen-go-api
|
||||||
|
|
||||||
pg_user := $(shell uv run python -m authentik.lib.config postgresql.user 2>/dev/null)
|
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_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
|
npx prettier --write diff.md
|
||||||
|
|
||||||
gen-clean-ts: ## Remove generated API client for Typescript
|
gen-clean-ts: ## Remove generated API client for Typescript
|
||||||
rm -rf ./${GEN_API_TS}/
|
rm -rf ${PWD}/${GEN_API_TS}/
|
||||||
rm -rf ./web/node_modules/@goauthentik/api/
|
rm -rf ${PWD}/web/node_modules/@goauthentik/api/
|
||||||
|
|
||||||
gen-clean-go: ## Remove generated API client for Go
|
gen-clean-go: ## Remove generated API client for Go
|
||||||
rm -rf ./${GEN_API_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
|
gen-clean-py: ## Remove generated API client for Python
|
||||||
rm -rf ./${GEN_API_PY}/
|
rm -rf ${PWD}/${GEN_API_PY}/
|
||||||
|
|
||||||
gen-clean: gen-clean-ts gen-clean-go gen-clean-py ## Remove generated API clients
|
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
|
gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescript into the authentik UI Application
|
||||||
docker run \
|
./scripts/gen-client-ts.mjs
|
||||||
--rm -v ${PWD}:/local \
|
|
||||||
--user ${UID}:${GID} \
|
npm i --prefix ${GEN_API_TS}
|
||||||
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
|
|
||||||
-i /local/schema.yml \
|
cd ./${GEN_API_TS} && npm link
|
||||||
-g typescript-fetch \
|
cd ./web && npm link @goauthentik/api
|
||||||
-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
|
|
||||||
|
|
||||||
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
|
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
|
||||||
docker run \
|
./scripts/gen-client-py.mjs
|
||||||
--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
|
|
||||||
pip install ./${GEN_API_PY}
|
pip install ./${GEN_API_PY}
|
||||||
|
|
||||||
gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
|
gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
|
||||||
mkdir -p ./${GEN_API_GO} ./${GEN_API_GO}/templates
|
mkdir -p ${PWD}/${GEN_API_GO}
|
||||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./${GEN_API_GO}/config.yaml
|
ifeq ($(wildcard ${PWD}/${GEN_API_GO}/.*),)
|
||||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./${GEN_API_GO}/templates/README.mustache
|
git clone --depth 1 https://github.com/goauthentik/client-go.git ${PWD}/${GEN_API_GO}
|
||||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O ./${GEN_API_GO}/templates/go.mod.mustache
|
else
|
||||||
cp schema.yml ./${GEN_API_GO}/
|
cd ${PWD}/${GEN_API_GO} && git pull
|
||||||
docker run \
|
endif
|
||||||
--rm -v ${PWD}/${GEN_API_GO}:/local \
|
cp ${PWD}/schema.yml ${PWD}/${GEN_API_GO}
|
||||||
--user ${UID}:${GID} \
|
make -C ${PWD}/${GEN_API_GO} build
|
||||||
docker.io/openapitools/openapi-generator-cli:v6.5.0 generate \
|
|
||||||
-i /local/schema.yml \
|
|
||||||
-g go \
|
|
||||||
-o /local/ \
|
|
||||||
-c /local/config.yaml
|
|
||||||
go mod edit -replace goauthentik.io/api/v3=./${GEN_API_GO}
|
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
|
gen-dev-config: ## Generate a local development config file
|
||||||
uv run scripts/generate_config.py
|
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}
|
DOCKER_BUILDKIT=1 docker build . --progress plain --tag ${DOCKER_IMAGE}
|
||||||
|
|
||||||
test-docker:
|
test-docker:
|
||||||
BUILD=true ./scripts/test_docker.sh
|
BUILD=true ${PWD}/scripts/test_docker.sh
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
## CI
|
## CI
|
||||||
@ -264,14 +247,3 @@ ci-ruff: ci--meta-debug
|
|||||||
|
|
||||||
ci-codespell: ci--meta-debug
|
ci-codespell: ci--meta-debug
|
||||||
uv run codespell -s
|
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