@@ -36,7 +36,6 @@ const outputDir = "generated-docs"
3636const APP_ENV = getServerEnv ( ) . APP_ENV as "development" | "production"
3737const currentDocsWorkspace = process . cwd ( )
3838
39- // Derive path of docs relative to repo root; tolerate odd CI/git states
4039let docsRelative = ""
4140try {
4241 docsRelative = run ( "git rev-parse --show-prefix" , { cwd : currentDocsWorkspace } ) . replace ( / \/ ? $ / , "" )
@@ -48,26 +47,25 @@ const allTags = () => run("git tag --list").split("\n").filter(Boolean)
4847
4948function resolveTagsFromSpec ( spec : string ) {
5049 const tags = allTags ( ) . filter ( ( t ) => semver . valid ( t ) )
51- const tokens = spec
52- . split ( "," )
53- . map ( ( t ) => t . trim ( ) )
54- . filter ( Boolean )
50+ const tokens = spec . split ( "," ) . map ( ( t ) => t . trim ( ) ) . filter ( Boolean )
5551 const matched = tags . filter ( ( tag ) =>
5652 tokens . some ( ( token ) => semver . satisfies ( tag , token , { includePrerelease : true } ) ) ,
5753 )
5854 return matched . sort ( semver . rcompare )
5955}
6056
57+ function hasDocsContentDir ( dir : string ) {
58+ return existsSync ( resolve ( dir , contentDir ) )
59+ }
60+
6161function buildDocs ( sourceDir : string , outDir : string ) {
6262 if ( ! existsSync ( sourceDir ) ) throw new Error ( `Docs workspace not found: ${ sourceDir } ` )
63-
6463 const docsContentDir = resolve ( sourceDir , contentDir )
6564 if ( ! existsSync ( docsContentDir ) ) {
6665 throw new Error ( `Docs content directory "${ contentDir } " not found at ${ docsContentDir } ` )
6766 }
6867
6968 resetDir ( outDir )
70-
7169 run ( "pnpm run content-collections:build" , { cwd : sourceDir , inherit : true } )
7270
7371 const ccSrc = resolve ( sourceDir , ".content-collections" )
@@ -76,8 +74,6 @@ function buildDocs(sourceDir: string, outDir: string) {
7674
7775 resetDir ( ccDest )
7876 cpSync ( ccSrc , ccDest , { recursive : true } )
79-
80- // biome-ignore lint/suspicious/noConsole: keep for debugging
8177 console . log ( chalk . green ( `✔ Built docs → ${ ccDest } ` ) )
8278}
8379
@@ -94,6 +90,7 @@ function buildRef(ref: string, labelForOutDir: string) {
9490 try {
9591 const docsWorkspace = docsRelative ? resolve ( worktreePath , docsRelative ) : worktreePath
9692
93+ // Install at worktree ROOT first (monorepo lockfile lives here)
9794 const rootPkg = existsSync ( resolve ( worktreePath , "package.json" ) )
9895 const rootLock = existsSync ( resolve ( worktreePath , "pnpm-lock.yaml" ) )
9996 if ( rootPkg ) {
@@ -103,13 +100,13 @@ function buildRef(ref: string, labelForOutDir: string) {
103100 } )
104101 }
105102
103+ // Only install inside docs/ if it has its own lockfile
106104 const docsPkg = existsSync ( resolve ( docsWorkspace , "package.json" ) )
107105 const docsLock = existsSync ( resolve ( docsWorkspace , "pnpm-lock.yaml" ) )
108106 if ( docsPkg && docsLock ) {
109107 run ( "pnpm install --frozen-lockfile" , { cwd : docsWorkspace , inherit : true } )
110108 }
111109
112-
113110 const outDir = resolve ( outputDir , labelForOutDir )
114111 buildDocs ( docsWorkspace , outDir )
115112 } finally {
@@ -131,15 +128,13 @@ function hasLocalRef(ref: string) {
131128}
132129
133130function buildBranch ( branch : string , labelForOutDir : string ) {
134- // Ensure the remote ref exists locally (for origin/< branch>)
135- run ( `git fetch --tags --prune origin ${ branch } ` , {
131+ run ( `git fetch --tags --prune origin ${ branch } ` , {
132+
136133 cwd : currentDocsWorkspace ,
137134 inherit : true ,
138135 } )
139-
140136 const localRef = `refs/heads/${ branch } `
141137 const targetRef = hasLocalRef ( localRef ) ? localRef : `origin/${ branch } `
142-
143138 return buildRef ( targetRef , labelForOutDir )
144139}
145140
@@ -154,26 +149,22 @@ function buildSpecifiedTags(spec: string, envLabel: "dev" | "prod"): string[] {
154149 `No tags matched spec "${ spec } ". Nothing to build in ${ envLabel === "dev" ? "development" : "production" } .` ,
155150 )
156151 }
157- // biome-ignore lint/suspicious/noConsole: keep for debugging
158- console . log ( chalk . cyan ( `(${ envLabel } ) Building docs for tags: ${ tags . join ( ", " ) } ` ) )
152+ console . log ( chalk . cyan ( `(${ envLabel } ) Building docs for tags: ${ tags . join ( ", " ) } ` ) )
159153 for ( const tag of tags ) buildTag ( tag )
160154 return tags
161155}
162156
163157function detectDefaultBranch ( ) : string {
164158 try {
165- // e.g. 'refs/remotes/origin/main'
166- const ref = run ( "git symbolic-ref --quiet refs/remotes/origin/HEAD" )
159+ const ref = run ( "git symbolic-ref --quiet refs/remotes/origin/HEAD" ) // e.g. 'refs/remotes/origin/main'
167160 const parts = ref . split ( "/" )
168161 return parts [ parts . length - 1 ] || "main"
169162 } catch {
170163 try {
171164 const info = run ( "git remote show origin" )
172165 const m = info . match ( / H E A D b r a n c h : \s * ( \S + ) / )
173166 if ( m ?. [ 1 ] ) return m [ 1 ] . trim ( )
174- } catch {
175- // ignore
176- }
167+ } catch { }
177168 }
178169 return "main"
179170}
@@ -183,11 +174,10 @@ function detectDefaultBranch(): string {
183174 args : process . argv . slice ( 2 ) ,
184175 options : {
185176 versions : { type : "string" } , // optional
186- branch : { type : "string" } , // optional (CLI override)
177+ branch : { type : "string" } , // optional (CLI override)
187178 } ,
188179 } )
189180
190- // Resolve branch precedence: CLI > ENV > auto-detect
191181 const branch =
192182 ( values . branch as string | undefined ) ?. trim ( ) ||
193183 process . env . DOCS_BRANCH ?. trim ( ) ||
@@ -197,14 +187,29 @@ function detectDefaultBranch(): string {
197187 let builtVersions : string [ ] = [ ]
198188
199189 if ( ! hasVersions && APP_ENV === "development" ) {
200- // biome-ignore lint/suspicious/noConsole: keep for debugging
201- console . log ( chalk . cyan ( `(dev) Building docs from current workspace: ${ currentDocsWorkspace } → current` ) )
190+ console . log ( chalk . cyan ( `(dev) Building docs from current workspace: ${ currentDocsWorkspace } → current` ) )
202191 buildDocs ( currentDocsWorkspace , join ( outputDir , "current" ) )
203192 builtVersions = [ "current" ]
204193 } else if ( ! hasVersions && APP_ENV === "production" ) {
205- // biome-ignore lint/suspicious/noConsole: keep for debugging
206- console . log ( chalk . cyan ( `(prod) Building docs from '${ branch } ' branch only → ${ branch } ` ) )
207- buildBranch ( branch , branch )
194+ console . log ( chalk . cyan ( `(prod) Building docs from '${ branch } ' branch only → ${ branch } ` ) )
195+ try {
196+ // Try to build from the target branch worktree
197+ buildBranch ( branch , branch )
198+ } catch ( e : any ) {
199+ // If the target branch doesn’t have /docs/content yet (common for PRs introducing it),
200+ // fall back to building from the current workspace but emit under the same label.
201+ const msg = String ( e ?. message ?? e )
202+ if ( msg . includes ( `Docs content directory "${ contentDir } " not found` ) ) {
203+ console . warn (
204+ chalk . yellow (
205+ `(prod) '${ branch } ' is missing /docs/${ contentDir } . Falling back to current workspace for this build.` ,
206+ ) ,
207+ )
208+ buildDocs ( currentDocsWorkspace , join ( outputDir , branch ) )
209+ } else {
210+ throw e
211+ }
212+ }
208213 builtVersions = [ branch ]
209214 } else {
210215 builtVersions = buildSpecifiedTags ( values . versions as string , APP_ENV === "development" ? "dev" : "prod" )
@@ -217,12 +222,10 @@ function detectDefaultBranch(): string {
217222export const versions = ${ JSON . stringify ( builtVersions , null , 2 ) } as const
218223` ,
219224 )
220- // biome-ignore lint/suspicious/noConsole: keep for debugging
221- console . log ( chalk . green ( `✔ Wrote versions.ts → ${ versionsFile } ` ) )
222- // biome-ignore lint/suspicious/noConsole: keep for debugging
223- console . log ( chalk . green ( "✅ Done" ) )
225+
226+ console . log ( chalk . green ( `✔ Wrote versions.ts → ${ versionsFile } ` ) )
227+ console . log ( chalk . green ( "✅ Done" ) )
224228} ) ( ) . catch ( ( e ) => {
225- // biome-ignore lint/suspicious/noConsole: keep for debugging
226- console . error ( chalk . red ( "❌ Build failed:" ) , e )
229+ console . error ( chalk . red ( "❌ Build failed:" ) , e )
227230 process . exit ( 1 )
228231} )
0 commit comments