core: include version in built JS files (#9558) * web: fix esbuild issue with style sheets Getting ESBuild, Lit, and Storybook to all agree on how to read and parse stylesheets is a serious pain. This fix better identifies the value types (instances) being passed from various sources in the repo to the three *different* kinds of style processors we're using (the native one, the polyfill one, and whatever the heck Storybook does internally). Falling back to using older CSS instantiating techniques one era at a time seems to do the trick. It's ugly, but in the face of the aggressive styling we use to avoid Flashes of Unstyled Content (FLoUC), it's the logic with which we're left. In standard mode, the following warning appears on the console when running a Flow: ``` Autofocus processing was blocked because a document already has a focused element. ``` In compatibility mode, the following **error** appears on the console when running a Flow: ``` crawler-inject.js:1106 Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'. at initDomMutationObservers (crawler-inject.js:1106:18) at crawler-inject.js:1114:24 at Array.forEach (<anonymous>) at initDomMutationObservers (crawler-inject.js:1114:10) at crawler-inject.js:1549:1 initDomMutationObservers @ crawler-inject.js:1106 (anonymous) @ crawler-inject.js:1114 initDomMutationObservers @ crawler-inject.js:1114 (anonymous) @ crawler-inject.js:1549 ``` Despite this error, nothing seems to be broken and flows work as anticipated. * core: include version in built JS files * add fallback * include build hash * format * fix stuff why does this even work locally * idk man node * just not use import assertions * web: add no-console, use proper dirname path * web: retarget to use the base package.json file. * web: encode path to root package.json using git This is the most authoritative way of finding the root of the git project. * use full version to match frontend * add fallback for missing .git folder --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Jens L <jens@goauthentik.io> Co-authored-by: Ken Sternberg <ken@goauthentik.io>
This commit is contained in:
![98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com](/assets/img/avatar_default.png)
committed by
GitHub

parent
b6157ecaf1
commit
eef02f2892
@ -17,6 +17,8 @@ optional_value = final
|
|||||||
|
|
||||||
[bumpversion:file:pyproject.toml]
|
[bumpversion:file:pyproject.toml]
|
||||||
|
|
||||||
|
[bumpversion:file:package.json]
|
||||||
|
|
||||||
[bumpversion:file:docker-compose.yml]
|
[bumpversion:file:docker-compose.yml]
|
||||||
|
|
||||||
[bumpversion:file:schema.yml]
|
[bumpversion:file:schema.yml]
|
||||||
|
@ -31,6 +31,7 @@ RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
|
|||||||
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
|
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
|
||||||
npm ci --include=dev
|
npm ci --include=dev
|
||||||
|
|
||||||
|
COPY ./package.json /work
|
||||||
COPY ./web /work/web/
|
COPY ./web /work/web/
|
||||||
COPY ./website /work/website/
|
COPY ./website /work/website/
|
||||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{% extends "base/skeleton.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load authentik_core %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
API Browser - {{ brand.branding_title }}
|
API Browser - {{ brand.branding_title }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{% static 'dist/standalone/api-browser/index.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/standalone/api-browser/index-%v.js" %}
|
||||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
|
||||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
|
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load authentik_core %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
@ -14,8 +15,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
|
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
|
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
|
||||||
<script src="{% static 'dist/poly.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/poly-%v.js" %}
|
||||||
<script src="{% static 'dist/standalone/loading/index.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/standalone/loading/index-%v.js" %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "base/skeleton.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load authentik_core %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{% static 'dist/admin/AdminInterface.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/admin/AdminInterface-%v.js" %}
|
||||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
||||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||||
{% include "base/header_js.html" %}
|
{% include "base/header_js.html" %}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{% extends "base/skeleton.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load authentik_core %}
|
||||||
|
|
||||||
{% block head_before %}
|
{% block head_before %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
@ -17,7 +18,7 @@ window.authentik.flow = {
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{% static 'dist/flow/FlowInterface.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/flow/FlowInterface-%v.js" %}
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--ak-flow-background: url("{{ flow.background_url }}");
|
--ak-flow-background: url("{{ flow.background_url }}");
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "base/skeleton.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load authentik_core %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{% static 'dist/user/UserInterface.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/user/UserInterface-%v.js" %}
|
||||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
|
||||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
|
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
|
||||||
{% include "base/header_js.html" %}
|
{% include "base/header_js.html" %}
|
||||||
|
0
authentik/core/templatetags/__init__.py
Normal file
0
authentik/core/templatetags/__init__.py
Normal file
27
authentik/core/templatetags/authentik_core.py
Normal file
27
authentik/core/templatetags/authentik_core.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"""authentik core tags"""
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django.templatetags.static import static as static_loader
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
from authentik import get_full_version
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag()
|
||||||
|
def versioned_script(path: str) -> str:
|
||||||
|
"""Wrapper around {% static %} tag that supports setting the version"""
|
||||||
|
returned_lines = [
|
||||||
|
(
|
||||||
|
f'<script src="{static_loader(path.replace("%v", get_full_version()))}'
|
||||||
|
'" type="module"></script>'
|
||||||
|
),
|
||||||
|
# Legacy method of loading scripts used as a fallback, without the version in the filename
|
||||||
|
# TODO: Remove after 2024.6 or later
|
||||||
|
(
|
||||||
|
f'<script src="{static_loader(path.replace("-%v", ""))}?'
|
||||||
|
f'version={get_full_version()}" type="module"></script>'
|
||||||
|
),
|
||||||
|
]
|
||||||
|
return mark_safe("".join(returned_lines)) # nosec
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "base/skeleton.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load authentik_core %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{% static 'dist/enterprise/rac/index.js' %}?version={{ version }}" type="module"></script>
|
{% versioned_script "dist/enterprise/rac/index-%v.js" %}
|
||||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
||||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||||
<link rel="icon" href="{{ tenant.branding_favicon }}">
|
<link rel="icon" href="{{ tenant.branding_favicon }}">
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""root settings for authentik"""
|
"""root settings for authentik"""
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -10,7 +9,7 @@ from celery.schedules import crontab
|
|||||||
from django.conf import ImproperlyConfigured
|
from django.conf import ImproperlyConfigured
|
||||||
from sentry_sdk import set_tag
|
from sentry_sdk import set_tag
|
||||||
|
|
||||||
from authentik import ENV_GIT_HASH_KEY, __version__
|
from authentik import __version__
|
||||||
from authentik.lib.config import CONFIG, redis_url
|
from authentik.lib.config import CONFIG, redis_url
|
||||||
from authentik.lib.logging import get_logger_config, structlog_configure
|
from authentik.lib.logging import get_logger_config, structlog_configure
|
||||||
from authentik.lib.sentry import sentry_init
|
from authentik.lib.sentry import sentry_init
|
||||||
@ -511,7 +510,6 @@ def _update_settings(app_path: str):
|
|||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
CELERY["task_always_eager"] = True
|
CELERY["task_always_eager"] = True
|
||||||
os.environ[ENV_GIT_HASH_KEY] = "dev"
|
|
||||||
REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append(
|
REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append(
|
||||||
"rest_framework.renderers.BrowsableAPIRenderer"
|
"rest_framework.renderers.BrowsableAPIRenderer"
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "1.0.0",
|
"version": "2024.4.2",
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# Stage 1: Build website
|
# Stage 1: Build web
|
||||||
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
|
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
WORKDIR /static
|
WORKDIR /static
|
||||||
|
|
||||||
|
COPY package.json /
|
||||||
COPY web/package.json .
|
COPY web/package.json .
|
||||||
COPY web/package-lock.json .
|
COPY web/package-lock.json .
|
||||||
RUN --mount=type=bind,target=/static/package.json,src=./web/package.json \
|
RUN --mount=type=bind,target=/static/package.json,src=./web/package.json \
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { execFileSync } from "child_process";
|
||||||
import * as chokidar from "chokidar";
|
import * as chokidar from "chokidar";
|
||||||
import esbuild from "esbuild";
|
import esbuild from "esbuild";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@ -9,12 +10,25 @@ import { fileURLToPath } from "url";
|
|||||||
|
|
||||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||||
|
|
||||||
|
let authentikProjectRoot = __dirname + "../";
|
||||||
|
try {
|
||||||
|
// Use the package.json file in the root folder, as it has the current version information.
|
||||||
|
authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
||||||
|
encoding: "utf8",
|
||||||
|
}).replace("\n", "");
|
||||||
|
} catch (exc) {
|
||||||
|
// We probably don't have a .git folder, which could happen in container builds
|
||||||
|
}
|
||||||
|
const rootPackage = JSON.parse(fs.readFileSync(path.join(authentikProjectRoot, "./package.json")));
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const isProdBuild = process.env.NODE_ENV === "production";
|
const isProdBuild = process.env.NODE_ENV === "production";
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const apiBasePath = process.env.AK_API_BASE_PATH || "";
|
const apiBasePath = process.env.AK_API_BASE_PATH || "";
|
||||||
|
|
||||||
|
const envGitHashKey = "GIT_BUILD_HASH";
|
||||||
|
|
||||||
const definitions = {
|
const definitions = {
|
||||||
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
|
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
|
||||||
"process.env.CWD": JSON.stringify(cwd()),
|
"process.env.CWD": JSON.stringify(cwd()),
|
||||||
@ -80,8 +94,17 @@ const baseArgs = {
|
|||||||
format: "esm",
|
format: "esm",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getVersion() {
|
||||||
|
let version = rootPackage.version;
|
||||||
|
if (process.env[envGitHashKey]) {
|
||||||
|
version = `${version}.${process.env[envGitHashKey]}`;
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
async function buildOneSource(source, dest) {
|
async function buildOneSource(source, dest) {
|
||||||
const DIST = path.join(__dirname, "./dist", dest);
|
const DIST = path.join(__dirname, "./dist", dest);
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
|
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -89,13 +112,13 @@ async function buildOneSource(source, dest) {
|
|||||||
await esbuild.build({
|
await esbuild.build({
|
||||||
...baseArgs,
|
...baseArgs,
|
||||||
entryPoints: [`./src/${source}`],
|
entryPoints: [`./src/${source}`],
|
||||||
|
entryNames: `[dir]/[name]-${getVersion()}`,
|
||||||
outdir: DIST,
|
outdir: DIST,
|
||||||
});
|
});
|
||||||
const end = Date.now();
|
const end = Date.now();
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(
|
console.log(
|
||||||
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${
|
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${Date.now() - start}ms`,
|
||||||
Date.now() - start
|
|
||||||
}ms`,
|
|
||||||
);
|
);
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
|
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
|
||||||
@ -112,12 +135,14 @@ function debouncedBuild() {
|
|||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
timeoutId = setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.clear();
|
console.clear();
|
||||||
buildAuthentik(interfaces);
|
buildAuthentik(interfaces);
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
|
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Build the authentikUI
|
console.log(`Build the authentikUI
|
||||||
|
|
||||||
options:
|
options:
|
||||||
@ -129,6 +154,7 @@ options:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) {
|
if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log("Watching ./src for changes");
|
console.log("Watching ./src for changes");
|
||||||
chokidar.watch("./src").on("all", (event, path) => {
|
chokidar.watch("./src").on("all", (event, path) => {
|
||||||
if (!["add", "change", "unlink"].includes(event)) {
|
if (!["add", "change", "unlink"].includes(event)) {
|
||||||
|
Reference in New Issue
Block a user