Skip to content

Commit e40a104

Browse files
authored
Add maxAgeDays option to contributor-mapping plugin to control contributors.json regeneration (speeds up npm run dev) (#1078)
1 parent 437e0bc commit e40a104

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

astro/astro.config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import markdownOutput from "./src/plugins/markdown-output.js";
2121
import contributorMapping from "./src/plugins/contributor-mapping.js";
2222

2323
// https://astro.build/config
24+
const isDev = import.meta.env.DEV;
25+
2426
export default defineConfig({
2527
site: "https://docs.duendesoftware.com",
2628
trailingSlash: "ignore",
@@ -39,6 +41,7 @@ export default defineConfig({
3941
contributorMapping({
4042
include: ["src/content/docs/**"],
4143
repo: "DuendeSoftware/docs.duendesoftware.com",
44+
maxAgeDays: isDev ? 10 : 0,
4245
}),
4346
starlight({
4447
customCss: ["./src/styles/custom.css"],

astro/src/plugins/contributor-mapping.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { execSync } from "node:child_process";
2-
import { writeFileSync, mkdirSync } from "node:fs";
2+
import { writeFileSync, mkdirSync, statSync } from "node:fs";
33
import { dirname, resolve } from "node:path";
44
import { fileURLToPath } from "node:url";
55
import picomatch from "picomatch";
@@ -19,6 +19,15 @@ export interface ContributorMappingOptions {
1919
* @example "DuendeSoftware/docs.duendesoftware.com"
2020
*/
2121
repo: string;
22+
23+
/**
24+
* Maximum age (in days) of an existing contributors.json before it is
25+
* regenerated. If the file exists and is younger than this, the plugin
26+
* short-circuits and skips the expensive git + API work.
27+
* Set to 0 to always regenerate.
28+
* @default 0
29+
*/
30+
maxAgeDays?: number;
2231
}
2332

2433
/**
@@ -36,13 +45,13 @@ export interface ContributorMappingOptions {
3645
export default function contributorMapping(
3746
options: ContributorMappingOptions
3847
): AstroIntegration {
39-
const { include, repo } = options;
48+
const { include, repo, maxAgeDays = 0 } = options;
4049

4150
return {
4251
name: "contributor-mapping",
4352
hooks: {
4453
"astro:config:setup": async ({ logger }) => {
45-
await generateContributors(include, repo, logger);
54+
await generateContributors(include, repo, maxAgeDays, logger);
4655
},
4756
},
4857
};
@@ -384,8 +393,26 @@ function buildPerFileContributors(
384393
async function generateContributors(
385394
include: string[],
386395
repo: string,
396+
maxAgeDays: number,
387397
logger: Logger
388398
) {
399+
// Short-circuit if the mapping file is fresh enough
400+
if (maxAgeDays > 0) {
401+
try {
402+
const stat = statSync(outPath);
403+
const ageDays =
404+
(Date.now() - stat.mtimeMs) / (1000 * 60 * 60 * 24);
405+
if (ageDays < maxAgeDays) {
406+
logger.info(
407+
`contributors.json is ${ageDays.toFixed(1)} days old (< ${maxAgeDays}) — skipping regeneration`
408+
);
409+
return;
410+
}
411+
} catch {
412+
// File doesn't exist yet — continue to generate
413+
}
414+
}
415+
389416
const gitPrefix = getGitPrefix();
390417
const isMatch = picomatch(include);
391418

0 commit comments

Comments
 (0)