🌳
pt0/deployF/dockerF/prebuildTarsAI.mts
1// Kaniko prebuild script - generates tar files from tarSpecs JSON
2// Run in kaniko prebuild init container before the main kaniko build
3// NOTE: This script runs WITHOUT node_modules - only use Node built-ins
4import { readFileSync, writeFileSync, mkdirSync } from 'fs'
5import { execSync } from 'child_process'
6import { dirname } from 'path'
7import { fileURLToPath } from 'url'
9// Exported so importers create a codegraph link (this file is used via string ref in kaniko)
10export const prebuildTarsPtPath = 'pt0/deployF/dockerF/prebuildTarsAI.mts'
12type TarSpec = {
13 type?: undefined
14 tarPath: string
15 filesA: string[]
16 patchedFilesH?: Record<string, string>
17 wpManReplaceTokH?: Record<string, string>
18} | {
19 type: 'submodule'
20 tarPath: string
21 submodulePath: string
22} | {
23 type: 'bundle'
24 tarPath: string
25 bundleName: string
28// Inline isDirectlyRun check (can't import isDirectlyRunF — runs WITHOUT node_modules).
29// IS_BUNDLE guard mirrors isDirectlyRunF.mts: esbuild gives all bundled modules the
30// bundle's own import.meta.url, so the raw check is always true inside a bundle.
31const isDirectlyRun = !process.env.IS_BUNDLE && (import.meta.url === `file://${process.argv[1]}` ||
32 fileURLToPath(import.meta.url) === process.argv[1])
34if (isDirectlyRun) {
35 const prodPatchedInfix = '-prodPatched'
37 // TODO: uncertain if regex escaping is needed for GNU tar --transform patterns
38 // Worked fine without escaping before b048473c77, defaulting to false
39 // If kaniko builds fail on Linux (codeserv), try setting this to true
40 const escapePatternForGnuTar = false
41 const maybeEscape = (str: string) => escapePatternForGnuTar
42 ? str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
43 : str
45 const tarSpecsPath = process.env.TAR_SPECS_PATH
46 if (!tarSpecsPath) throw new Error('TAR_SPECS_PATH env var required') // can't import assertDefined - runs without node_modules
48 const {tarSpecsA} = JSON.parse(readFileSync(tarSpecsPath, 'utf8')) as {tarSpecsA: TarSpec[]}
50 for (const tarSpec of tarSpecsA) {
51 mkdirSync(dirname(tarSpec.tarPath), {recursive: true})
53 if (tarSpec.type === 'bundle') {
54 // esbuilt on the dev pc and shipped inside the ctx tar (no esbuild in this container)
55 console.log(`prebuild: bundle tar ${tarSpec.tarPath} prebuilt, skipping`)
56 continue
57 }
59 if (tarSpec.type === 'submodule') {
60 const {tarPath, submodulePath} = tarSpec
61 console.log(`prebuild: initializing submodule ${submodulePath}...`)
62 execSync(`git submodule update --init --depth 1 ${submodulePath}`, {stdio: 'inherit'})
63 console.log(`prebuild: tarring submodule ${submodulePath}...`)
64 execSync(`tar -zcf ${tarPath} -C . --exclude node_modules --exclude .git ${submodulePath}`, {
65 env: {...process.env, GZIP: '-n'}, stdio: 'inherit',
66 })
67 continue
68 }
70 const {tarPath, filesA, patchedFilesH, wpManReplaceTokH} = tarSpec
72 if (patchedFilesH) {
73 for (const [filePath, content] of Object.entries(patchedFilesH)) {
74 mkdirSync(dirname(filePath), {recursive: true})
75 writeFileSync(filePath, content)
76 }
77 }
79 const cmdA = [
80 'tar', '-zcvf', tarPath, '-C', '.',
81 `--transform=s/${maybeEscape(prodPatchedInfix)}//`,
82 ]
83 if (wpManReplaceTokH) {
84 for (const [fromStr, toStr] of Object.entries(wpManReplaceTokH)) {
85 cmdA.push(`--transform=s/${maybeEscape(fromStr)}/${toStr}/`)
86 }
87 }
88 cmdA.push(...filesA)
90 console.log(`prebuild: generating ${tarPath} (${filesA.length} files)`)
91 execSync(cmdA.join(' '), {env: {...process.env, GZIP: '-n'}, stdio: 'inherit'})
92 }
94 console.log(`prebuild: generated ${tarSpecsA.length} tar file(s)`)