-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild-all-branches.js
More file actions
executable file
·245 lines (206 loc) · 7.1 KB
/
build-all-branches.js
File metadata and controls
executable file
·245 lines (206 loc) · 7.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/usr/bin/env node
/**
* Build all configured branches
* Used by CI to build multiple branches at once
*
* This script:
* 1. Reads build.config.json
* 2. For each enabled branch:
* - Creates a Git worktree
* - Installs dependencies
* - Builds HTML and PDFs
* - Copies outputs to dist/
* - Cleans up worktree
*
* Usage:
* node build-all-branches.js
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const CONFIG = require('./build.config.json');
/**
* Execute command and log output
*/
function exec(command, options = {}) {
console.log(`\n$ ${command}`);
try {
execSync(command, {
stdio: 'inherit',
...options
});
} catch (error) {
throw new Error(`Command failed: ${command}\n${error.message}`);
}
}
/**
* Check if running in CI environment
*/
function isCI() {
return process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
}
/**
* Build a single branch
*/
async function buildBranch(branchName, branchConfig) {
console.log(`\n${'='.repeat(80)}`);
console.log(`📦 Building branch: ${branchName} (${branchConfig.displayName})`);
console.log(`${'='.repeat(80)}\n`);
const worktreePath = path.join(__dirname, '.worktree', branchName);
try {
// Clean up any existing worktree
if (fs.existsSync(worktreePath)) {
console.log(`🗑️ Removing existing worktree: ${worktreePath}`);
exec(`git worktree remove --force ${worktreePath}`);
}
// Determine the ref to checkout
// In CI, use origin/branchName, locally use branchName
const ref = isCI() ? `origin/${branchName}` : branchName;
// Check if ref exists
try {
execSync(`git rev-parse --verify ${ref}`, { stdio: 'pipe' });
} catch (error) {
console.warn(`⚠️ Branch ${ref} does not exist, skipping...`);
return 'skipped'; // Skip this branch
}
// Create worktree
console.log(`📁 Creating worktree for ${ref}...`);
exec(`git worktree add --force ${worktreePath} ${ref}`);
// Check if worktree was created
if (!fs.existsSync(worktreePath)) {
throw new Error(`Failed to create worktree at ${worktreePath}`);
}
// Install dependencies in worktree
console.log(`\n📦 Installing dependencies...`);
exec('npm ci', { cwd: worktreePath });
// Build in worktree
console.log(`\n🔨 Building...`);
const outputPath = branchConfig.outputPath;
const basePath = outputPath ? `/cv/${outputPath}` : '/cv';
exec('node build.js', {
cwd: worktreePath,
env: {
...process.env,
BASE_PATH: basePath,
BRANCH_NAME: branchName
}
});
// Copy outputs to main dist/ directory
console.log(`\n📋 Copying outputs to main dist/ directory...`);
const worktreeWebDir = outputPath
? path.join(worktreePath, CONFIG.build.outputDirs.web, outputPath)
: path.join(worktreePath, CONFIG.build.outputDirs.web);
const worktreePdfDir = outputPath
? path.join(worktreePath, CONFIG.build.outputDirs.pdf, outputPath)
: path.join(worktreePath, CONFIG.build.outputDirs.pdf);
const mainWebDir = outputPath
? path.join(__dirname, CONFIG.build.outputDirs.web, outputPath)
: path.join(__dirname, CONFIG.build.outputDirs.web);
const mainPdfDir = outputPath
? path.join(__dirname, CONFIG.build.outputDirs.pdf, outputPath)
: path.join(__dirname, CONFIG.build.outputDirs.pdf);
// Ensure target directories exist
fs.mkdirSync(mainWebDir, { recursive: true });
fs.mkdirSync(mainPdfDir, { recursive: true });
// Copy web files
if (fs.existsSync(worktreeWebDir)) {
console.log(` Copying ${worktreeWebDir} → ${mainWebDir}`);
exec(`cp -r ${worktreeWebDir}/* ${mainWebDir}/`);
} else {
console.warn(` ⚠️ Web directory not found: ${worktreeWebDir}`);
}
// Copy PDF files to dist/pdf/ (for Git tracking)
if (fs.existsSync(worktreePdfDir)) {
console.log(` Copying ${worktreePdfDir} → ${mainPdfDir}`);
exec(`cp -r ${worktreePdfDir}/* ${mainPdfDir}/`);
} else {
console.warn(` ⚠️ PDF directory not found: ${worktreePdfDir}`);
}
// ALSO copy PDFs to dist/web/pdf/ for GitHub Pages serving
const mainWebPdfDir = outputPath
? path.join(__dirname, CONFIG.build.outputDirs.web, outputPath, 'pdf')
: path.join(__dirname, CONFIG.build.outputDirs.web, 'pdf');
if (fs.existsSync(worktreePdfDir)) {
fs.mkdirSync(mainWebPdfDir, { recursive: true });
console.log(` Copying ${worktreePdfDir} → ${mainWebPdfDir} (for GitHub Pages)`);
exec(`cp -r ${worktreePdfDir}/* ${mainWebPdfDir}/`);
}
console.log(`\n✅ Branch ${branchName} built successfully!`);
} catch (error) {
console.error(`\n❌ Failed to build branch ${branchName}:`, error.message);
throw error;
} finally {
// Clean up worktree
if (fs.existsSync(worktreePath)) {
console.log(`\n🧹 Cleaning up worktree...`);
try {
exec(`git worktree remove --force ${worktreePath}`);
} catch (error) {
console.warn(`⚠️ Failed to remove worktree: ${error.message}`);
}
}
}
}
/**
* Main function
*/
async function buildAll() {
console.log('🚀 Building all configured branches...\n');
// Get enabled branches
const enabledBranches = Object.entries(CONFIG.branches)
.filter(([name, config]) => config.enabled)
.map(([name, config]) => ({ name, ...config }));
if (enabledBranches.length === 0) {
console.log('⚠️ No branches are enabled in build.config.json');
process.exit(0);
}
console.log(`📋 Branches to build: ${enabledBranches.map(b => b.name).join(', ')}\n`);
// Ensure dist directories exist
fs.mkdirSync(CONFIG.build.outputDirs.web, { recursive: true });
fs.mkdirSync(CONFIG.build.outputDirs.pdf, { recursive: true });
// Build each branch
let successCount = 0;
let failCount = 0;
let skipCount = 0;
for (const branch of enabledBranches) {
try {
const result = await buildBranch(branch.name, branch);
if (result === 'skipped') {
skipCount++;
} else {
successCount++;
}
} catch (error) {
console.error(`\n❌ Failed to build ${branch.name}`);
failCount++;
// In CI, fail fast
if (isCI()) {
throw error;
}
}
}
// Summary
console.log(`\n${'='.repeat(80)}`);
console.log('📊 Build Summary');
console.log(`${'='.repeat(80)}`);
console.log(`✅ Success: ${successCount}`);
if (skipCount > 0) {
console.log(`⏭️ Skipped: ${skipCount}`);
}
console.log(`❌ Failed: ${failCount}`);
console.log(`📁 Output directory: ${CONFIG.build.outputDirs.web}/`);
console.log(`📄 PDFs directory: ${CONFIG.build.outputDirs.pdf}/`);
console.log(`${'='.repeat(80)}\n`);
if (failCount > 0) {
process.exit(1);
}
console.log('✨ All branches built successfully!');
}
// Run if called directly
if (require.main === module) {
buildAll().catch(error => {
console.error('\n💥 Fatal error:', error);
process.exit(1);
});
}
module.exports = { buildAll };