@@ -116,13 +116,17 @@ function formatProductLessonUrl({
116116 productHost,
117117 productSlug,
118118 lessonSlug,
119+ sectionSlug,
119120} : {
120121 productHost : string
121122 productSlug : string
122123 lessonSlug : string
124+ sectionSlug : string | null
123125} ) {
124126 // The product site will typically redirect to a section-specific path when needed.
125- return `https://${ productHost } /workshops/${ productSlug } /${ lessonSlug } `
127+ return sectionSlug
128+ ? `https://${ productHost } /workshops/${ productSlug } /${ sectionSlug } /${ lessonSlug } `
129+ : `https://${ productHost } /workshops/${ productSlug } /${ lessonSlug } `
126130}
127131
128132function formatIssue ( issue : Issue , workshopRoot : string ) {
@@ -347,7 +351,10 @@ async function fetchRemoteWorkshopLessonSlugs({
347351 productHost : string
348352 workshopSlug : string
349353} ) : Promise <
350- | { status : 'success' ; lessonSlugs : Array < string > }
354+ | {
355+ status : 'success'
356+ lessons : Array < { slug : string ; sectionSlug : string | null } >
357+ }
351358 | { status : 'error' ; message : string }
352359> {
353360 const url = `https://${ productHost } /api/workshops/${ encodeURIComponent ( workshopSlug ) } `
@@ -420,30 +427,36 @@ async function fetchRemoteWorkshopLessonSlugs({
420427 }
421428 }
422429
423- const lessonSlugs : Array < string > = [ ]
430+ const lessons : Array < { slug : string ; sectionSlug : string | null } > = [ ]
424431 for ( const resource of resources ) {
425432 if ( ! resource || typeof resource !== 'object' ) continue
426433 const r = resource as Record < string , unknown >
427434
428435 if ( r . _type === 'lesson' ) {
429436 const slug = r . slug
430- if ( typeof slug === 'string' ) lessonSlugs . push ( slug )
437+ if ( typeof slug === 'string' ) lessons . push ( { slug, sectionSlug : null } )
431438 continue
432439 }
433440
434441 if ( r . _type === 'section' ) {
435- const lessons = r . lessons
436- if ( ! Array . isArray ( lessons ) ) continue
437- for ( const lesson of lessons ) {
442+ const sectionSlug =
443+ typeof r . slug === 'string' && r . slug . trim ( ) . length > 0
444+ ? r . slug . trim ( )
445+ : null
446+ const sectionLessons = r . lessons
447+ if ( ! Array . isArray ( sectionLessons ) ) continue
448+ for ( const lesson of sectionLessons ) {
438449 if ( ! lesson || typeof lesson !== 'object' ) continue
439450 const l = lesson as Record < string , unknown >
440451 const slug = l . slug
441- if ( typeof slug === 'string' ) lessonSlugs . push ( slug )
452+ if ( typeof slug === 'string' ) {
453+ lessons . push ( { slug, sectionSlug } )
454+ }
442455 }
443456 }
444457 }
445458
446- return { status : 'success' , lessonSlugs }
459+ return { status : 'success' , lessons }
447460}
448461
449462async function checkMinContentLength ( {
@@ -1020,9 +1033,25 @@ export async function launchReadiness(
10201033 message : remote . message ,
10211034 } )
10221035 } else {
1023- const remoteLessonSlugs = Array . from (
1024- new Set ( remote . lessonSlugs . map ( stripEpicAiSlugSuffix ) ) ,
1025- )
1036+ const remoteLessons = remote . lessons
1037+ . map ( ( l ) => ( {
1038+ slug : stripEpicAiSlugSuffix ( l . slug ) ,
1039+ sectionSlug : l . sectionSlug
1040+ ? stripEpicAiSlugSuffix ( l . sectionSlug )
1041+ : null ,
1042+ } ) )
1043+ . filter ( ( l ) => l . slug . trim ( ) . length > 0 )
1044+
1045+ // Preserve the first sectionSlug seen for a given lesson slug.
1046+ const remoteLessonBySlug = new Map <
1047+ string ,
1048+ { slug : string ; sectionSlug : string | null }
1049+ > ( )
1050+ for ( const l of remoteLessons ) {
1051+ if ( ! remoteLessonBySlug . has ( l . slug ) ) remoteLessonBySlug . set ( l . slug , l )
1052+ }
1053+
1054+ const remoteLessonSlugs = [ ...remoteLessonBySlug . keys ( ) ]
10261055
10271056 if ( remoteLessonSlugs . length === 0 ) {
10281057 issues . push ( {
@@ -1039,14 +1068,15 @@ export async function launchReadiness(
10391068 if ( missing . length ) {
10401069 const formatted = missing
10411070 . sort ( )
1042- . map (
1043- ( slug ) =>
1044- `- ${ slug } : ${ formatProductLessonUrl ( {
1045- productHost,
1046- productSlug,
1047- lessonSlug : slug ,
1048- } ) } `,
1049- )
1071+ . map ( ( slug ) => {
1072+ const remoteLesson = remoteLessonBySlug . get ( slug )
1073+ return `- ${ slug } : ${ formatProductLessonUrl ( {
1074+ productHost,
1075+ productSlug,
1076+ lessonSlug : slug ,
1077+ sectionSlug : remoteLesson ?. sectionSlug ?? null ,
1078+ } ) } `
1079+ } )
10501080 . join ( '\n' )
10511081 issues . push ( {
10521082 level : 'error' ,
0 commit comments