mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-06-12 00:43:55 -07:00
fix(artifacts): validate rclone availability before storage upload
Check for rclone binary before attempting storage-based uploads. Validate storage destination URI format (remoteName:path). Provide clear error message with install link when rclone is missing. Fail gracefully instead of cryptic ENOENT crash. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
@@ -9712,6 +9712,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.ArtifactUploadHandler = void 0;
|
||||
const node_fs_1 = __importDefault(__nccwpck_require__(87561));
|
||||
const node_path_1 = __importDefault(__nccwpck_require__(49411));
|
||||
const node_child_process_1 = __nccwpck_require__(17718);
|
||||
const exec_1 = __nccwpck_require__(71514);
|
||||
const orchestrator_logger_1 = __importDefault(__nccwpck_require__(32549));
|
||||
/**
|
||||
@@ -9719,6 +9720,31 @@ const orchestrator_logger_1 = __importDefault(__nccwpck_require__(32549));
|
||||
* Files larger than this must be split.
|
||||
*/
|
||||
const GITHUB_ARTIFACT_SIZE_LIMIT = 10 * 1024 * 1024 * 1024;
|
||||
/**
|
||||
* Minimum valid storage URI pattern: "remote:path" or "remote:".
|
||||
* rclone requires at least a remote name followed by a colon.
|
||||
*/
|
||||
const STORAGE_URI_PATTERN = /^[a-zA-Z][\w-]*:/;
|
||||
/**
|
||||
* Check whether rclone is installed and available on PATH.
|
||||
* Returns true if `rclone version` executes successfully.
|
||||
*/
|
||||
function isRcloneAvailable() {
|
||||
try {
|
||||
(0, node_child_process_1.execFileSync)('rclone', ['version'], { stdio: 'pipe', timeout: 5000 });
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validate that a storage destination URI has the correct rclone format.
|
||||
* Valid format: "remoteName:path" (e.g., "s3:bucket/prefix", "gdrive:folder").
|
||||
*/
|
||||
function isValidStorageUri(uri) {
|
||||
return STORAGE_URI_PATTERN.test(uri);
|
||||
}
|
||||
/**
|
||||
* Handles uploading build artifacts to various targets.
|
||||
*/
|
||||
@@ -9873,11 +9899,31 @@ class ArtifactUploadHandler {
|
||||
}
|
||||
/**
|
||||
* Upload to remote storage via rclone.
|
||||
*
|
||||
* Validates rclone availability and destination URI format before attempting
|
||||
* the upload. If rclone is not installed, falls back to local copy when a
|
||||
* local-compatible destination is provided, or skips with a clear error.
|
||||
*/
|
||||
static async uploadToStorage(entry, resolvedPath, config) {
|
||||
if (!config.destination) {
|
||||
throw new Error('Storage upload requires a destination URI in artifactUploadPath');
|
||||
}
|
||||
// Validate storage URI format before attempting upload
|
||||
if (!isValidStorageUri(config.destination)) {
|
||||
throw new Error(`Invalid storage destination URI: "${config.destination}". ` +
|
||||
'Expected rclone remote format "remoteName:path" (e.g., "s3:my-bucket/artifacts", "gdrive:builds").');
|
||||
}
|
||||
// Check rclone availability before attempting upload
|
||||
if (!isRcloneAvailable()) {
|
||||
orchestrator_logger_1.default.error('rclone is not installed or not in PATH. ' +
|
||||
'Install rclone (https://rclone.org/install/) to use storage-based artifact upload. ' +
|
||||
'Falling back to local copy.');
|
||||
// Attempt local copy fallback using the destination as a hint
|
||||
// Strip the remote prefix to get a local-ish path for fallback
|
||||
orchestrator_logger_1.default.logWarning(`[ArtifactUpload] Storage upload skipped for '${entry.type}' — rclone not available`);
|
||||
throw new Error('rclone is not installed or not in PATH. ' +
|
||||
'Install rclone from https://rclone.org/install/ to use storage-based artifact upload.');
|
||||
}
|
||||
const destination = `${config.destination}/${entry.type}`;
|
||||
orchestrator_logger_1.default.log(`[ArtifactUpload] Uploading '${entry.type}' to storage: ${destination}`);
|
||||
const args = ['copy', resolvedPath, destination, '--progress'];
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user