Files
team/docs/site/docusaurus.config.ts
55055ca2f3 ci: add docs PR preview workflows (#37440)
* ci: add docs PR preview workflows (P10)

Adds preview builds for PRs touching docs/** or api/**, deployed to the
existing mattermost-docs-preview-pulls S3 bucket under a repo-scoped
mattermost/pr-<N>/ prefix so they don't collide with mattermost/docs's
own previews of the same bucket. Fork PRs are handled via a manual
workflow_dispatch since they can't access secrets; previews are cleaned
up automatically on PR close for both same-repo and fork PRs.

* fix: use PR author for docs preview TRIGGERING_ACTOR

pull_request.head.user.login is the owner of the head repo/branch, not
the PR author -- for same-repo PRs (head repo == base repo) this
resolves to the org name instead of the contributor who opened the PR.
pull_request.user.login is always the actual PR author.

* docs: reword docs preview PR comment

* fix: harden docs preview workflows

- docs-preview-fork: add explicit permissions (statuses/pull-requests
  write, contents read) instead of relying on default token scope.
- docs-preview-template: validate PR_NUMBER is digits-only and quote
  the S3 destination before use in the upload step, guarding against
  script injection via the fork dispatch's free-text input.
- docs-preview-template: add a per-PR concurrency group so an older,
  slower build can't overwrite a newer upload.
- docs-preview/docs-preview-fork: replace secrets: inherit with an
  explicit secrets mapping, and declare the secrets contract on the
  reusable template, so only the two AWS preview credentials are
  passed instead of every repo/org secret.

* fix: align docs preview build/permissions with docs-ci, drop 3rd-party comment action

- docs-preview-template: add Set up Go (api/server/go.mod), matching
  docs-ci -- make -C api build shells out to `go run .` for code
  sample extraction and needs a pinned toolchain, not whatever happens
  to be preinstalled on the runner.
- docs-preview-template: drop the explicit "Build OpenAPI spec" step;
  npm run build's prebuild lifecycle script already runs
  make -C api build, so it was running twice.
- docs-preview-template: replace peter-evans/create-or-update-comment
  with plain `gh pr comment`, dropping a third-party action pin;
  behavior is unchanged (posts a new comment every run).
- docs-preview: add explicit permissions (contents: read,
  pull-requests: write) so the reusable workflow's requested
  pull-requests: write isn't silently downgraded by a restrictive
  default token policy.

* fix: use gh pr comment in docs-preview-cleanup, drop 3rd-party action

Same swap already made in docs-preview-template.yml -- gh is
preinstalled on the runner, so this drops another third-party action
pin. Also quotes the S3 URI via env vars for consistency with the
template's upload step.

* fix: replace pull_request_target with pull_request in docs-preview-cleanup

zizmor flags pull_request_target as a dangerous trigger by default.
Switch to plain pull_request, guarded to skip fork PRs (which don't
get secrets on this event) -- fork preview cleanup will be handled by
a separate scheduled sweep instead. Also fixes a stray '=' character
that had crept into the file.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-13 15:54:27 +03:00

257 lines
8.1 KiB
TypeScript

import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
// Active redirects (legacy Sphinx URLs → migrated MDX paths). Regenerated
// by `node docs-site/scripts/gen-active-redirects.mjs` after content
// changes; only entries whose target exists end up here.
import activeRedirects from './sidebars/active-redirects.json';
// Multi-instance docs setup with three top-level navigations:
// / → Documentation (admin / end-user) sources: ../docs
// /developers → Developers (contribute / integrate) sources: ../develop
// /api → API Reference (OpenAPI-generated) sources: ../api
// See PLAN.md §3.1 for the IA, §3.2 for design tokens.
// Docusaurus's Algolia schema rejects an empty `appId`/`apiKey`, so the
// block is only included when both are set. Without credentials the search
// bar is simply omitted (rather than rendered as an inert element), which
// keeps local and CI builds green.
const algoliaAppId = process.env.ALGOLIA_APP_ID;
const algoliaApiKey = process.env.ALGOLIA_SEARCH_API_KEY;
const algoliaThemeConfig =
algoliaAppId && algoliaApiKey
? {
algolia: {
appId: algoliaAppId,
apiKey: algoliaApiKey,
indexName: 'mattermost-docs',
contextualSearch: true,
searchPagePath: 'search',
},
}
: {};
const config: Config = {
title: 'Mattermost Documentation',
tagline: 'Mission in Motion',
favicon: 'img/brand/icon-denim.svg',
future: {
v4: true,
},
url: 'https://docs.mattermost.com',
baseUrl: process.env.BASE_URL ?? '/',
trailingSlash: false,
organizationName: 'mattermost',
projectName: 'mattermost',
// Broken-link / broken-image policy. During the Phase 4 (developer docs)
// and Phase 5 (main docs) migrations, content references images and
// anchors that haven't been migrated yet — `warn` keeps the build green
// while the unconverted set shows up as warnings we can grep for.
// Tighten to `throw` after each migration phase completes.
onBrokenLinks: 'warn',
markdown: {
hooks: {
onBrokenMarkdownLinks: 'warn',
onBrokenMarkdownImages: 'warn',
},
},
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
// Google Fonts: Inter (body) + Archivo Black (headings, free Trade Gothic Heavy fallback).
// Replace with Adobe Fonts kit once Trade Gothic Next licensing is confirmed
// — see PLAN.md §12 open items.
stylesheets: [
{
href: 'https://fonts.googleapis.com/css2?family=Archivo+Black&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap',
type: 'text/css',
},
],
headTags: [
{tagName: 'link', attributes: {rel: 'preconnect', href: 'https://fonts.googleapis.com'}},
{tagName: 'link', attributes: {rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: 'anonymous'}},
],
// Use the classic preset for the default Documentation instance.
// Developers and API are added as separate plugin instances below
// to give each its own routeBasePath and sidebar.
presets: [
[
'classic',
{
docs: {
id: 'documentation',
path: '../main',
routeBasePath: '/',
sidebarPath: './sidebars/documentation.ts',
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/main/',
},
blog: false,
theme: {
customCss: ['./src/css/tokens.css', './src/css/custom.css'],
},
} satisfies Preset.Options,
],
],
plugins: [
[
'@docusaurus/plugin-content-docs',
{
id: 'developers',
path: '../develop',
routeBasePath: '/developers',
sidebarPath: './sidebars/developers.ts',
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/develop/',
},
],
[
'@docusaurus/plugin-content-docs',
{
id: 'api',
path: '../api',
routeBasePath: '/api',
sidebarPath: './sidebars/api.ts',
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/api/',
// Required for endpoint pages generated by docusaurus-plugin-openapi-docs.
docItemComponent: '@theme/ApiItem',
},
],
[
'@docusaurus/plugin-client-redirects',
{
// Legacy URL → migrated MDX path. Pre-filtered to entries whose
// target exists, so the build never breaks on a missing target.
redirects: activeRedirects.redirects,
},
],
// Generates API reference pages from the OpenAPI bundle produced by
// build-openapi.mjs
[
'docusaurus-plugin-openapi-docs',
{
id: 'api-generator',
docsPluginId: 'api',
config: {
mattermost: {
specPath: 'openapi/mattermost-openapi-v4.yaml',
outputDir: '../api/reference',
sidebarOptions: {
groupPathsBy: 'tag',
categoryLinkSource: 'tag',
},
},
},
},
],
],
// Theme for the API endpoint pages (parameter tables, request/response
// schemas, code-sample picker). Layered on the classic preset theme.
themes: ['docusaurus-theme-openapi-docs'],
themeConfig: {
image: 'img/brand/logo-horizontal-denim.svg',
colorMode: {
defaultMode: 'light',
respectPrefersColorScheme: true,
},
navbar: {
title: '',
logo: {
alt: 'Mattermost',
// Navbar is denim in both light and dark mode, so white logo always.
src: 'img/brand/logo-horizontal-white.svg',
srcDark: 'img/brand/logo-horizontal-white.svg',
},
items: [
{
type: 'docSidebar',
docsPluginId: 'documentation',
sidebarId: 'documentation',
position: 'left',
label: 'Documentation',
},
{
type: 'docSidebar',
docsPluginId: 'developers',
sidebarId: 'developers',
position: 'left',
label: 'Developers',
},
{
type: 'docSidebar',
docsPluginId: 'api',
sidebarId: 'api',
position: 'left',
label: 'API',
},
{
href: 'https://github.com/mattermost/mattermost',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
style: 'dark',
logo: {
alt: 'Mattermost — Mission in Motion',
src: 'img/brand/logo-horizontal-white.svg',
width: 180,
},
links: [
{
title: 'Documentation',
items: [
{label: 'Product Overview', to: '/'},
{label: 'Deployment Guide', to: '/'},
{label: 'Administration Guide', to: '/'},
],
},
{
title: 'Developers',
items: [
{label: 'Contribute', to: '/developers'},
{label: 'Integrate & Extend', to: '/developers'},
{label: 'API Reference', to: '/api'},
],
},
{
title: 'Community',
items: [
{label: 'GitHub', href: 'https://github.com/mattermost/mattermost'},
{label: 'Forum', href: 'https://forum.mattermost.com/'},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} Mattermost, Inc. All rights reserved.`,
},
...algoliaThemeConfig,
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
additionalLanguages: ['bash', 'powershell', 'json', 'yaml', 'go', 'python'],
},
// Code-sample tabs shown on every endpoint page, in display order.
// First entry is the default selected tab (curl).
languageTabs: [
{highlight: 'bash', language: 'curl', logoClass: 'curl'},
{highlight: 'powershell', language: 'powershell', logoClass: 'powershell'},
{highlight: 'python', language: 'python', logoClass: 'python'},
{highlight: 'javascript', language: 'nodejs', logoClass: 'nodejs', label: 'Node'},
{highlight: 'go', language: 'go', logoClass: 'go'},
],
} satisfies Preset.ThemeConfig,
};
export default config;