Skip to content

Commit a0af573

Browse files
committed
feat(build-infra): add build logging and checkpoint helpers
Add utility functions for build logging, checkpoint management, and pre-build verification to build-helpers module. Changes: - Add getBuildLogPath() for consistent log file paths - Add saveBuildLog() for appending to build logs - Add getLastLogLines() for retrieving recent log entries - Add createCheckpoint() for build resume support - Add readCheckpoint() and cleanCheckpoint() for checkpoint management - Add checkNetworkConnectivity() for pre-build network verification - Add verifyGitTag() for validating Node.js version tags Benefits: - Centralized logging utilities across build packages - Support for resumable builds via checkpoints - Pre-build validation to catch issues early - Better debugging with structured log access
1 parent 60f19bc commit a0af573

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

packages/build-infra/lib/build-helpers.mjs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,154 @@ export async function getFileSize(filePath) {
189189

190190
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`
191191
}
192+
193+
/**
194+
* Get build log path.
195+
*
196+
* @param {string} buildDir - Build directory
197+
* @returns {string} Log file path
198+
*/
199+
export function getBuildLogPath(buildDir) {
200+
return path.join(buildDir, 'build.log')
201+
}
202+
203+
/**
204+
* Save build output to log file.
205+
*
206+
* @param {string} buildDir - Build directory
207+
* @param {string} content - Content to log
208+
* @returns {Promise<void>}
209+
*/
210+
export async function saveBuildLog(buildDir, content) {
211+
const logPath = getBuildLogPath(buildDir)
212+
try {
213+
await fs.appendFile(logPath, `${content}\n`)
214+
} catch {
215+
// Don't fail build if logging fails.
216+
}
217+
}
218+
219+
/**
220+
* Get last N lines from build log.
221+
*
222+
* @param {string} buildDir - Build directory
223+
* @param {number} lines - Number of lines to get
224+
* @returns {Promise<string|null>} Last lines or null
225+
*/
226+
export async function getLastLogLines(buildDir, lines = 50) {
227+
const logPath = getBuildLogPath(buildDir)
228+
try {
229+
const content = await fs.readFile(logPath, 'utf8')
230+
const allLines = content.split('\n')
231+
return allLines.slice(-lines).join('\n')
232+
} catch {
233+
return null
234+
}
235+
}
236+
237+
/**
238+
* Create checkpoint for build resume.
239+
*
240+
* @param {string} buildDir - Build directory
241+
* @param {string} step - Checkpoint step name
242+
* @returns {Promise<void>}
243+
*/
244+
export async function createCheckpoint(buildDir, step) {
245+
const checkpointFile = path.join(buildDir, '.build-checkpoint')
246+
try {
247+
await fs.writeFile(
248+
checkpointFile,
249+
JSON.stringify({
250+
step,
251+
timestamp: Date.now(),
252+
}),
253+
)
254+
} catch {
255+
// Don't fail if checkpoint creation fails.
256+
}
257+
}
258+
259+
/**
260+
* Read checkpoint.
261+
*
262+
* @param {string} buildDir - Build directory
263+
* @returns {Promise<object|null>} Checkpoint data or null
264+
*/
265+
export async function readCheckpoint(buildDir) {
266+
const checkpointFile = path.join(buildDir, '.build-checkpoint')
267+
try {
268+
const content = await fs.readFile(checkpointFile, 'utf8')
269+
return JSON.parse(content)
270+
} catch {
271+
return null
272+
}
273+
}
274+
275+
/**
276+
* Clean checkpoint.
277+
*
278+
* @param {string} buildDir - Build directory
279+
* @returns {Promise<void>}
280+
*/
281+
export async function cleanCheckpoint(buildDir) {
282+
const checkpointFile = path.join(buildDir, '.build-checkpoint')
283+
try {
284+
await fs.unlink(checkpointFile)
285+
} catch {
286+
// Ignore errors.
287+
}
288+
}
289+
290+
/**
291+
* Check network connectivity.
292+
*
293+
* @returns {Promise<object>} Connection status
294+
*/
295+
export async function checkNetworkConnectivity() {
296+
try {
297+
// Try to reach GitHub (where we clone from).
298+
const result = await execCapture('curl', [
299+
'-s',
300+
'-o',
301+
'/dev/null',
302+
'-w',
303+
'%{http_code}',
304+
'--connect-timeout',
305+
'5',
306+
'https://github.com',
307+
])
308+
309+
const statusCode = result.stdout
310+
return {
311+
connected:
312+
statusCode === '200' || statusCode === '301' || statusCode === '302',
313+
statusCode,
314+
}
315+
} catch {
316+
return { connected: false, statusCode: null }
317+
}
318+
}
319+
320+
/**
321+
* Verify git tag exists.
322+
*
323+
* @param {string} version - Git tag version
324+
* @returns {Promise<object>} Tag verification result
325+
*/
326+
export async function verifyGitTag(version) {
327+
try {
328+
const result = await execCapture('git', [
329+
'ls-remote',
330+
'--tags',
331+
'https://github.com/nodejs/node.git',
332+
version,
333+
])
334+
335+
return {
336+
exists: result.stdout.includes(version),
337+
output: result.stdout,
338+
}
339+
} catch {
340+
return { exists: false, output: null }
341+
}
342+
}

0 commit comments

Comments
 (0)