@@ -340,15 +340,41 @@ function convertCSVToInternalFormat(csvData, country, yearRange) {
340340 return result ;
341341}
342342
343+ /**
344+ * Get submodule commit info for reproducible builds
345+ */
346+ async function getSubmoduleInfo ( ) {
347+ const { execSync } = await import ( 'child_process' ) ;
348+ const submodulePath = path . join ( ROOT_DIR , 'submodules' , 'openholidaysapi.data' ) ;
349+
350+ const hash = execSync ( 'git rev-parse --short HEAD' , {
351+ cwd : submodulePath ,
352+ encoding : 'utf8'
353+ } ) . trim ( ) ;
354+
355+ // Commit timestamp in seconds (for year range calculation)
356+ const commitUnixTimestamp = parseInt (
357+ execSync ( 'git show --no-patch --format=%ct HEAD' , {
358+ cwd : submodulePath ,
359+ encoding : 'utf8'
360+ } ) . trim ( ) ,
361+ 10
362+ ) ;
363+
364+ return { hash, commitUnixTimestamp } ;
365+ }
366+
343367/**
344368 * Generate JavaScript file with holiday definitions
345369 */
346- async function generateJavaScriptFile ( countriesData , yearRange ) {
370+ async function generateJavaScriptFile ( countriesData , yearRange , submodule ) {
371+ const commitDate = new Date ( submodule . commitUnixTimestamp * 1000 ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
372+
347373 const lines = [
348374 '/**' ,
349375 ' * Auto-generated school holidays from OpenHolidays API Data (Git Submodule)' ,
350376 ' * DO NOT EDIT MANUALLY - Run: node scripts/fetch-school-holidays.mjs' ,
351- ` * Generated : ${ new Date ( ) . toISOString ( ) } ` ,
377+ ` * Submodule : ${ submodule . hash } ( ${ commitDate } ) ` ,
352378 ' */' ,
353379 ''
354380 ] ;
@@ -635,11 +661,14 @@ async function buildSchoolHolidays() {
635661 }
636662 }
637663
638- // Generate JavaScript file (limit to current year ±15)
639- const currentYear = new Date ( ) . getFullYear ( ) ;
640- const yearRange = [ currentYear - 15 , currentYear + 15 ] ;
664+ // Generate JavaScript file (limit to submodule commit year ±15)
665+ // Using submodule timestamp ensures reproducible builds
666+ // @see https://reproducible-builds.org/docs/timestamps/
667+ const submodule = await getSubmoduleInfo ( ) ;
668+ const referenceYear = new Date ( submodule . commitUnixTimestamp * 1000 ) . getUTCFullYear ( ) ;
669+ const yearRange = [ referenceYear - 15 , referenceYear + 15 ] ;
641670 console . log ( `📅 Year range: ${ yearRange [ 0 ] } –${ yearRange [ 1 ] } ` ) ;
642- const jsContent = await generateJavaScriptFile ( results , yearRange ) ;
671+ const jsContent = await generateJavaScriptFile ( results , yearRange , submodule ) ;
643672 await fs . writeFile ( GENERATED_FILE , jsContent , 'utf8' ) ;
644673
645674 const jsStats = await fs . stat ( GENERATED_FILE ) ;
0 commit comments