mirror of
https://github.com/nimbold/Firelink.git
synced 2026-09-10 01:35:43 +00:00
eca4efb1ad
- replace hardcoded make -j2 with dynamic CPU core detection in aria2 build.sh - isolate Aria2 source build cache from prebuilt engine downloads - add atomic cache validation, restoration, and promotion in scripts/engine-aria2-cache.js - add Rust dependency and target caching with Swatinem/rust-cache@v2 - raise Desktop checks timeout to 45 minutes to prevent job aborts - harden temporary directory cleanup on Windows process abort
148 lines
4.4 KiB
JavaScript
148 lines
4.4 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import crypto from 'node:crypto';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { getAria2BuildScriptSha256 } from './engine-aria2-cache.js';
|
|
|
|
const WINDOWS_PACKAGES = [
|
|
'autoconf',
|
|
'automake',
|
|
'libtool',
|
|
'gettext-devel',
|
|
'pkgconf',
|
|
'make',
|
|
'patch',
|
|
'binutils',
|
|
'mingw-w64-x86_64-gcc',
|
|
'mingw-w64-x86_64-binutils',
|
|
'mingw-w64-x86_64-pkgconf',
|
|
'mingw-w64-x86_64-openssl',
|
|
'mingw-w64-x86_64-libssh2',
|
|
'mingw-w64-x86_64-c-ares',
|
|
'mingw-w64-x86_64-expat',
|
|
'mingw-w64-x86_64-sqlite3',
|
|
'mingw-w64-x86_64-zlib',
|
|
];
|
|
|
|
const LINUX_PACKAGES = [
|
|
'gcc',
|
|
'g++',
|
|
'make',
|
|
'patch',
|
|
'binutils',
|
|
'autoconf',
|
|
'automake',
|
|
'libtool',
|
|
'gettext',
|
|
'autopoint',
|
|
'pkg-config',
|
|
'libssl-dev',
|
|
'libssh2-1-dev',
|
|
'libgcrypt20-dev',
|
|
'libc-ares-dev',
|
|
'libexpat1-dev',
|
|
'libsqlite3-dev',
|
|
'zlib1g-dev',
|
|
];
|
|
|
|
function run(command, args) {
|
|
try {
|
|
return execFileSync(command, args, {
|
|
encoding: 'utf8',
|
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
}).replaceAll('\r\n', '\n').trim();
|
|
} catch (error) {
|
|
const detail = error.stderr?.toString().trim() || error.message;
|
|
throw new Error(`Could not fingerprint the engine toolchain with ${command}: ${detail}`);
|
|
}
|
|
}
|
|
|
|
function writeOutput(name, value) {
|
|
const line = `${name}=${value}\n`;
|
|
if (process.env.GITHUB_OUTPUT) {
|
|
fs.appendFileSync(process.env.GITHUB_OUTPUT, line);
|
|
} else {
|
|
process.stdout.write(line);
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const target = process.env.FIRELINK_TARGET_TRIPLE;
|
|
if (!target) throw new Error('FIRELINK_TARGET_TRIPLE is required.');
|
|
|
|
const records = [`target=${target}`];
|
|
if (process.platform === 'win32') {
|
|
const msysRoot = process.env.FIRELINK_MSYS2_ROOT;
|
|
if (!msysRoot) throw new Error('FIRELINK_MSYS2_ROOT is required on Windows.');
|
|
const bash = path.join(msysRoot, 'usr', 'bin', 'bash.exe');
|
|
const packages = WINDOWS_PACKAGES.join(' ');
|
|
records.push(`msys2-packages=${run(bash, ['-lc', `pacman -Q ${packages}`])}`);
|
|
} else if (process.platform === 'linux') {
|
|
records.push(`debian-packages=${run('dpkg-query', [
|
|
'-W',
|
|
'-f=${binary:Package}=${Version}\\n',
|
|
...LINUX_PACKAGES,
|
|
])}`);
|
|
for (const [command, args] of [
|
|
['gcc', ['--version']],
|
|
['make', ['--version']],
|
|
['autoconf', ['--version']],
|
|
['automake', ['--version']],
|
|
['pkg-config', ['--version']],
|
|
]) {
|
|
records.push(`${command}=${run(command, args).split('\n', 1)[0]}`);
|
|
}
|
|
} else {
|
|
throw new Error(`Unsupported engine toolchain host: ${process.platform}`);
|
|
}
|
|
|
|
const fingerprint = crypto.createHash('sha256').update(records.join('\n')).digest('hex');
|
|
writeOutput('fingerprint', fingerprint);
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const sourceLockPath = path.join(repoRoot, 'engine-sources.lock.json');
|
|
if (fs.existsSync(sourceLockPath)) {
|
|
const sourceLock = JSON.parse(fs.readFileSync(sourceLockPath, 'utf8'));
|
|
const aria2Source = sourceLock.targets?.[target]?.aria2c;
|
|
if (aria2Source) {
|
|
const canonicalize = val => {
|
|
if (Array.isArray(val)) return val.map(canonicalize);
|
|
if (val && typeof val === 'object') {
|
|
return Object.fromEntries(
|
|
Object.keys(val).sort().map(k => [k, canonicalize(val[k])])
|
|
);
|
|
}
|
|
return val;
|
|
};
|
|
|
|
const patchPath = path.join(repoRoot, aria2Source.patch || 'scripts/aria2/firelink.patch');
|
|
const buildShPath = path.join(repoRoot, 'scripts/aria2/build.sh');
|
|
const patchSha = fs.existsSync(patchPath)
|
|
? crypto.createHash('sha256').update(fs.readFileSync(patchPath, 'utf8').replaceAll('\r\n', '\n')).digest('hex')
|
|
: (aria2Source.patchSha256 || '');
|
|
const buildShSha = fs.existsSync(buildShPath)
|
|
? getAria2BuildScriptSha256(repoRoot)
|
|
: '';
|
|
|
|
const aria2Records = [
|
|
...records,
|
|
`aria2-source=${JSON.stringify(canonicalize(aria2Source))}`,
|
|
`aria2-patch-sha256=${patchSha}`,
|
|
`aria2-build-sh-sha256=${buildShSha}`,
|
|
];
|
|
const aria2Fingerprint = crypto.createHash('sha256').update(aria2Records.join('\n')).digest('hex');
|
|
writeOutput('aria2-fingerprint', aria2Fingerprint);
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
main();
|
|
} catch (error) {
|
|
console.error(error.message);
|
|
process.exitCode = 1;
|
|
}
|