@@ -35979,6 +35979,21 @@ function run() {
35979
35979
var _a, _b, _c, _d, _e, _f;
35980
35980
const platform = providers_1.PlatformProviderFactory.create(providers_1.Platform.AzureDevOps);
35981
35981
try {
35982
+ // Validate required inputs
35983
+ const githubRepository = platform.input.getInput("githubRepository");
35984
+ const githubToken = platform.input.getInput("token");
35985
+ if (!githubRepository) {
35986
+ platform.logger.setFailed("githubRepository input is required. Please provide the GitHub repository in format 'owner/repo'");
35987
+ return;
35988
+ }
35989
+ if (!githubToken) {
35990
+ platform.logger.setFailed("token input is required. Please provide a GitHub Personal Access Token with 'Contents' repository permissions");
35991
+ return;
35992
+ }
35993
+ platform.logger.debug(`GitHub Repository: ${githubRepository}`);
35994
+ platform.logger.debug(`GitHub Token provided: ${githubToken ? 'Yes' : 'No'}`);
35995
+ // Set the GitHub token in environment for dependency-submission-toolkit
35996
+ process.env.GITHUB_TOKEN = githubToken;
35982
35997
let manifests = yield componentDetection_1.default.scanAndGetManifests(platform.input.getInput("filePath") || ".", platform);
35983
35998
const correlatorInput = ((_a = platform.input.getInput("correlator")) === null || _a === void 0 ? void 0 : _a.trim()) || platform.context.getJobId();
35984
35999
// Get detector configuration inputs
@@ -36143,27 +36158,68 @@ class ComponentDetection {
36143
36158
try {
36144
36159
this.platform.logger.debug(`Downloading latest release for ${process.platform}`);
36145
36160
const downloadURL = yield this.getLatestReleaseURL();
36146
- const blob = yield (yield (0, cross_fetch_1.default)(new URL(downloadURL))).blob();
36161
+ if (!downloadURL) {
36162
+ throw new Error(`No download URL found for platform: ${process.platform}`);
36163
+ }
36164
+ this.platform.logger.debug(`Download URL: ${downloadURL}`);
36165
+ const response = yield (0, cross_fetch_1.default)(new URL(downloadURL));
36166
+ if (!response.ok) {
36167
+ throw new Error(`Failed to download component-detection: ${response.status} ${response.statusText}`);
36168
+ }
36169
+ const blob = yield response.blob();
36147
36170
const arrayBuffer = yield blob.arrayBuffer();
36148
36171
const buffer = new Uint8Array(arrayBuffer);
36149
36172
// Write the blob to a file
36150
36173
this.platform.logger.debug(`Writing binary to file ${this.componentDetectionPath}`);
36151
36174
fs_1.default.writeFileSync(this.componentDetectionPath, buffer, { mode: 0o777, flag: 'w' });
36175
+ // Verify the file was created and is executable
36176
+ if (!fs_1.default.existsSync(this.componentDetectionPath)) {
36177
+ throw new Error(`Failed to create component-detection executable at ${this.componentDetectionPath}`);
36178
+ }
36179
+ this.platform.logger.debug(`Successfully downloaded and saved component-detection to ${this.componentDetectionPath}`);
36152
36180
}
36153
36181
catch (error) {
36154
- this.platform.logger.error(error);
36182
+ this.platform.logger.error(`Error downloading component-detection: ${error.message}`);
36183
+ throw error;
36155
36184
}
36156
36185
});
36157
36186
}
36158
36187
// Run the component-detection CLI on the path specified
36159
36188
static runComponentDetection(path) {
36160
36189
return __awaiter(this, void 0, void 0, function* () {
36161
36190
this.platform.logger.info("Running component-detection");
36191
+ // Verify the executable exists before trying to run it
36192
+ if (!fs_1.default.existsSync(this.componentDetectionPath)) {
36193
+ throw new Error(`Component detection executable not found at ${this.componentDetectionPath}. Download may have failed.`);
36194
+ }
36195
+ // Verify the file is executable (on Unix systems)
36196
+ if (process.platform !== "win32") {
36197
+ try {
36198
+ fs_1.default.accessSync(this.componentDetectionPath, fs_1.default.constants.X_OK);
36199
+ }
36200
+ catch (error) {
36201
+ this.platform.logger.warning(`Component detection file may not be executable. Attempting to set execute permissions.`);
36202
+ try {
36203
+ fs_1.default.chmodSync(this.componentDetectionPath, 0o755);
36204
+ }
36205
+ catch (chmodError) {
36206
+ this.platform.logger.error(`Failed to set execute permissions: ${chmodError}`);
36207
+ }
36208
+ }
36209
+ }
36210
+ const command = `${this.componentDetectionPath} scan --SourceDirectory ${path} --ManifestFile ${this.outputPath} ${this.getComponentDetectionParameters()}`;
36211
+ this.platform.logger.debug(`Executing command: ${command}`);
36162
36212
try {
36163
- yield exec.exec(`${this.componentDetectionPath} scan --SourceDirectory ${path} --ManifestFile ${this.outputPath} ${this.getComponentDetectionParameters()}`);
36213
+ yield exec.exec(command);
36214
+ // Verify the output file was created
36215
+ if (!fs_1.default.existsSync(this.outputPath)) {
36216
+ throw new Error(`Component detection completed but output file ${this.outputPath} was not created`);
36217
+ }
36218
+ this.platform.logger.debug(`Component detection completed successfully. Output file: ${this.outputPath}`);
36164
36219
}
36165
36220
catch (error) {
36166
- this.platform.logger.error(error);
36221
+ this.platform.logger.error(`Component detection execution failed: ${error.message}`);
36222
+ throw error;
36167
36223
}
36168
36224
});
36169
36225
}
@@ -36179,10 +36235,23 @@ class ComponentDetection {
36179
36235
static getManifestsFromResults() {
36180
36236
return __awaiter(this, void 0, void 0, function* () {
36181
36237
this.platform.logger.info("Getting manifests from results");
36182
- const results = yield fs_1.default.readFileSync(this.outputPath, 'utf8');
36183
- var json = JSON.parse(results);
36184
- let dependencyGraphs = this.normalizeDependencyGraphPaths(json.dependencyGraphs, this.platform.input.getInput('filePath'));
36185
- return this.processComponentsToManifests(json.componentsFound, dependencyGraphs);
36238
+ if (!fs_1.default.existsSync(this.outputPath)) {
36239
+ throw new Error(`Output file ${this.outputPath} does not exist. Component detection may have failed.`);
36240
+ }
36241
+ try {
36242
+ const results = yield fs_1.default.readFileSync(this.outputPath, 'utf8');
36243
+ if (!results.trim()) {
36244
+ this.platform.logger.warning(`Output file ${this.outputPath} is empty`);
36245
+ return [];
36246
+ }
36247
+ var json = JSON.parse(results);
36248
+ let dependencyGraphs = this.normalizeDependencyGraphPaths(json.dependencyGraphs, this.platform.input.getInput('filePath'));
36249
+ return this.processComponentsToManifests(json.componentsFound, dependencyGraphs);
36250
+ }
36251
+ catch (error) {
36252
+ this.platform.logger.error(`Failed to parse component detection results: ${error.message}`);
36253
+ throw error;
36254
+ }
36186
36255
});
36187
36256
}
36188
36257
static processComponentsToManifests(componentsFound, dependencyGraphs) {
@@ -36355,30 +36424,50 @@ class ComponentDetection {
36355
36424
if (ghesMode) {
36356
36425
githubToken = "";
36357
36426
}
36358
- const octokit = new octokit_1.Octokit({ auth: githubToken, baseUrl: githubAPIURL, request: { fetch: cross_fetch_1.default }, log: {
36427
+ // For accessing public repositories, don't use auth if no token is provided
36428
+ // This prevents "Bad credentials" errors when accessing public repos
36429
+ const octokitConfig = {
36430
+ baseUrl: githubAPIURL,
36431
+ request: { fetch: cross_fetch_1.default },
36432
+ log: {
36359
36433
debug: this.platform.logger.debug,
36360
36434
info: this.platform.logger.info,
36361
36435
warn: this.platform.logger.warning,
36362
36436
error: this.platform.logger.error
36363
- }, });
36437
+ }
36438
+ };
36439
+ // Only add auth if we have a token, since microsoft/component-detection is public
36440
+ if (githubToken) {
36441
+ octokitConfig.auth = githubToken;
36442
+ }
36443
+ const octokit = new octokit_1.Octokit(octokitConfig);
36364
36444
const owner = "microsoft";
36365
36445
const repo = "component-detection";
36366
36446
this.platform.logger.debug("Attempting to download latest release from " + githubAPIURL);
36367
36447
try {
36368
36448
const latestRelease = yield octokit.request("GET /repos/{owner}/{repo}/releases/latest", { owner, repo });
36369
36449
var downloadURL = "";
36370
36450
const assetName = process.platform === "win32" ? "component-detection-win-x64.exe" : "component-detection-linux-x64";
36451
+ this.platform.logger.debug(`Looking for asset: ${assetName}`);
36452
+ this.platform.logger.debug(`Available assets: ${latestRelease.data.assets.map(a => a.name).join(', ')}`);
36371
36453
latestRelease.data.assets.forEach((asset) => {
36372
36454
if (asset.name === assetName) {
36373
36455
downloadURL = asset.browser_download_url;
36456
+ this.platform.logger.debug(`Found matching asset: ${asset.name} -> ${downloadURL}`);
36374
36457
}
36375
36458
});
36459
+ if (!downloadURL) {
36460
+ throw new Error(`No matching asset found for platform ${process.platform}. Expected asset name: ${assetName}`);
36461
+ }
36376
36462
return downloadURL;
36377
36463
}
36378
36464
catch (error) {
36379
- this.platform.logger.error(error);
36380
- this.platform.logger.debug(error.message);
36381
- this.platform.logger.debug(error.stack);
36465
+ this.platform.logger.error(`Failed to get latest release: ${error.message}`);
36466
+ if (error.response) {
36467
+ this.platform.logger.debug(`HTTP Status: ${error.response.status}`);
36468
+ this.platform.logger.debug(`Response: ${JSON.stringify(error.response.data)}`);
36469
+ }
36470
+ this.platform.logger.debug(`Stack trace: ${error.stack}`);
36382
36471
throw new Error("Failed to download latest release");
36383
36472
}
36384
36473
});
@@ -36452,7 +36541,12 @@ class AzureDevOpsInputProvider {
36452
36541
getInput(name) {
36453
36542
// ADO task inputs are available as environment variables with INPUT_ prefix
36454
36543
const envName = `INPUT_${name.toUpperCase().replace(/-/g, '_')}`;
36455
- return process.env[envName] || '';
36544
+ const value = process.env[envName] || '';
36545
+ // Special handling for token input - also check GITHUB_TOKEN for backward compatibility
36546
+ if (name === 'token' && !value) {
36547
+ return process.env['GITHUB_TOKEN'] || '';
36548
+ }
36549
+ return value;
36456
36550
}
36457
36551
getBooleanInput(name) {
36458
36552
const value = this.getInput(name).toLowerCase();
0 commit comments