mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-06-13 09:23:52 -07:00
feat(reliability): implement build reliability service with git integrity, reserved filename cleanup, and build archival
Adds BuildReliabilityService with the following capabilities: - checkGitIntegrity(): runs git fsck --no-dangling and parses output for corruption - cleanStaleLockFiles(): removes stale .lock files older than 10 minutes - validateSubmoduleBackingStores(): validates .git files point to valid backing stores - recoverCorruptedRepo(): orchestrates fsck, lock cleanup, re-fetch, retry fsck - cleanReservedFilenames(): removes Windows reserved filenames (con, prn, aux, nul, com1-9, lpt1-9) - archiveBuildOutput(): creates tar.gz archive of build output - enforceRetention(): deletes archives older than retention period - configureGitEnvironment(): sets GIT_TERMINAL_PROMPT=0, http.postBuffer, core.longpaths Wired into action.yml as opt-in inputs, with pre-build integrity checks and post-build archival in the main entry point. Includes 29 unit tests covering success and failure cases for all methods. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+474
-6
@@ -38,6 +38,7 @@ const model_1 = __nccwpck_require__(41359);
|
||||
const cli_1 = __nccwpck_require__(55651);
|
||||
const mac_builder_1 = __importDefault(__nccwpck_require__(39364));
|
||||
const platform_setup_1 = __importDefault(__nccwpck_require__(64423));
|
||||
const reliability_1 = __nccwpck_require__(9842);
|
||||
async function runMain() {
|
||||
try {
|
||||
if (cli_1.Cli.InitCliMode()) {
|
||||
@@ -46,9 +47,32 @@ async function runMain() {
|
||||
}
|
||||
model_1.Action.checkCompatibility();
|
||||
model_1.Cache.verify();
|
||||
// Always configure git environment for CI reliability
|
||||
reliability_1.BuildReliabilityService.configureGitEnvironment();
|
||||
const { workspace, actionFolder } = model_1.Action;
|
||||
const buildParameters = await model_1.BuildParameters.create();
|
||||
const baseImage = new model_1.ImageTag(buildParameters);
|
||||
// Pre-build reliability checks
|
||||
if (buildParameters.gitIntegrityCheck) {
|
||||
core.info('Running git integrity checks...');
|
||||
const isHealthy = reliability_1.BuildReliabilityService.checkGitIntegrity(workspace);
|
||||
reliability_1.BuildReliabilityService.cleanStaleLockFiles(workspace);
|
||||
reliability_1.BuildReliabilityService.validateSubmoduleBackingStores(workspace);
|
||||
if (buildParameters.cleanReservedFilenames) {
|
||||
reliability_1.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
||||
}
|
||||
if (!isHealthy && buildParameters.gitAutoRecover) {
|
||||
core.info('Git corruption detected, attempting automatic recovery...');
|
||||
const recovered = reliability_1.BuildReliabilityService.recoverCorruptedRepo(workspace);
|
||||
if (!recovered) {
|
||||
core.warning('Automatic recovery failed. Build may encounter issues.');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (buildParameters.cleanReservedFilenames) {
|
||||
// cleanReservedFilenames can run independently of gitIntegrityCheck
|
||||
reliability_1.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
||||
}
|
||||
let exitCode = -1;
|
||||
if (buildParameters.providerStrategy === 'local') {
|
||||
core.info('Building locally');
|
||||
@@ -66,6 +90,12 @@ async function runMain() {
|
||||
await model_1.Orchestrator.run(buildParameters, baseImage.toString());
|
||||
exitCode = 0;
|
||||
}
|
||||
// Post-build: archive and enforce retention
|
||||
if (buildParameters.buildArchiveEnabled && exitCode === 0) {
|
||||
core.info('Archiving build output...');
|
||||
reliability_1.BuildReliabilityService.archiveBuildOutput(buildParameters.buildPath, buildParameters.buildArchivePath);
|
||||
reliability_1.BuildReliabilityService.enforceRetention(buildParameters.buildArchivePath, buildParameters.buildArchiveRetention);
|
||||
}
|
||||
// Set output
|
||||
await model_1.Output.setBuildVersion(buildParameters.buildVersion);
|
||||
await model_1.Output.setAndroidVersionCode(buildParameters.androidVersionCode);
|
||||
@@ -1833,26 +1863,26 @@ class Input {
|
||||
return Input.getInput('skipActivation')?.toLowerCase() ?? 'false';
|
||||
}
|
||||
static get gitIntegrityCheck() {
|
||||
const input = Input.getInput('gitIntegrityCheck') ?? false;
|
||||
const input = Input.getInput('gitIntegrityCheck') ?? 'false';
|
||||
return input === 'true';
|
||||
}
|
||||
static get gitAutoRecover() {
|
||||
const input = Input.getInput('gitAutoRecover') ?? 'true';
|
||||
const input = Input.getInput('gitAutoRecover') ?? 'false';
|
||||
return input === 'true';
|
||||
}
|
||||
static get cleanReservedFilenames() {
|
||||
const input = Input.getInput('cleanReservedFilenames') ?? false;
|
||||
const input = Input.getInput('cleanReservedFilenames') ?? 'false';
|
||||
return input === 'true';
|
||||
}
|
||||
static get buildArchiveEnabled() {
|
||||
const input = Input.getInput('buildArchiveEnabled') ?? false;
|
||||
const input = Input.getInput('buildArchiveEnabled') ?? 'false';
|
||||
return input === 'true';
|
||||
}
|
||||
static get buildArchivePath() {
|
||||
return Input.getInput('buildArchivePath') ?? '';
|
||||
return Input.getInput('buildArchivePath') ?? './build-archives';
|
||||
}
|
||||
static get buildArchiveRetention() {
|
||||
return Number.parseInt(Input.getInput('buildArchiveRetention') ?? '3', 10);
|
||||
return Number.parseInt(Input.getInput('buildArchiveRetention') ?? '30', 10);
|
||||
}
|
||||
static ToEnvVarFormat(input) {
|
||||
if (input.toUpperCase() === input) {
|
||||
@@ -9660,6 +9690,444 @@ class ContainerHookService {
|
||||
exports.ContainerHookService = ContainerHookService;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 37347:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.BuildReliabilityService = void 0;
|
||||
const node_child_process_1 = __nccwpck_require__(17718);
|
||||
const node_fs_1 = __importDefault(__nccwpck_require__(87561));
|
||||
const node_path_1 = __importDefault(__nccwpck_require__(49411));
|
||||
const core = __importStar(__nccwpck_require__(42186));
|
||||
/**
|
||||
* Build reliability features for hardening CI pipelines.
|
||||
* Provides git integrity checks, stale lock cleanup, submodule validation,
|
||||
* reserved filename removal, build archival, and git environment configuration.
|
||||
* All features are opt-in and fail gracefully (warnings only).
|
||||
*/
|
||||
class BuildReliabilityService {
|
||||
/**
|
||||
* Run git fsck to check repository integrity.
|
||||
* Returns true if the repo is healthy, false if corruption detected.
|
||||
*/
|
||||
static checkGitIntegrity(repoPath = '.') {
|
||||
core.info(`[Reliability] Checking git integrity in ${repoPath}`);
|
||||
try {
|
||||
const output = (0, node_child_process_1.execSync)(`git -C "${repoPath}" fsck --no-dangling`, {
|
||||
encoding: 'utf8',
|
||||
timeout: 120000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
// Parse output for corruption indicators
|
||||
const corruptionPatterns = [
|
||||
/broken link/i,
|
||||
/missing (blob|tree|commit|tag)/i,
|
||||
/dangling/i,
|
||||
/corrupt/i,
|
||||
/error in /i,
|
||||
];
|
||||
for (const pattern of corruptionPatterns) {
|
||||
if (pattern.test(output)) {
|
||||
core.warning(`[Reliability] Git integrity check found issues: ${output.trim()}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
core.info('[Reliability] Git integrity check passed');
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
// execSync throws on non-zero exit code
|
||||
const stderr = error.stderr?.toString() ?? error.message;
|
||||
core.warning(`[Reliability] Git integrity check failed: ${stderr}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Remove stale .lock files from the .git directory.
|
||||
* Only removes lock files older than 10 minutes to avoid interfering with active operations.
|
||||
* Returns the number of lock files removed.
|
||||
*/
|
||||
static cleanStaleLockFiles(repoPath = '.') {
|
||||
const gitDir = node_path_1.default.join(repoPath, '.git');
|
||||
if (!node_fs_1.default.existsSync(gitDir) || !node_fs_1.default.statSync(gitDir).isDirectory()) {
|
||||
return 0;
|
||||
}
|
||||
core.info(`[Reliability] Scanning for stale lock files in ${gitDir}`);
|
||||
const now = Date.now();
|
||||
let removed = 0;
|
||||
const cleanDirectory = (directory) => {
|
||||
if (!node_fs_1.default.existsSync(directory))
|
||||
return;
|
||||
try {
|
||||
const entries = node_fs_1.default.readdirSync(directory, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const fullPath = node_path_1.default.join(directory, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
cleanDirectory(fullPath);
|
||||
}
|
||||
else if (entry.name.endsWith('.lock')) {
|
||||
// Check if it is a known lock file location OR under refs/
|
||||
const relativePath = node_path_1.default.relative(gitDir, fullPath);
|
||||
const isKnownLock = BuildReliabilityService.LOCK_FILE_NAMES.has(entry.name);
|
||||
const isRefsLock = relativePath.startsWith('refs' + node_path_1.default.sep);
|
||||
if (isKnownLock || isRefsLock) {
|
||||
try {
|
||||
const stat = node_fs_1.default.statSync(fullPath);
|
||||
const ageMs = now - stat.mtimeMs;
|
||||
if (ageMs > BuildReliabilityService.LOCK_FILE_MAX_AGE_MS) {
|
||||
node_fs_1.default.unlinkSync(fullPath);
|
||||
removed++;
|
||||
core.info(`[Reliability] Removed stale lock file (age: ${Math.round(ageMs / 1000)}s): ${relativePath}`);
|
||||
}
|
||||
else {
|
||||
core.info(`[Reliability] Lock file is recent (age: ${Math.round(ageMs / 1000)}s), skipping: ${relativePath}`);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
core.warning(`[Reliability] Could not remove lock file: ${fullPath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Directory not accessible
|
||||
}
|
||||
};
|
||||
cleanDirectory(gitDir);
|
||||
if (removed > 0) {
|
||||
core.info(`[Reliability] Cleaned ${removed} stale lock file(s)`);
|
||||
}
|
||||
else {
|
||||
core.info('[Reliability] No stale lock files found');
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/**
|
||||
* Validate that submodule .git files point to existing backing stores
|
||||
* under .git/modules/. Returns list of submodule paths with broken backing stores.
|
||||
*/
|
||||
static validateSubmoduleBackingStores(repoPath = '.') {
|
||||
const broken = [];
|
||||
const gitmodulesPath = node_path_1.default.join(repoPath, '.gitmodules');
|
||||
if (!node_fs_1.default.existsSync(gitmodulesPath)) {
|
||||
core.info('[Reliability] No .gitmodules found, skipping submodule validation');
|
||||
return broken;
|
||||
}
|
||||
core.info(`[Reliability] Validating submodule backing stores in ${repoPath}`);
|
||||
try {
|
||||
const content = node_fs_1.default.readFileSync(gitmodulesPath, 'utf8');
|
||||
const pathMatches = content.matchAll(/path\s*=\s*(.+)/g);
|
||||
for (const match of pathMatches) {
|
||||
const submodulePath = match[1].trim();
|
||||
const gitFile = node_path_1.default.join(repoPath, submodulePath, '.git');
|
||||
if (!node_fs_1.default.existsSync(gitFile)) {
|
||||
// Submodule not initialized -- not necessarily broken
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const stat = node_fs_1.default.statSync(gitFile);
|
||||
if (stat.isFile()) {
|
||||
// .git is a file -- should contain "gitdir: <path>"
|
||||
const gitFileContent = node_fs_1.default.readFileSync(gitFile, 'utf8').trim();
|
||||
const gitdirMatch = gitFileContent.match(/^gitdir:\s*(.+)$/);
|
||||
if (gitdirMatch) {
|
||||
const backingStore = node_path_1.default.resolve(node_path_1.default.join(repoPath, submodulePath), gitdirMatch[1]);
|
||||
if (!node_fs_1.default.existsSync(backingStore)) {
|
||||
broken.push(submodulePath);
|
||||
core.warning(`[Reliability] Submodule ${submodulePath} has broken backing store: ${backingStore}`);
|
||||
}
|
||||
else {
|
||||
core.info(`[Reliability] Submodule ${submodulePath} backing store OK`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
broken.push(submodulePath);
|
||||
core.warning(`[Reliability] Submodule ${submodulePath} .git file has invalid format`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Can't read .git file
|
||||
core.warning(`[Reliability] Could not read .git file for submodule: ${submodulePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`[Reliability] Could not read .gitmodules: ${error.message}`);
|
||||
}
|
||||
if (broken.length > 0) {
|
||||
core.warning(`[Reliability] ${broken.length} submodule(s) have broken backing stores`);
|
||||
}
|
||||
else {
|
||||
core.info('[Reliability] All submodule backing stores are valid');
|
||||
}
|
||||
return broken;
|
||||
}
|
||||
/**
|
||||
* Orchestrate recovery of a corrupted repository.
|
||||
* Sequence: fsck -> clean locks -> re-fetch -> retry fsck.
|
||||
* Returns true if recovery succeeded.
|
||||
*/
|
||||
static recoverCorruptedRepo(repoPath = '.') {
|
||||
core.warning(`[Reliability] Attempting automatic recovery for ${repoPath}`);
|
||||
// Step 1: Clean stale lock files that may be preventing operations
|
||||
const locksRemoved = BuildReliabilityService.cleanStaleLockFiles(repoPath);
|
||||
if (locksRemoved > 0) {
|
||||
core.info(`[Reliability] Recovery: cleaned ${locksRemoved} lock file(s)`);
|
||||
}
|
||||
// Step 2: Re-fetch to restore missing objects
|
||||
try {
|
||||
core.info('[Reliability] Recovery: re-fetching from remote');
|
||||
(0, node_child_process_1.execSync)(`git -C "${repoPath}" fetch --all`, {
|
||||
encoding: 'utf8',
|
||||
timeout: 300000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
core.info('[Reliability] Recovery: fetch completed');
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`[Reliability] Recovery: fetch failed: ${error.stderr?.toString() ?? error.message}`);
|
||||
}
|
||||
// Step 3: Retry fsck
|
||||
const healthy = BuildReliabilityService.checkGitIntegrity(repoPath);
|
||||
if (healthy) {
|
||||
core.info('[Reliability] Recovery succeeded -- repository is healthy');
|
||||
}
|
||||
else {
|
||||
core.warning('[Reliability] Recovery failed -- repository still has integrity issues');
|
||||
}
|
||||
return healthy;
|
||||
}
|
||||
/**
|
||||
* Scan a directory tree for files/directories with Windows reserved names.
|
||||
* These names (con, prn, aux, nul, com1-9, lpt1-9) with any extension
|
||||
* cause Unity asset importer infinite loops on Windows.
|
||||
* Returns list of paths that were removed.
|
||||
*/
|
||||
static cleanReservedFilenames(projectPath) {
|
||||
const assetsPath = node_path_1.default.join(projectPath, 'Assets');
|
||||
if (!node_fs_1.default.existsSync(assetsPath)) {
|
||||
core.info(`[Reliability] No Assets directory found at ${assetsPath}, skipping reserved filename scan`);
|
||||
return [];
|
||||
}
|
||||
core.info(`[Reliability] Scanning for reserved filenames in ${assetsPath}`);
|
||||
const cleaned = [];
|
||||
const scanDirectory = (directory) => {
|
||||
try {
|
||||
const entries = node_fs_1.default.readdirSync(directory, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const nameWithoutExtension = entry.name.split('.')[0].toLowerCase();
|
||||
const fullPath = node_path_1.default.join(directory, entry.name);
|
||||
if (BuildReliabilityService.RESERVED_NAMES.has(nameWithoutExtension)) {
|
||||
try {
|
||||
if (entry.isDirectory()) {
|
||||
node_fs_1.default.rmSync(fullPath, { recursive: true, force: true });
|
||||
}
|
||||
else {
|
||||
node_fs_1.default.unlinkSync(fullPath);
|
||||
}
|
||||
cleaned.push(fullPath);
|
||||
core.warning(`[Reliability] Removed reserved filename: ${fullPath}`);
|
||||
}
|
||||
catch {
|
||||
core.warning(`[Reliability] Could not remove reserved filename: ${fullPath}`);
|
||||
}
|
||||
}
|
||||
else if (entry.isDirectory()) {
|
||||
scanDirectory(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Directory not accessible
|
||||
}
|
||||
};
|
||||
scanDirectory(assetsPath);
|
||||
if (cleaned.length > 0) {
|
||||
core.warning(`[Reliability] Cleaned ${cleaned.length} reserved filename(s)`);
|
||||
}
|
||||
else {
|
||||
core.info('[Reliability] No reserved filenames found');
|
||||
}
|
||||
return cleaned;
|
||||
}
|
||||
/**
|
||||
* Create a tar.gz archive of build output.
|
||||
*/
|
||||
static archiveBuildOutput(sourcePath, archivePath) {
|
||||
if (!node_fs_1.default.existsSync(sourcePath)) {
|
||||
core.info(`[Reliability] No build output to archive at ${sourcePath}`);
|
||||
return;
|
||||
}
|
||||
node_fs_1.default.mkdirSync(archivePath, { recursive: true });
|
||||
const timestamp = new Date().toISOString().replace(/[.:]/g, '-');
|
||||
const archiveFile = node_path_1.default.join(archivePath, `build-${timestamp}.tar.gz`);
|
||||
try {
|
||||
(0, node_child_process_1.execSync)(`tar -czf "${archiveFile}" -C "${node_path_1.default.dirname(sourcePath)}" "${node_path_1.default.basename(sourcePath)}"`, {
|
||||
encoding: 'utf8',
|
||||
timeout: 600000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
core.info(`[Reliability] Build output archived to ${archiveFile}`);
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`[Reliability] Failed to archive build output: ${error.stderr?.toString() ?? error.message}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Enforce retention policy -- delete archives older than the retention period.
|
||||
* Returns the number of old archives removed.
|
||||
*/
|
||||
static enforceRetention(archivePath, retentionDays) {
|
||||
if (!node_fs_1.default.existsSync(archivePath)) {
|
||||
return 0;
|
||||
}
|
||||
const now = Date.now();
|
||||
const retentionMs = retentionDays * 24 * 60 * 60 * 1000;
|
||||
let removed = 0;
|
||||
try {
|
||||
const entries = node_fs_1.default.readdirSync(archivePath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const fullPath = node_path_1.default.join(archivePath, entry.name);
|
||||
try {
|
||||
const stat = node_fs_1.default.statSync(fullPath);
|
||||
const ageMs = now - stat.mtimeMs;
|
||||
if (ageMs > retentionMs) {
|
||||
if (entry.isDirectory()) {
|
||||
node_fs_1.default.rmSync(fullPath, { recursive: true, force: true });
|
||||
}
|
||||
else {
|
||||
node_fs_1.default.unlinkSync(fullPath);
|
||||
}
|
||||
removed++;
|
||||
core.info(`[Reliability] Removed old archive: ${entry.name} (age: ${Math.round(ageMs / (24 * 60 * 60 * 1000))} days)`);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
core.warning(`[Reliability] Could not process archive entry: ${fullPath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
core.warning(`[Reliability] Could not read archive directory: ${archivePath}`);
|
||||
return 0;
|
||||
}
|
||||
if (removed > 0) {
|
||||
core.info(`[Reliability] Retention enforced: removed ${removed} old archive(s), retention: ${retentionDays} days`);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/**
|
||||
* Configure git environment variables for CI reliability.
|
||||
* Sets GIT_TERMINAL_PROMPT=0, increases http.postBuffer, enables core.longpaths.
|
||||
*/
|
||||
static configureGitEnvironment() {
|
||||
core.info('[Reliability] Configuring git environment for CI');
|
||||
// Prevent git from prompting for credentials (hangs in CI)
|
||||
process.env.GIT_TERMINAL_PROMPT = '0';
|
||||
core.info('[Reliability] Set GIT_TERMINAL_PROMPT=0');
|
||||
try {
|
||||
// Increase http.postBuffer to 500MB for large pushes
|
||||
(0, node_child_process_1.execSync)('git config --global http.postBuffer 524288000', {
|
||||
encoding: 'utf8',
|
||||
timeout: 10000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
core.info('[Reliability] Set http.postBuffer=524288000 (500MB)');
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`[Reliability] Could not set http.postBuffer: ${error.message}`);
|
||||
}
|
||||
try {
|
||||
// Enable long paths on Windows
|
||||
(0, node_child_process_1.execSync)('git config --global core.longpaths true', {
|
||||
encoding: 'utf8',
|
||||
timeout: 10000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
core.info('[Reliability] Set core.longpaths=true');
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`[Reliability] Could not set core.longpaths: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.BuildReliabilityService = BuildReliabilityService;
|
||||
// Windows reserved device names that cause Unity asset importer infinite loops
|
||||
BuildReliabilityService.RESERVED_NAMES = new Set([
|
||||
'con',
|
||||
'prn',
|
||||
'aux',
|
||||
'nul',
|
||||
'com1',
|
||||
'com2',
|
||||
'com3',
|
||||
'com4',
|
||||
'com5',
|
||||
'com6',
|
||||
'com7',
|
||||
'com8',
|
||||
'com9',
|
||||
'lpt1',
|
||||
'lpt2',
|
||||
'lpt3',
|
||||
'lpt4',
|
||||
'lpt5',
|
||||
'lpt6',
|
||||
'lpt7',
|
||||
'lpt8',
|
||||
'lpt9',
|
||||
]);
|
||||
// Lock files to look for in the .git directory
|
||||
BuildReliabilityService.LOCK_FILE_NAMES = new Set(['index.lock', 'shallow.lock', 'config.lock', 'HEAD.lock']);
|
||||
// Maximum age in milliseconds before a lock file is considered stale (10 minutes)
|
||||
BuildReliabilityService.LOCK_FILE_MAX_AGE_MS = 10 * 60 * 1000;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9842:
|
||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.BuildReliabilityService = void 0;
|
||||
var build_reliability_service_1 = __nccwpck_require__(37347);
|
||||
Object.defineProperty(exports, "BuildReliabilityService", ({ enumerable: true, get: function () { return build_reliability_service_1.BuildReliabilityService; } }));
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 23451:
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user