almost working VCS integration, adding default v1/v2 strategy

This commit is contained in:
sebastien 2025-11-07 19:56:39 +01:00
parent 6bf515d5fc
commit 01e16637e4
9 changed files with 134 additions and 49 deletions

View File

@ -79,7 +79,13 @@ export type VcsConfig = {
/**
* List of pre-built VcsConfig that Docusaurus provides.
*/
export type VcsPreset = 'git-ad-hoc' | 'git-eager' | 'hardcoded';
export type VcsPreset =
| 'git-ad-hoc'
| 'git-eager'
| 'hardcoded'
| 'disabled'
| 'default-v1'
| 'default-v2';
export type FutureConfig = {
/**

View File

@ -128,12 +128,7 @@ export {
type FrontMatterLastUpdate,
} from './lastUpdateUtils';
export {
VcsPresetNames,
getVcsPreset,
getDefaultVcsConfig,
DEFAULT_TEST_VCS_CONFIG,
} from './vcs/vcs';
export {VcsPresetNames, getVcsPreset, DEFAULT_TEST_VCS_CONFIG} from './vcs/vcs';
// Annoying to have to expose that for tests :/
export {VCS_HARDCODED_LAST_UPDATE_INFO} from './vcs/vcsHardcoded';

View File

@ -6,7 +6,7 @@
*/
import _ from 'lodash';
import {getDefaultVcsConfig} from './vcs/vcs';
import {getVcsPreset} from './vcs/vcs';
import type {PluginOptions, VcsConfig} from '@docusaurus/types';
@ -52,7 +52,7 @@ export async function readLastUpdateData(
// This also ensures unit tests keep working without extra setup
// We still want to ensure type safety by requiring the VCS param
// TODO Docusaurus v4: refactor all these Git read APIs
const vcs = vcsParam ?? getDefaultVcsConfig();
const vcs = vcsParam ?? getVcsPreset('default-v1');
const {showLastUpdateAuthor, showLastUpdateTime} = options;

View File

@ -8,12 +8,19 @@
import {VcsHardcoded} from './vcsHardcoded';
import {VcsGitAdHoc} from './vcsGitAdHoc';
import {VscGitEager} from './vcsGitEager';
import {VcsDisabled} from './vcsDisabled';
import {VcsDefaultV1} from './vcsDefaultV1';
import {VcsDefaultV2} from './vcsDefaultV2';
import type {VcsConfig, VcsPreset} from '@docusaurus/types';
const VcsPresets: Record<VcsPreset, VcsConfig> = {
'git-ad-hoc': VcsGitAdHoc,
'git-eager': VscGitEager,
hardcoded: VcsHardcoded,
disabled: VcsDisabled,
'default-v1': VcsDefaultV1,
'default-v2': VcsDefaultV2,
};
export const VcsPresetNames = Object.keys(VcsPresets) as VcsPreset[];
@ -33,32 +40,4 @@ export function getVcsPreset(presetName: VcsPreset): VcsConfig {
}
}
export function getDefaultVcsPresetName(): VcsPreset {
// Escape hatch to override the default VCS preset we use
if (process.env.DOCUSAURUS_VCS) {
return process.env.DOCUSAURUS_VCS as VcsPreset;
}
if (process.env.NODE_ENV === 'production') {
// TODO add feature flag switch for git-eager / git-ad-hoc strategies
// return getVcsPreset('git-ad-hoc');
return 'git-eager';
}
// Return hardcoded values in dev to improve DX
if (process.env.NODE_ENV === 'development') {
return 'hardcoded';
}
// Return hardcoded values in test to make tests simpler and faster
if (process.env.NODE_ENV === 'test') {
return 'hardcoded';
}
return 'git-eager';
}
export function getDefaultVcsConfig(): VcsConfig {
return getVcsPreset(getDefaultVcsPresetName());
}
export const DEFAULT_TEST_VCS_CONFIG: VcsConfig = VcsHardcoded;

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {VcsHardcoded} from './vcsHardcoded';
import {VcsGitAdHoc} from './vcsGitAdHoc';
import type {VcsConfig} from '@docusaurus/types';
function getDynamicStrategy(): VcsConfig {
return process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'test'
? VcsHardcoded
: VcsGitAdHoc;
}
/**
* This VCS implements the historical Git automatic strategy.
* It is only enabled in production mode, using ad-hoc git log commands.
*/
export const VcsDefaultV1: VcsConfig = {
initialize: (...params) => {
return getDynamicStrategy().initialize(...params);
},
getFileCreationInfo: (...params) => {
return getDynamicStrategy().getFileCreationInfo(...params);
},
getFileLastUpdateInfo: (...params) => {
return getDynamicStrategy().getFileLastUpdateInfo(...params);
},
};

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {VcsHardcoded} from './vcsHardcoded';
import {VscGitEager} from './vcsGitEager';
import type {VcsConfig} from '@docusaurus/types';
function getStrategy(): VcsConfig {
return process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'test'
? VcsHardcoded
: VscGitEager;
}
/**
* This VCS implements the new eager Git automatic strategy.
* It is only enabled in production mode, reading the git repository eagerly.
*/
export const VcsDefaultV2: VcsConfig = {
initialize: (...params) => {
return getStrategy().initialize(...params);
},
getFileCreationInfo: (...params) => {
return getStrategy().getFileCreationInfo(...params);
},
getFileLastUpdateInfo: (...params) => {
return getStrategy().getFileLastUpdateInfo(...params);
},
};

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type {VcsConfig} from '@docusaurus/types';
/**
* This VCS implementation always returns null values
*/
export const VcsDisabled: VcsConfig = {
initialize: () => {
// Noop
},
getFileCreationInfo: async (_filePath) => {
return null;
},
getFileLastUpdateInfo: async (_ilePath) => {
return null;
},
};

View File

@ -62,7 +62,6 @@ function createGitVcsConfig(): VcsConfig {
return {
initialize: ({siteDir}) => {
console.trace('git eager init');
// Only pre-init for production builds
getGitFileInfo(siteDir).catch((error) => {
console.error(

View File

@ -6,30 +6,29 @@
*/
import {
DEFAULT_I18N_DIR_NAME,
DEFAULT_PARSE_FRONT_MATTER,
DEFAULT_STATIC_DIR_NAME,
DEFAULT_I18N_DIR_NAME,
getDefaultVcsConfig,
VcsPresetNames,
getVcsPreset,
VcsPresetNames,
} from '@docusaurus/utils';
import {Joi, printWarning} from '@docusaurus/utils-validation';
import {
addTrailingSlash,
addLeadingSlash,
addTrailingSlash,
removeTrailingSlash,
} from '@docusaurus/utils-common';
import logger from '@docusaurus/logger';
import type {
DocusaurusConfig,
FasterConfig,
FutureConfig,
FutureV4Config,
StorageConfig,
DocusaurusConfig,
I18nConfig,
I18nLocaleConfig,
MarkdownConfig,
MarkdownHooks,
I18nLocaleConfig,
StorageConfig,
VcsConfig,
VcsPreset,
} from '@docusaurus/types';
@ -111,9 +110,7 @@ export const DEFAULT_FUTURE_CONFIG: FutureConfig = {
v4: DEFAULT_FUTURE_V4_CONFIG,
experimental_faster: DEFAULT_FASTER_CONFIG,
experimental_storage: DEFAULT_STORAGE_CONFIG,
// Not good, need to be loaded lazily
experimental_vcs: getDefaultVcsConfig(),
experimental_vcs: getVcsPreset('default-v1'),
experimental_router: 'browser',
};
@ -355,12 +352,19 @@ const VCS_CONFIG_SCHEMA = Joi.custom((input) => {
}
return getVcsPreset(presetName);
}
if (typeof input === 'boolean') {
// We return the boolean on purpose
// We'll normalize it to a real VcsConfig later
// This is annoying, but we have to read the future flag to switch to the
// new "default-v2" config
return input;
}
const {error, value} = VCS_CONFIG_OBJECT_SCHEMA.validate(input);
if (error) {
throw error;
}
return value;
}).default(() => getDefaultVcsConfig());
}).default(true);
const FUTURE_CONFIG_SCHEMA = Joi.object<FutureConfig>({
v4: FUTURE_V4_SCHEMA,
@ -530,6 +534,17 @@ Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBroke
config.onBrokenMarkdownLinks = undefined;
}
// We normalize the VCS config when using a boolean value
if (typeof config.future.experimental_vcs === 'boolean') {
// TODO implement future flag for new VCS config default
const isNewVcsConfigEnabled = false;
config.future.experimental_vcs = config.future.experimental_vcs
? isNewVcsConfigEnabled
? getVcsPreset('default-v2')
: getVcsPreset('default-v1')
: getVcsPreset('disabled');
}
if (
config.future.experimental_faster.ssgWorkerThreads &&
!config.future.v4.removeLegacyPostBuildHeadAttribute