From 574a2a33de3996cb1d411f0388f1152f81454635 Mon Sep 17 00:00:00 2001 From: Paul Gottschling Date: Mon, 9 Dec 2024 11:57:23 -0500 Subject: [PATCH] Change versioning logic (#39) Reflect the fact that the latest major Teleport release is not available to Teleport Enterprise Cloud customers until a few weeks after the release date. Configure versioning for v17. Use an `isDefault` key in `config.json` to specify the default version. This way, we can specify the default version explicitly using config.json instead of using the potentially confusing `current` and `latest` fields. Configure git modules. Remove 14.x and add 18.x. Remove the "normalize" function, which is dead code. Remove the latest version suggestion link from the version banner. It's not always accurate (e.g., if we have different versions for Cloud and Self-Hosted), and users can find the dropdown anyway. Adjust the version banner text if a docs version is only available for self-hosted Teleport clusters. --- .gitmodules | 9 ++- config.json | 12 ++-- content/14.x | 1 - content/18.x | 1 + server/config-site.ts | 56 +++++-------------- src/theme/DocVersionBanner/index.tsx | 84 +++++++++++----------------- 6 files changed, 61 insertions(+), 102 deletions(-) delete mode 160000 content/14.x create mode 160000 content/18.x diff --git a/.gitmodules b/.gitmodules index 4031ad0..63f616a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "content/14.x"] - path = content/14.x - url = https://github.com/gravitational/teleport/ - branch = branch/v14 [submodule "content/15.x"] path = content/15.x url = https://github.com/gravitational/teleport/ @@ -13,4 +9,7 @@ [submodule "content/17.x"] path = content/17.x url = https://github.com/gravitational/teleport/ - branch = master + branch = branch/v17 +[submodule "content/18.x"] + path = content/18.x + url = https://github.com/gravitational/teleport diff --git a/config.json b/config.json index f07e124..f13247b 100644 --- a/config.json +++ b/config.json @@ -62,7 +62,8 @@ }, { "name": "14.x", - "branch": "branch/v14" + "branch": "branch/v14", + "deprecated": true }, { "name": "15.x", @@ -71,12 +72,15 @@ { "name": "16.x", "branch": "branch/v16", - "latest": true + "isDefault": true }, { "name": "17.x", - "branch": "master", - "current": true + "branch": "branch/v17" + }, + { + "name": "18.x", + "branch": "master" } ] } diff --git a/content/14.x b/content/14.x deleted file mode 160000 index 5aed8c0..0000000 --- a/content/14.x +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5aed8c06e4e8eb6f894d44d0ccb3c447488e0674 diff --git a/content/18.x b/content/18.x new file mode 160000 index 0000000..925b74e --- /dev/null +++ b/content/18.x @@ -0,0 +1 @@ +Subproject commit 925b74ec7c7af86a1b4bbeb4d311486d9583be39 diff --git a/server/config-site.ts b/server/config-site.ts index 5110ca3..97fda62 100644 --- a/server/config-site.ts +++ b/server/config-site.ts @@ -12,15 +12,13 @@ interface Config { versions: { name: string; branch: string; - latest?: true; - current?: true; + isDefault?: boolean; deprecated?: boolean; }[]; } interface NormalizedConfig { - latest: string; - current: string; + isDefault: string; versions: string[]; branches: Record; } @@ -47,8 +45,7 @@ const validator = ajv.compile({ properties: { name: { type: "string" }, branch: { type: "string" }, - latest: { type: "boolean", nullable: true }, - current: { type: "boolean", nullable: true }, + isDefault: { type: "boolean", nullable: true }, deprecated: { type: "boolean", nullable: true }, }, additionalProperties: false, @@ -61,32 +58,6 @@ const validator = ajv.compile({ required: ["versions"], }); -/* - * Config format for storing data and config format for using data not nescessary the same. - * Storing version data as a singe array is convenient, but for usage, having separate - * "latest", "versions" and "branches" fileds are easier, so we transform them here. - */ - -export const normalize = ({ versions }: Config): NormalizedConfig => { - const supportedVersions = versions.filter((version) => !version.deprecated); - const result: NormalizedConfig = { - latest: ( - supportedVersions.find(({ latest }) => latest === true) || - versions[supportedVersions.length - 1] - ).name, - current: ( - supportedVersions.find(({ current }) => current === true) || - versions[supportedVersions.length - 1] - ).name, - versions: supportedVersions.map(({ name }) => name), - branches: supportedVersions.reduce((result, { name, branch }) => { - return { ...result, [name]: branch }; - }, {}), - }; - - return result; -}; - /* Load and validate config. */ export const loadConfig = () => { @@ -111,7 +82,7 @@ export const getLatestVersion = () => { const versions = getSupportedVersions(); return ( - versions.find(({ latest }) => latest === true) || + versions.find(({ isDefault }) => isDefault === true) || versions[versions.length - 1] ).name; }; @@ -122,7 +93,6 @@ export const getCurrentVersion = () => { const versions = getSupportedVersions(); return ( - versions.find(({ current }) => current === true) || versions[versions.length - 1] ).name; }; @@ -135,20 +105,22 @@ export const getDocusaurusConfigVersionOptions = (): Record< > => { const versions = getSupportedVersions(); - return versions.reduce((result, { name, latest, current }) => { - // Use "current" as a name for the current version. This way Docusaurus - // will look for it in the `docs` folder instead of `versioned_docs`. - const versionName = current ? "current" : name; + return versions.reduce((result, { name, isDefault, branch }, idx) => { + // Use "current" as the name for the current version (i.e., the edge + // version), the highest-numbered version in the configuration. This way + // Docusaurus will look for it in the `docs` folder instead of + // `versioned_docs`. + const isCurrent = idx === versions.length - 1; + const versionName = isCurrent ? "current" : name; const versionOptions: VersionOptions = { - // Mark latest version as unreleased. - label: current ? `${name} (unreleased)` : name, + label: isCurrent ? `${name} (unreleased)` : name, // Configure root path for the version. Latest in the root, others in the `ver/XX.x` folder. - path: latest ? "" : `ver/${name}`, + path: isDefault ? "" : `ver/${name}`, }; // Banner will show message for the current version that it is still WIP. - if (current) { + if (isCurrent) { versionOptions.banner = "unreleased"; } diff --git a/src/theme/DocVersionBanner/index.tsx b/src/theme/DocVersionBanner/index.tsx index d385b66..0b2e599 100644 --- a/src/theme/DocVersionBanner/index.tsx +++ b/src/theme/DocVersionBanner/index.tsx @@ -1,7 +1,6 @@ import React, { type ComponentType } from "react"; import clsx from "clsx"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import Link from "@docusaurus/Link"; import Translate from "@docusaurus/Translate"; import { useActivePlugin, @@ -22,22 +21,50 @@ type BannerLabelComponentProps = { versionMetadata: PropVersionMetadata; }; +const unreleasedMessage = + "This documentation is for an unreleased version of Teleport."; +const selfHostedMessage = + "This documentation is for a version of Teleport that is only available for self-hosted clusters."; + function UnreleasedVersionLabel({ siteTitle, versionMetadata, }: BannerLabelComponentProps) { + const { versions, lastVersion } = + useDocusaurusContext().siteConfig.plugins.find((p) => { + return p[0] == "@docusaurus/plugin-content-docs"; + })[1]; + const verToOrder = new Map(); + const vers = Object.keys(versions); + for (let i = 0; i < vers.length; i++) { + verToOrder.set(vers[i], i); + } + + const { version } = useDocsVersion(); + let message: string; + const thisIdx = verToOrder.get(version); + // Set a version banner. Indicate if the version is the edge version or + // only available for self-hosted users. The latter situation happens when + // the latest release is not yet the latest version in the docs. + if ( + verToOrder.get(lastVersion) < thisIdx && + verToOrder.get("current") > thisIdx + ) { + message = selfHostedMessage; + } else { + message = unreleasedMessage; + } + return ( {versionMetadata.label}, }} > - { - "This is unreleased documentation for {siteTitle} {versionLabel} version." - } + {message} ); } @@ -49,13 +76,13 @@ function UnmaintainedVersionLabel({ return ( {versionMetadata.label}, }} > - {"This is documentation for {siteTitle} {versionLabel}."} + {"This is documentation for {siteTitle} {versionLabel}, a previous version of Teleport."} ); } @@ -73,42 +100,6 @@ function BannerLabel(props: BannerLabelComponentProps) { return ; } -function LatestVersionSuggestionLabel({ - versionLabel, - to, - onClick, -}: { - to: string; - onClick: () => void; - versionLabel: string; -}) { - return ( - - - - latest version - - - - ), - }} - > - { - "For up-to-date documentation, see the {latestVersionLink} ({versionLabel})." - } - - ); -} - function DocVersionBannerEnabled({ className, versionMetadata, @@ -145,13 +136,6 @@ function DocVersionBannerEnabled({
-
- savePreferredVersionName(latestVersionSuggestion.name)} - /> -
); }