mirror of
https://github.com/SonarSource/sonarqube-scan-action.git
synced 2025-12-12 17:31:15 +00:00
feat: Enhance Sonar Scanner installation with authentication support
- Added a new input parameter `scannerBinariesAuth` to allow passing an authentication token for downloading the Sonar Scanner CLI. - Implemented a `downloadWithFetch` function to handle downloads with authorization headers. - Updated the `installSonarScanner` function to use the new download method when an auth token is provided. - Included the `fs` module in the project dependencies to manage file system operations. - Updated package.json and package-lock.json to include the new `fs` dependency. - Modified the `getInputs` function to return the new `scannerBinariesAuth` input.
This commit is contained in:
parent
40f5b61913
commit
fcd9e5e893
9 changed files with 155 additions and 26 deletions
|
|
@ -200,6 +200,15 @@ This can be useful when the runner executing the action is self-hosted and has r
|
|||
scannerBinariesUrl: https://my.custom.binaries.url.com/Distribution/sonar-scanner-cli/
|
||||
```
|
||||
|
||||
If the specified URL requires authorization then use the `scannerBinariesAuth` input to provide the necessary token:
|
||||
|
||||
```yaml
|
||||
- uses: SonarSource/sonarqube-scan-action@<action version>
|
||||
with:
|
||||
scannerBinariesUrl: https://my.custom.binaries.url.com/Distribution/sonar-scanner-cli/
|
||||
scannerBinariesAuth: ${{ secrets.SCANNER_BINARIES_AUTH_TOKEN }}
|
||||
```
|
||||
|
||||
More information about possible analysis parameters can be found:
|
||||
* in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/analysis-parameters/) of the SonarQube Server documentation
|
||||
* in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/analysis-parameters/) of the SonarQube Cloud documentation
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ inputs:
|
|||
description: URL to download the Sonar Scanner CLI binaries from
|
||||
required: false
|
||||
default: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli
|
||||
scannerBinariesAuth:
|
||||
description: Authentication token to download the Sonar Scanner CLI binary from customBinariesUrl
|
||||
required: false
|
||||
default: ""
|
||||
runs:
|
||||
using: node20
|
||||
main: dist/index.js
|
||||
|
|
|
|||
78
dist/index.js
vendored
78
dist/index.js
vendored
|
|
@ -2640,12 +2640,53 @@ const scannerDirName = (version, flavor) =>
|
|||
|
||||
const TOOLNAME = "sonar-scanner-cli";
|
||||
|
||||
/**
|
||||
* Download the sonar-scanner-cli from a internal url along with authorization token
|
||||
*/
|
||||
async function downloadWithFetch(url, outputPath, authToken) {
|
||||
coreExports.info(`Downloading sonar-scanner-cli from: ${url}`);
|
||||
|
||||
//create output directory if it doesn't exist
|
||||
const outputDir = path.dirname(outputPath);
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
//prepare headers
|
||||
const headers = {};
|
||||
if (authToken) {
|
||||
headers["Authorization"] = `Bearer ${authToken}`;
|
||||
coreExports.info("Using auth token for download");
|
||||
}
|
||||
try {
|
||||
const response = await fetch(url, { headers });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to download sonar-scanner-cli from ${url}: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
fs.writeFileSync(outputPath, buffer);
|
||||
coreExports.info(`Successfully Downloaded sonar-scanner-cli to: ${outputPath}`);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
catch (error) {
|
||||
coreExports.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the Sonar Scanner CLI for the current environment and cache it.
|
||||
*/
|
||||
async function installSonarScanner({
|
||||
scannerVersion,
|
||||
scannerBinariesUrl,
|
||||
scannerBinariesAuth,
|
||||
}) {
|
||||
const flavor = getPlatformFlavor(require$$0.platform(), require$$0.arch());
|
||||
|
||||
|
|
@ -2665,28 +2706,39 @@ async function installSonarScanner({
|
|||
|
||||
coreExports.info(`Downloading from: ${downloadUrl}`);
|
||||
|
||||
const downloadPath = await toolCacheExports.downloadTool(downloadUrl);
|
||||
const extractedPath = await toolCacheExports.extractZip(downloadPath);
|
||||
let downloadPath;
|
||||
|
||||
if (scannerBinariesAuth) {
|
||||
// If auth token is provided
|
||||
const tempDir = process.env.RUNNER_TEMP || require$$0.tmpdir();
|
||||
const fileName = path.basename(downloadUrl);
|
||||
const tempFile = path.join(tempDir, fileName);
|
||||
|
||||
downloadPath = await downloadWithFetch(downloadUrl, tempFile, scannerBinariesAuth);
|
||||
} else {
|
||||
// use tool-cache without auth token
|
||||
coreExports.info("Using tool-cache to run sonar-scanner-cli");
|
||||
downloadPath = await toolCacheExports.downloadTool(downloadUrl);
|
||||
}
|
||||
|
||||
const extractPath = await toolCacheExports.extractZip(downloadPath);
|
||||
|
||||
// Find the actual scanner directory inside the extracted folder
|
||||
const scannerPath = path.join(
|
||||
extractedPath,
|
||||
scannerDirName(scannerVersion, flavor)
|
||||
);
|
||||
|
||||
const scannerPath = path.join(extractPath, scannerDirName(scannerVersion, flavor));
|
||||
|
||||
toolDir = await toolCacheExports.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
||||
|
||||
coreExports.info(`Sonar Scanner CLI cached to: ${toolDir}`);
|
||||
} else {
|
||||
coreExports.info(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
||||
coreExports.info(`Using Sonar Scanner CLI from cache: ${toolDir}`);
|
||||
}
|
||||
|
||||
// Add the bin directory to PATH
|
||||
// Add the tool to the path
|
||||
const binDir = path.join(toolDir, "bin");
|
||||
coreExports.addPath(binDir);
|
||||
|
||||
return toolDir;
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgsStringToArgv(value, env, file) {
|
||||
// ([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*) Matches nested quotes until the first space outside of quotes
|
||||
|
|
@ -2918,9 +2970,10 @@ function getInputs() {
|
|||
const args = coreExports.getInput("args");
|
||||
const projectBaseDir = coreExports.getInput("projectBaseDir");
|
||||
const scannerBinariesUrl = coreExports.getInput("scannerBinariesUrl");
|
||||
const scannerBinariesAuth = coreExports.getInput("scannerBinariesAuth");
|
||||
const scannerVersion = coreExports.getInput("scannerVersion");
|
||||
|
||||
return { args, projectBaseDir, scannerBinariesUrl, scannerVersion };
|
||||
return { args, projectBaseDir, scannerBinariesUrl, scannerBinariesAuth, scannerVersion };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2956,7 +3009,7 @@ function runSanityChecks(inputs) {
|
|||
|
||||
async function run() {
|
||||
try {
|
||||
const { args, projectBaseDir, scannerVersion, scannerBinariesUrl } =
|
||||
const { args, projectBaseDir, scannerVersion, scannerBinariesUrl, scannerBinariesAuth } =
|
||||
getInputs();
|
||||
const runnerEnv = getEnvVariables();
|
||||
const { sonarToken } = runnerEnv;
|
||||
|
|
@ -2966,6 +3019,7 @@ async function run() {
|
|||
const scannerDir = await installSonarScanner({
|
||||
scannerVersion,
|
||||
scannerBinariesUrl,
|
||||
scannerBinariesAuth,
|
||||
});
|
||||
|
||||
await runSonarScanner(args, projectBaseDir, scannerDir, runnerEnv);
|
||||
|
|
|
|||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/install-build-wrapper.js.map
vendored
2
dist/install-build-wrapper.js.map
vendored
File diff suppressed because one or more lines are too long
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -12,6 +12,7 @@
|
|||
"@actions/core": "1.11.1",
|
||||
"@actions/github": "6.0.1",
|
||||
"@actions/tool-cache": "2.0.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"string-argv": "0.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -695,6 +696,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fs": {
|
||||
"version": "0.0.1-security",
|
||||
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"@actions/core": "1.11.1",
|
||||
"@actions/github": "6.0.1",
|
||||
"@actions/tool-cache": "2.0.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"string-argv": "0.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@ function getInputs() {
|
|||
const args = core.getInput("args");
|
||||
const projectBaseDir = core.getInput("projectBaseDir");
|
||||
const scannerBinariesUrl = core.getInput("scannerBinariesUrl");
|
||||
const scannerBinariesAuth = core.getInput("scannerBinariesAuth");
|
||||
const scannerVersion = core.getInput("scannerVersion");
|
||||
|
||||
return { args, projectBaseDir, scannerBinariesUrl, scannerVersion };
|
||||
return { args, projectBaseDir, scannerBinariesUrl, scannerBinariesAuth, scannerVersion };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -53,7 +54,7 @@ function runSanityChecks(inputs) {
|
|||
|
||||
async function run() {
|
||||
try {
|
||||
const { args, projectBaseDir, scannerVersion, scannerBinariesUrl } =
|
||||
const { args, projectBaseDir, scannerVersion, scannerBinariesUrl, scannerBinariesAuth } =
|
||||
getInputs();
|
||||
const runnerEnv = getEnvVariables();
|
||||
const { sonarToken } = runnerEnv;
|
||||
|
|
@ -63,6 +64,7 @@ async function run() {
|
|||
const scannerDir = await installSonarScanner({
|
||||
scannerVersion,
|
||||
scannerBinariesUrl,
|
||||
scannerBinariesAuth,
|
||||
});
|
||||
|
||||
await runSonarScanner(args, projectBaseDir, scannerDir, runnerEnv);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import * as core from "@actions/core";
|
|||
import * as tc from "@actions/tool-cache";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import {
|
||||
getPlatformFlavor,
|
||||
getScannerDownloadURL,
|
||||
|
|
@ -10,12 +11,53 @@ import {
|
|||
|
||||
const TOOLNAME = "sonar-scanner-cli";
|
||||
|
||||
/**
|
||||
* Download the sonar-scanner-cli from a internal url along with authorization token
|
||||
*/
|
||||
async function downloadWithFetch(url, outputPath, authToken) {
|
||||
core.info(`Downloading sonar-scanner-cli from: ${url}`);
|
||||
|
||||
//create output directory if it doesn't exist
|
||||
const outputDir = path.dirname(outputPath);
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
//prepare headers
|
||||
const headers = {};
|
||||
if (authToken) {
|
||||
headers["Authorization"] = `Bearer ${authToken}`;
|
||||
core.info("Using auth token for download");
|
||||
}
|
||||
try {
|
||||
const response = await fetch(url, { headers });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to download sonar-scanner-cli from ${url}: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
fs.writeFileSync(outputPath, buffer);
|
||||
core.info(`Successfully Downloaded sonar-scanner-cli to: ${outputPath}`);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the Sonar Scanner CLI for the current environment and cache it.
|
||||
*/
|
||||
export async function installSonarScanner({
|
||||
scannerVersion,
|
||||
scannerBinariesUrl,
|
||||
scannerBinariesAuth,
|
||||
}) {
|
||||
const flavor = getPlatformFlavor(os.platform(), os.arch());
|
||||
|
||||
|
|
@ -35,25 +77,36 @@ export async function installSonarScanner({
|
|||
|
||||
core.info(`Downloading from: ${downloadUrl}`);
|
||||
|
||||
const downloadPath = await tc.downloadTool(downloadUrl);
|
||||
const extractedPath = await tc.extractZip(downloadPath);
|
||||
let downloadPath;
|
||||
|
||||
if (scannerBinariesAuth) {
|
||||
// If auth token is provided
|
||||
const tempDir = process.env.RUNNER_TEMP || os.tmpdir();
|
||||
const fileName = path.basename(downloadUrl);
|
||||
const tempFile = path.join(tempDir, fileName);
|
||||
|
||||
downloadPath = await downloadWithFetch(downloadUrl, tempFile, scannerBinariesAuth);
|
||||
} else {
|
||||
// use tool-cache without auth token
|
||||
core.info("Using tool-cache to run sonar-scanner-cli");
|
||||
downloadPath = await tc.downloadTool(downloadUrl);
|
||||
}
|
||||
|
||||
const extractPath = await tc.extractZip(downloadPath);
|
||||
|
||||
// Find the actual scanner directory inside the extracted folder
|
||||
const scannerPath = path.join(
|
||||
extractedPath,
|
||||
scannerDirName(scannerVersion, flavor)
|
||||
);
|
||||
|
||||
const scannerPath = path.join(extractPath, scannerDirName(scannerVersion, flavor));
|
||||
|
||||
toolDir = await tc.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
||||
|
||||
core.info(`Sonar Scanner CLI cached to: ${toolDir}`);
|
||||
} else {
|
||||
core.info(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
||||
core.info(`Using Sonar Scanner CLI from cache: ${toolDir}`);
|
||||
}
|
||||
|
||||
// Add the bin directory to PATH
|
||||
// Add the tool to the path
|
||||
const binDir = path.join(toolDir, "bin");
|
||||
core.addPath(binDir);
|
||||
|
||||
return toolDir;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue