mirror of
https://github.com/SonarSource/sonarqube-scan-action.git
synced 2025-12-12 17:31:15 +00:00
SQSCANGHA-112 Migrate installation step
This commit is contained in:
parent
8f448484d9
commit
ed9f3aad50
12 changed files with 2963 additions and 216 deletions
124
.github/workflows/qa-main.yml
vendored
124
.github/workflows/qa-main.yml
vendored
|
|
@ -13,7 +13,7 @@ jobs:
|
||||||
No inputs
|
No inputs
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -32,7 +32,7 @@ jobs:
|
||||||
'args' input
|
'args' input
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -55,8 +55,12 @@ jobs:
|
||||||
'args' input with command injection will fail
|
'args' input with command injection will fail
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
args: [ -Dsonar.someArg=aValue && echo "Injection", -Dsonar.someArg="value\"; whoami; echo \"" ]
|
args:
|
||||||
|
[
|
||||||
|
-Dsonar.someArg=aValue && echo "Injection",
|
||||||
|
-Dsonar.someArg="value\"; whoami; echo \"",
|
||||||
|
]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -81,7 +85,7 @@ jobs:
|
||||||
'args' input with backticks injection does not execute command
|
'args' input with backticks injection does not execute command
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -109,7 +113,7 @@ jobs:
|
||||||
'args' input with dollar command injection does not execute command
|
'args' input with dollar command injection does not execute command
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -136,7 +140,7 @@ jobs:
|
||||||
'args' input with other command injection variants does not execute command
|
'args' input with other command injection variants does not execute command
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -166,7 +170,7 @@ jobs:
|
||||||
'projectBaseDir' input
|
'projectBaseDir' input
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -203,7 +207,12 @@ jobs:
|
||||||
SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}'
|
SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}'
|
||||||
- name: Assert
|
- name: Assert
|
||||||
run: |
|
run: |
|
||||||
./test/assertFileExists "$RUNNER_TEMP/sonarscanner/sonar-scanner-cli-6.1.0.4477-linux-x64.zip"
|
# The new JavaScript implementation uses @actions/tool-cache which caches tools differently
|
||||||
|
# Instead of checking for the zip file, verify the tool was installed by checking it's in PATH
|
||||||
|
if ! command -v sonar-scanner &> /dev/null; then
|
||||||
|
echo "Error: sonar-scanner not found in PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
scannerBinariesUrlTest:
|
scannerBinariesUrlTest:
|
||||||
name: >
|
name: >
|
||||||
'scannerBinariesUrl' input with invalid URL
|
'scannerBinariesUrl' input with invalid URL
|
||||||
|
|
@ -245,7 +254,7 @@ jobs:
|
||||||
uses: ./
|
uses: ./
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
scannerBinariesUrl: 'http://some_uri;touch file.txt;'
|
scannerBinariesUrl: "http://some_uri;touch file.txt;"
|
||||||
env:
|
env:
|
||||||
NO_CACHE: true
|
NO_CACHE: true
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
SONAR_HOST_URL: http://not_actually_used
|
||||||
|
|
@ -274,7 +283,7 @@ jobs:
|
||||||
uses: ./
|
uses: ./
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
scannerBinariesUrl: 'http://some_uri http://another_uri''; touch file.txt;'
|
scannerBinariesUrl: "http://some_uri http://another_uri'; touch file.txt;"
|
||||||
env:
|
env:
|
||||||
NO_CACHE: true
|
NO_CACHE: true
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
SONAR_HOST_URL: http://not_actually_used
|
||||||
|
|
@ -381,7 +390,7 @@ jobs:
|
||||||
'RUNNER_DEBUG' is used
|
'RUNNER_DEBUG' is used
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -440,7 +449,7 @@ jobs:
|
||||||
'SONARCLOUD_URL' is used
|
'SONARCLOUD_URL' is used
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
@ -457,91 +466,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
./test/assertFileContains ./output.properties "sonar.host.url=mirror.sonarcloud.io"
|
./test/assertFileContains ./output.properties "sonar.host.url=mirror.sonarcloud.io"
|
||||||
./test/assertFileContains ./output.properties "sonar.scanner.sonarcloudUrl=mirror.sonarcloud.io"
|
./test/assertFileContains ./output.properties "sonar.scanner.sonarcloudUrl=mirror.sonarcloud.io"
|
||||||
dontFailWhenMissingWgetButCurlAvailable:
|
|
||||||
name: Don't fail when missing wget but curl available
|
|
||||||
runs-on: github-ubuntu-latest-s
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Remove wget
|
|
||||||
run: sudo apt-get remove -y wget
|
|
||||||
- name: Assert wget is not available
|
|
||||||
run: |
|
|
||||||
if command -v wget 2>&1 >/dev/null
|
|
||||||
then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- name: Run action
|
|
||||||
uses: ./
|
|
||||||
env:
|
|
||||||
NO_CACHE: true
|
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
|
||||||
SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}'
|
|
||||||
with:
|
|
||||||
args: -Dsonar.scanner.internal.dumpToFile=./output.properties
|
|
||||||
- name: Assert
|
|
||||||
run: |
|
|
||||||
./test/assertFileExists ./output.properties
|
|
||||||
dontFailWhenMissingCurlButWgetAvailable:
|
|
||||||
name: Don't fail when missing curl but wget available
|
|
||||||
runs-on: github-ubuntu-latest-s
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Remove curl
|
|
||||||
run: sudo apt-get remove -y curl
|
|
||||||
- name: Assert curl is not available
|
|
||||||
run: |
|
|
||||||
if command -v curl 2>&1 >/dev/null
|
|
||||||
then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- name: Run action
|
|
||||||
id: runTest
|
|
||||||
uses: ./
|
|
||||||
env:
|
|
||||||
NO_CACHE: true
|
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
|
||||||
SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}'
|
|
||||||
with:
|
|
||||||
args: -Dsonar.scanner.internal.dumpToFile=./output.properties
|
|
||||||
- name: Assert
|
|
||||||
run: |
|
|
||||||
./test/assertFileExists ./output.properties
|
|
||||||
failWhenBothWgetAndCurlMissing:
|
|
||||||
name: Fail when both wget and curl are missing
|
|
||||||
runs-on: github-ubuntu-latest-s
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Remove wget and curl
|
|
||||||
run: sudo apt-get remove -y wget curl
|
|
||||||
- name: Assert wget and curl are not available
|
|
||||||
run: |
|
|
||||||
if command -v wget 2>&1 >/dev/null
|
|
||||||
then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if command -v curl 2>&1 >/dev/null
|
|
||||||
then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- name: Run action
|
|
||||||
id: runTest
|
|
||||||
uses: ./
|
|
||||||
continue-on-error: true
|
|
||||||
env:
|
|
||||||
NO_CACHE: true
|
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
|
||||||
SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}'
|
|
||||||
with:
|
|
||||||
args: -Dsonar.scanner.internal.dumpToFile=./output.properties
|
|
||||||
- name: Assert failure of previous step
|
|
||||||
if: steps.runTest.outcome == 'success'
|
|
||||||
run: exit 1
|
|
||||||
curlPerformsRedirect:
|
curlPerformsRedirect:
|
||||||
name: >
|
name: >
|
||||||
curl performs redirect when scannerBinariesUrl returns 3xx
|
curl performs redirect when scannerBinariesUrl returns 3xx
|
||||||
|
|
@ -566,7 +490,7 @@ jobs:
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
scannerVersion: 6.2.1.4610
|
scannerVersion: 6.2.1.4610
|
||||||
scannerBinariesUrl: http://localhost:8080/clientRedirectToSonarBinaries
|
scannerBinariesUrl: https://localhost:8080/clientRedirectToSonarBinaries
|
||||||
env:
|
env:
|
||||||
NO_CACHE: true
|
NO_CACHE: true
|
||||||
SONAR_HOST_URL: http://not_actually_used
|
SONAR_HOST_URL: http://not_actually_used
|
||||||
|
|
@ -579,7 +503,7 @@ jobs:
|
||||||
'SONAR_ROOT_CERT' is converted to truststore
|
'SONAR_ROOT_CERT' is converted to truststore
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ github-ubuntu-latest-s, github-windows-latest-s, macos-latest ]
|
os: [github-ubuntu-latest-s, github-windows-latest-s, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
|
||||||
25
.github/workflows/unit-tests.yml
vendored
Normal file
25
.github/workflows/unit-tests.yml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
name: Unit tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
22
action.yml
22
action.yml
|
|
@ -30,32 +30,14 @@ runs:
|
||||||
# with:
|
# with:
|
||||||
# ref: "jay/js-rewrite"
|
# ref: "jay/js-rewrite"
|
||||||
|
|
||||||
- name: Sanity checks
|
- name: Sanity checks & setup
|
||||||
run: node ./dist/index.js
|
run: node ./dist/index.js
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }}
|
INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }}
|
||||||
INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }}
|
INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }}
|
||||||
|
|
||||||
- name: Load Sonar Scanner CLI from cache
|
|
||||||
id: sonar-scanner-cli
|
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
|
||||||
env:
|
|
||||||
# The default value is 60mins. Reaching timeout is treated the same as a cache miss.
|
|
||||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
|
||||||
with:
|
|
||||||
path: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}
|
|
||||||
key: sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}
|
|
||||||
- name: Install Sonar Scanner CLI
|
|
||||||
if: ${{ env.NO_CACHE == 'true' || steps.sonar-scanner-cli.outputs.cache-hit != 'true' }}
|
|
||||||
run: ${GITHUB_ACTION_PATH}/scripts/install-sonar-scanner-cli.sh
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }}
|
|
||||||
INPUT_SCANNERBINARIESURL: ${{ inputs.scannerBinariesUrl }}
|
INPUT_SCANNERBINARIESURL: ${{ inputs.scannerBinariesUrl }}
|
||||||
- name: Add SonarScanner CLI to the PATH
|
|
||||||
run: echo "${RUNNER_TEMP}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/bin" >> $GITHUB_PATH
|
|
||||||
shell: bash
|
|
||||||
- name: Run SonarScanner
|
- name: Run SonarScanner
|
||||||
run: ${GITHUB_ACTION_PATH}/scripts/run-sonar-scanner.sh
|
run: ${GITHUB_ACTION_PATH}/scripts/run-sonar-scanner.sh
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
2725
dist/index.js
vendored
2725
dist/index.js
vendored
File diff suppressed because it is too large
Load diff
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
47
dist/sanity-checks.js
vendored
47
dist/sanity-checks.js
vendored
|
|
@ -1,47 +0,0 @@
|
||||||
import fs from 'fs';
|
|
||||||
import { join } from 'path';
|
|
||||||
|
|
||||||
function validateScannerVersion(version) {
|
|
||||||
if (!version) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionRegex = /^\d+\.\d+\.\d+\.\d+$/;
|
|
||||||
if (!versionRegex.test(version)) {
|
|
||||||
throw new Error(
|
|
||||||
"Invalid scannerVersion format. Expected format: x.y.z.w (e.g., 7.1.0.4889)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkSonarToken(core) {
|
|
||||||
if (!process.env.SONAR_TOKEN) {
|
|
||||||
core.warning(
|
|
||||||
"Running this GitHub Action without SONAR_TOKEN is not recommended"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkMavenProject(core, projectBaseDir) {
|
|
||||||
const pomPath = join(projectBaseDir.replace(/\/$/, ""), "pom.xml");
|
|
||||||
if (fs.existsSync(pomPath)) {
|
|
||||||
core.warning(
|
|
||||||
"Maven project detected. Sonar recommends running the 'org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' goal during the build process instead of using this GitHub Action to get more accurate results."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkGradleProject(core, projectBaseDir) {
|
|
||||||
const baseDir = projectBaseDir.replace(/\/$/, "");
|
|
||||||
const gradlePath = join(baseDir, "build.gradle");
|
|
||||||
const gradleKtsPath = join(baseDir, "build.gradle.kts");
|
|
||||||
|
|
||||||
if (fs.existsSync(gradlePath) || fs.existsSync(gradleKtsPath)) {
|
|
||||||
core.warning(
|
|
||||||
"Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action to get more accurate results."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { checkGradleProject, checkMavenProject, checkSonarToken, validateScannerVersion };
|
|
||||||
//# sourceMappingURL=sanity-checks.js.map
|
|
||||||
1
dist/sanity-checks.js.map
vendored
1
dist/sanity-checks.js.map
vendored
|
|
@ -1 +0,0 @@
|
||||||
{"version":3,"file":"sanity-checks.js","sources":["../src/sanity-checks.js"],"sourcesContent":["import fs from \"fs\";\nimport { join } from \"path\";\n\nexport function validateScannerVersion(version) {\n if (!version) {\n return;\n }\n\n const versionRegex = /^\\d+\\.\\d+\\.\\d+\\.\\d+$/;\n if (!versionRegex.test(version)) {\n throw new Error(\n \"Invalid scannerVersion format. Expected format: x.y.z.w (e.g., 7.1.0.4889)\"\n );\n }\n}\n\nexport function checkSonarToken(core) {\n if (!process.env.SONAR_TOKEN) {\n core.warning(\n \"Running this GitHub Action without SONAR_TOKEN is not recommended\"\n );\n }\n}\n\nexport function checkMavenProject(core, projectBaseDir) {\n const pomPath = join(projectBaseDir.replace(/\\/$/, \"\"), \"pom.xml\");\n if (fs.existsSync(pomPath)) {\n core.warning(\n \"Maven project detected. Sonar recommends running the 'org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' goal during the build process instead of using this GitHub Action to get more accurate results.\"\n );\n }\n}\n\nexport function checkGradleProject(core, projectBaseDir) {\n const baseDir = projectBaseDir.replace(/\\/$/, \"\");\n const gradlePath = join(baseDir, \"build.gradle\");\n const gradleKtsPath = join(baseDir, \"build.gradle.kts\");\n\n if (fs.existsSync(gradlePath) || fs.existsSync(gradleKtsPath)) {\n core.warning(\n \"Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action to get more accurate results.\"\n );\n }\n}\n"],"names":[],"mappings":";;;AAGO,SAAS,sBAAsB,CAAC,OAAO,EAAE;AAChD,EAAE,IAAI,CAAC,OAAO,EAAE;AAChB,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,YAAY,GAAG,sBAAsB;AAC7C,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACnC,IAAI,MAAM,IAAI,KAAK;AACnB,MAAM;AACN,KAAK;AACL,EAAE;AACF;;AAEO,SAAS,eAAe,CAAC,IAAI,EAAE;AACtC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE;AAChC,IAAI,IAAI,CAAC,OAAO;AAChB,MAAM;AACN,KAAK;AACL,EAAE;AACF;;AAEO,SAAS,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE;AACxD,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC;AACpE,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;AAC9B,IAAI,IAAI,CAAC,OAAO;AAChB,MAAM;AACN,KAAK;AACL,EAAE;AACF;;AAEO,SAAS,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE;AACzD,EAAE,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AACnD,EAAE,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC;AAClD,EAAE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;;AAEzD,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;AACjE,IAAI,IAAI,CAAC,OAAO;AAChB,MAAM;AACN,KAAK;AACL,EAAE;AACF;;;;"}
|
|
||||||
25
package-lock.json
generated
25
package-lock.json
generated
|
|
@ -13,6 +13,7 @@
|
||||||
"@actions/github": "6.0.1"
|
"@actions/github": "6.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@actions/tool-cache": "^2.0.2",
|
||||||
"@rollup/plugin-commonjs": "28.0.6",
|
"@rollup/plugin-commonjs": "28.0.6",
|
||||||
"@rollup/plugin-node-resolve": "16.0.1",
|
"@rollup/plugin-node-resolve": "16.0.1",
|
||||||
"mock-fs": "^5.5.0",
|
"mock-fs": "^5.5.0",
|
||||||
|
|
@ -69,6 +70,20 @@
|
||||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@actions/tool-cache": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "^1.11.1",
|
||||||
|
"@actions/exec": "^1.0.0",
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"@actions/io": "^1.1.1",
|
||||||
|
"semver": "^6.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@fastify/busboy": {
|
"node_modules/@fastify/busboy": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||||
|
|
@ -862,6 +877,16 @@
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-preserve-symlinks-flag": {
|
"node_modules/supports-preserve-symlinks-flag": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@
|
||||||
"license": "LGPL-3.0-only",
|
"license": "LGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"@actions/github": "6.0.1"
|
"@actions/github": "6.0.1",
|
||||||
|
"@actions/tool-cache": "2.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "28.0.6",
|
"@rollup/plugin-commonjs": "28.0.6",
|
||||||
"@rollup/plugin-node-resolve": "16.0.1",
|
"@rollup/plugin-node-resolve": "16.0.1",
|
||||||
"mock-fs": "^5.5.0",
|
"mock-fs": "5.5.0",
|
||||||
"rollup": "4.50.1"
|
"rollup": "4.50.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
81
src/__tests__/utils.test.js
Normal file
81
src/__tests__/utils.test.js
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { describe, it } from "node:test";
|
||||||
|
import {
|
||||||
|
getPlatformFlavor,
|
||||||
|
getScannerDownloadURL,
|
||||||
|
scannerDirName,
|
||||||
|
} from "../utils.js";
|
||||||
|
|
||||||
|
describe("getPlatformFlavor", () => {
|
||||||
|
const supportedPlatforms = [
|
||||||
|
{ platform: "linux", arch: "x64", expected: "linux-x64" },
|
||||||
|
{ platform: "linux", arch: "arm64", expected: "linux-aarch64" },
|
||||||
|
{ platform: "win32", arch: "x64", expected: "windows-x64" },
|
||||||
|
{ platform: "darwin", arch: "x64", expected: "macosx-x64" },
|
||||||
|
{ platform: "darwin", arch: "arm64", expected: "macosx-aarch64" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const unsupportedPlatforms = [
|
||||||
|
{ platform: "linux", arch: "arm" },
|
||||||
|
{ platform: "openbsd", arch: "x64" },
|
||||||
|
{ platform: undefined, arch: "x64" },
|
||||||
|
{ platform: "linux", arch: undefined },
|
||||||
|
{ platform: null, arch: "x64" },
|
||||||
|
{ platform: "linux", arch: null },
|
||||||
|
];
|
||||||
|
|
||||||
|
supportedPlatforms.forEach(({ platform, arch, expected }) => {
|
||||||
|
it(`returns ${expected} for ${platform} ${arch}`, () => {
|
||||||
|
assert.equal(getPlatformFlavor(platform, arch), expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
unsupportedPlatforms.forEach(({ platform, arch }) => {
|
||||||
|
it(`throws for unsupported platform ${platform} ${arch}`, () => {
|
||||||
|
assert.throws(
|
||||||
|
() => getPlatformFlavor(platform, arch),
|
||||||
|
{
|
||||||
|
message: `Platform ${platform} ${arch} not supported`,
|
||||||
|
},
|
||||||
|
`should have thrown for ${platform} ${arch}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getScannerDownloadURL", () => {
|
||||||
|
it("generates correct URL without trailing slash", () => {
|
||||||
|
const result = getScannerDownloadURL({
|
||||||
|
scannerBinariesUrl:
|
||||||
|
"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli",
|
||||||
|
scannerVersion: "7.2.0.5079",
|
||||||
|
flavor: "linux-x64",
|
||||||
|
});
|
||||||
|
assert.equal(
|
||||||
|
result,
|
||||||
|
"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.2.0.5079-linux-x64.zip"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("generates correct URL with trailing slash", () => {
|
||||||
|
const result = getScannerDownloadURL({
|
||||||
|
scannerBinariesUrl:
|
||||||
|
"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/",
|
||||||
|
scannerVersion: "7.2.0.5079",
|
||||||
|
flavor: "linux-x64",
|
||||||
|
});
|
||||||
|
assert.equal(
|
||||||
|
result,
|
||||||
|
"https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.2.0.5079-linux-x64.zip"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("scannerDirName", () => {
|
||||||
|
it("handles special characters", () => {
|
||||||
|
assert.equal(
|
||||||
|
scannerDirName("7.2.0-SNAPSHOT", "linux_x64"),
|
||||||
|
"sonar-scanner-7.2.0-SNAPSHOT-linux_x64"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
71
src/index.js
71
src/index.js
|
|
@ -1,19 +1,28 @@
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import * as tc from "@actions/tool-cache";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as path from "path";
|
||||||
import {
|
import {
|
||||||
checkGradleProject,
|
checkGradleProject,
|
||||||
checkMavenProject,
|
checkMavenProject,
|
||||||
checkSonarToken,
|
checkSonarToken,
|
||||||
validateScannerVersion,
|
validateScannerVersion,
|
||||||
} from "./sanity-checks";
|
} from "./sanity-checks";
|
||||||
|
import {
|
||||||
|
getPlatformFlavor,
|
||||||
|
getScannerDownloadURL,
|
||||||
|
scannerDirName,
|
||||||
|
} from "./utils";
|
||||||
|
|
||||||
|
const TOOLNAME = "sonar-scanner-cli";
|
||||||
|
|
||||||
function getInputs() {
|
function getInputs() {
|
||||||
//FIXME: should not rely on ENV vars
|
//FIXME: should not rely on ENV vars
|
||||||
const scannerVersion = process.env.INPUT_SCANNERVERSION; // core.getInput("scannerVersion");
|
const scannerVersion = process.env.INPUT_SCANNERVERSION; // core.getInput("scannerVersion");
|
||||||
const projectBaseDir = process.env.INPUT_PROJECTBASEDIR; // core.getInput("projectBaseDir") || ".";
|
const projectBaseDir = process.env.INPUT_PROJECTBASEDIR; // core.getInput("projectBaseDir") || ".";
|
||||||
|
const scannerBinariesUrl = process.env.INPUT_SCANNERBINARIESURL; // core.getInput("scannerBinariesUrl");
|
||||||
|
|
||||||
console.log("scannerVersion: ", scannerVersion);
|
return { scannerVersion, projectBaseDir, scannerBinariesUrl };
|
||||||
|
|
||||||
return { scannerVersion, projectBaseDir };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSanityChecks(inputs) {
|
function runSanityChecks(inputs) {
|
||||||
|
|
@ -30,10 +39,62 @@ function runSanityChecks(inputs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
async function installSonarScannerCLI(scannerVersion, scannerBinariesUrl) {
|
||||||
const inputs = getInputs();
|
const flavor = getPlatformFlavor(os.platform(), os.arch());
|
||||||
|
|
||||||
|
// Check if tool is already cached
|
||||||
|
let toolDir = tc.find(TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
|
if (!toolDir) {
|
||||||
|
console.log(
|
||||||
|
`Installing Sonar Scanner CLI ${scannerVersion} for ${flavor}...`
|
||||||
|
);
|
||||||
|
|
||||||
|
const downloadUrl = getScannerDownloadURL({
|
||||||
|
scannerBinariesUrl,
|
||||||
|
scannerVersion,
|
||||||
|
flavor,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Downloading from: ${downloadUrl}`);
|
||||||
|
|
||||||
|
const downloadPath = await tc.downloadTool(downloadUrl);
|
||||||
|
const extractedPath = await tc.extractZip(downloadPath);
|
||||||
|
|
||||||
|
// Find the actual scanner directory inside the extracted folder
|
||||||
|
const scannerPath = path.join(
|
||||||
|
extractedPath,
|
||||||
|
scannerDirName(scannerVersion, flavor)
|
||||||
|
);
|
||||||
|
|
||||||
|
toolDir = await tc.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
|
console.log(`Sonar Scanner CLI cached to: ${toolDir}`);
|
||||||
|
} else {
|
||||||
|
console.log(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the bin directory to PATH
|
||||||
|
const binDir = path.join(toolDir, "bin");
|
||||||
|
core.addPath(binDir);
|
||||||
|
|
||||||
|
return toolDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const inputs = getInputs();
|
||||||
|
const { scannerVersion, scannerBinariesUrl } = inputs;
|
||||||
|
|
||||||
|
// Run sanity checks first
|
||||||
runSanityChecks(inputs);
|
runSanityChecks(inputs);
|
||||||
|
|
||||||
|
// Install Sonar Scanner CLI using @actions/tool-cache
|
||||||
|
await installSonarScannerCLI(scannerVersion, scannerBinariesUrl);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Action failed: ${error.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
|
||||||
35
src/utils.js
Normal file
35
src/utils.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
const platformFlavor = {
|
||||||
|
linux: {
|
||||||
|
x64: "linux-x64",
|
||||||
|
arm64: "linux-aarch64",
|
||||||
|
},
|
||||||
|
win32: {
|
||||||
|
x64: "windows-x64",
|
||||||
|
},
|
||||||
|
darwin: {
|
||||||
|
x64: "macosx-x64",
|
||||||
|
arm64: "macosx-aarch64",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getPlatformFlavor(platform, arch) {
|
||||||
|
const flavor = platformFlavor[platform]?.[arch];
|
||||||
|
|
||||||
|
if (!flavor) {
|
||||||
|
throw new Error(`Platform ${platform} ${arch} not supported`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flavor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getScannerDownloadURL({
|
||||||
|
scannerBinariesUrl,
|
||||||
|
scannerVersion,
|
||||||
|
flavor,
|
||||||
|
}) {
|
||||||
|
const trimURL = scannerBinariesUrl.replace(/\/$/, "");
|
||||||
|
return `${trimURL}/sonar-scanner-cli-${scannerVersion}-${flavor}.zip`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const scannerDirName = (version, flavor) =>
|
||||||
|
`sonar-scanner-${version}-${flavor}`;
|
||||||
Loading…
Reference in a new issue