diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..86137bd
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,15 @@
+Please be aware that we are not actively looking for feature contributions.
+The truth is that it's extremely difficult for someone outside SonarSource to comply with our roadmap and expectations.
+Therefore, we typically only accept minor cosmetic changes and typo fixes.
+If you would like to see a new feature, please create a new thread in the forum ["Suggest new features"](https://community.sonarsource.com/c/suggestions/features).
+
+With that in mind, if you would like to submit a code contribution, make sure that you adhere to the following guidelines and all tests are passing:
+
+- [ ] Please explain your motives to contribute this change: what problem you are trying to fix, what improvement you are trying to make
+- [ ] Make sure any code you changed is covered by tests
+- [ ] If there is a [JIRA](http://jira.sonarsource.com/browse/SONAR) ticket available, please make your commits and pull request start with the ticket ID (SONAR-XXXX)
+
+We will try to give you feedback on your contribution as quickly as possible.
+
+Thank You!
+The SonarSource Team
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..b83b160
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,371 @@
+name: Tests
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+jobs:
+ create-install-dir-test:
+ name: create_install_path.sh script test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+
+ - name: Existing
+ shell: bash
+ env:
+ INSTALL_PATH: '.sonar'
+ run: |
+ echo "- Create dir"
+ mkdir -p "${INSTALL_PATH}"
+
+ echo "- Test script behavior"
+ ./scripts/create_install_path.sh > output
+ grep -v "::error::" output
+
+ - name: Non-existing nested in current dir
+ shell: bash
+ env:
+ INSTALL_PATH: '.sonar'
+ run: |
+ ./scripts/create_install_path.sh > output
+ grep -v "::error::" output
+ test -d "${INSTALL_PATH}"
+
+ - name: Nonexisting nested in home
+ shell: bash
+ env:
+ INSTALL_PATH: '~/third_party/.sonar'
+ run: |
+ ./scripts/create_install_path.sh > output
+ grep -v "::error::" output
+ test -d "${INSTALL_PATH}"
+
+ - name: Empty install dir specified
+ shell: bash
+ env:
+ INSTALL_PATH: ''
+ run: |
+ (./scripts/create_install_path.sh || echo "=== Script failed ===") > output
+ grep "::error::Empty installation path specified" output
+ grep "=== Script failed ===" output
+
+ - name: No permission to create directory
+ shell: bash
+ env:
+ INSTALL_PATH: '/non_creatable'
+ run: |
+ (./scripts/create_install_path.sh || echo "=== Script failed ===") > output
+ grep "::error::Failed to create non-existing installation path '/non_creatable'" output
+ grep "=== Script failed ===" output
+
+ - name: Existing but not directory
+ shell: bash
+ env:
+ INSTALL_PATH: 'not_directory'
+ run: |
+ echo "- Create normal file"
+ echo "content" > "${INSTALL_PATH}"
+
+ echo "- Test script behavior"
+ (./scripts/create_install_path.sh || echo "=== Script failed ===") > output
+ grep "::error::Installation path 'not_directory' is not a directory" output
+ grep "=== Script failed ===" output
+
+
+ - name: Existing but not readable
+ shell: bash
+ env:
+ INSTALL_PATH: 'not_readable'
+ run: |
+ echo "- Create dir and make it not readable"
+ mkdir -p "${INSTALL_PATH}"
+ chmod -r "${INSTALL_PATH}"
+
+ echo "- Test script behavior"
+ (./scripts/create_install_path.sh || echo "=== Script failed ===") > output
+ grep "::error::Installation path 'not_readable' is not readable" output
+ grep "=== Script failed ===" output
+
+ - name: Existing but not writeable
+ shell: bash
+ env:
+ INSTALL_PATH: 'not_writeable'
+ run: |
+ echo "- Create dir and make it not writeable"
+ mkdir -p "${INSTALL_PATH}"
+ chmod -w "${INSTALL_PATH}"
+
+ echo "- Test script behavior"
+ (./scripts/create_install_path.sh || echo "=== Script failed ===") > output
+ grep "::error::Installation path 'not_writeable' is not writeable" output
+ grep "=== Script failed ===" output
+
+ setup-script-test:
+ name: configure_paths.sh script test
+ runs-on: ubuntu-latest
+ env:
+ INSTALL_PATH: 'install-directory'
+ SONAR_HOST_URL: 'http://sonar-host.com'
+ SONAR_SCANNER_VERSION: 'vX.Y.Z.MMMM'
+ SONAR_SCANNER_URL_WINDOWS: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-windows.zip'
+ SONAR_SCANNER_SHA_WINDOWS: 'DOWNLOAD-SHA-WINDOWS'
+ SONAR_SCANNER_URL_LINUX: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux.zip'
+ SONAR_SCANNER_SHA_LINUX: 'DOWNLOAD-SHA-LINUX'
+ SONAR_SCANNER_URL_MACOSX: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx.zip'
+ SONAR_SCANNER_SHA_MACOSX: 'DOWNLOAD-SHA-MACOSX'
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+
+ - name: Windows
+ shell: bash
+ env:
+ OS: 'Windows'
+ ARCH: 'X64'
+ run: |
+ ./scripts/configure_paths.sh > output
+ grep -v "::error::" output
+
+ echo "- Check sonar-scanner:"
+ grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-windows.zip" output
+ grep "sonar-scanner-sha=DOWNLOAD-SHA-WINDOWS" output
+ grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-windows" output
+ grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-windows/bin/sonar-scanner.bat" output
+
+ echo "- Check build-wrapper:"
+ grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-win-x86.zip" output
+ grep "build-wrapper-dir=install-directory/build-wrapper-win-x86" output
+ grep "build-wrapper-bin=install-directory/build-wrapper-win-x86/build-wrapper-win-x86-64.exe" output
+
+ - name: Linux
+ shell: bash
+ env:
+ OS: 'Linux'
+ ARCH: 'X64'
+ run: |
+ ./scripts/configure_paths.sh > output
+ grep -v "::error::" output
+
+ echo "- Check sonar-scanner:"
+ grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux.zip" output
+ grep "sonar-scanner-sha=DOWNLOAD-SHA-LINUX" output
+ grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux" output
+ grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux/bin/sonar-scanner" output
+
+ echo "- Check build-wrapper:"
+ grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-linux-x86.zip" output
+ grep "build-wrapper-dir=install-directory/build-wrapper-linux-x86" output
+ grep "build-wrapper-bin=install-directory/build-wrapper-linux-x86/build-wrapper-linux-x86-64" output
+
+ - name: macOSX
+ shell: bash
+ env:
+ OS: 'macOS'
+ ARCH: 'X64'
+ run: |
+ ./scripts/configure_paths.sh > output
+ grep -v "::error::" output
+
+ echo "- Check sonar-scanner:"
+ grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx.zip" output
+ grep "sonar-scanner-sha=DOWNLOAD-SHA-MACOSX" output
+ grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx" output
+ grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx/bin/sonar-scanner" output
+
+ echo "- Check build-wrapper:"
+ grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-macosx-x86.zip" output
+ grep "build-wrapper-dir=install-directory/build-wrapper-macosx-x86" output
+ grep "build-wrapper-bin=install-directory/build-wrapper-macosx-x86/build-wrapper-macosx-x86" output
+
+ - name: Unssuported OS
+ shell: bash
+ env:
+ OS: 'unsupportedOS'
+ ARCH: 'X64'
+ run: |
+ (./scripts/configure_paths.sh || echo "=== Script failed ===") > output
+
+ echo "- Check errors:"
+ grep "::error::Unsupported runner OS 'unsupportedOS'" output
+ grep "=== Script failed ===" output
+
+ - name: Unssuported architecture
+ shell: bash
+ env:
+ OS: 'Linux'
+ ARCH: 'X86'
+ run: |
+ (./scripts/configure_paths.sh || echo "=== Script failed ===") > output
+
+ echo "- Check errors:"
+ grep "::error::Architecture 'X86' is unsupported by build-wrapper" output
+ grep "=== Script failed ===" output
+
+
+ download-script-test:
+ name: download.sh script test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+
+ - name: Download test without validation
+ shell: bash
+ env:
+ INSTALL_PATH: 'install-directory-no-sha-validation'
+ DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip'
+ EXPECTED_SHA: 'incorrect-sha-not-validated'
+ TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip
+ run: |
+ ./scripts/download.sh > output
+ test -f "$TMP_ZIP_PATH"
+ grep -v "::error::" output
+ - name: Download test with validation
+ shell: bash
+ env:
+ INSTALL_PATH: 'install-directory-sha-validation'
+ DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip'
+ EXPECTED_SHA: '9411331814c1d002bd65d37758b872918b7602e7cf3ca5b83a3e19a729b2be05'
+ TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip
+ run: |
+ ./scripts/download.sh -v > output
+ test -f "$TMP_ZIP_PATH"
+ grep -v "::error::" output
+ - name: Incorrect install dir
+ shell: bash
+ env:
+ INSTALL_PATH: ''
+ run: |
+ (./scripts/download.sh || echo "=== Script failed ===") > output
+ grep "::error::Failed to create" output
+ grep "=== Script failed ===" output
+ - name: Incorrect download url
+ shell: bash
+ env:
+ INSTALL_PATH: 'install-directory-incorrect-url'
+ DOWNLOAD_URL: 'incorrect-url'
+ run: |
+ (./scripts/download.sh || echo "=== Script failed ===") > output
+ grep "::error::Failed to download 'incorrect-url'" output
+ grep "=== Script failed ===" output
+ - name: Incorrect SHA256
+ shell: bash
+ env:
+ INSTALL_PATH: 'install-directory-incorrect-sha'
+ DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip'
+ EXPECTED_SHA: 'incorrect-sha256'
+ TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip
+ run: |
+ (./scripts/download.sh -v || echo "=== Script failed ===") > output
+ grep "::error::Checking sha256 failed" output
+ grep "=== Script failed ===" output
+ - name: Mismatching SHA256
+ shell: bash
+ env:
+ INSTALL_PATH: 'install-directory-mismtaching-sha'
+ DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip'
+ EXPECTED_SHA: '3e121d85a4adb1f30b917d5f3eb897966b59e02c3d6d313a78dcd964193dc963'
+ TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip
+ run: |
+ (./scripts/download.sh -v || echo "=== Script failed ===") > output
+ grep "::error::Checking sha256 failed" output
+ grep "=== Script failed ===" output
+
+ fetch-latest-version-test:
+ name: fetch_latest_version.sh script test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+ - name: Test script
+ shell: bash
+ run: |
+ ./scripts/fetch_latest_version.sh > output
+
+ echo "- Check sonar-scanner version:"
+ grep "sonar-scanner-version=" output
+ SONAR_SCANNER_VERSION=$(cat output | cut -d= -f 2)
+ test ! -z "${SONAR_SCANNER_VERSION}"
+
+ echo "- Check windows sonar-scanner URLs:"
+ grep "sonar-scanner-url-windows=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-windows.zip" output
+ grep -e "^sonar-scanner-sha-windows=[0-9A-Fa-f]\+$" output
+
+ echo "- Check linux sonar-scanner URLs:"
+ grep "sonar-scanner-url-linux=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux.zip" output
+ grep -e "^sonar-scanner-sha-linux=[0-9A-Fa-f]\+$" output
+
+ echo "- Check macosx sonar-scanner URLs:"
+ grep "sonar-scanner-url-macosx=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-macosx.zip" output
+ grep -e "^sonar-scanner-sha-macosx=[0-9A-Fa-f]\+$" output
+
+ output-test:
+ name: Test action outputs
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ cache: [true, false]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+
+ - name: Run SonarQube C/C++ action
+ id: run-action
+ uses: ./
+ env:
+ SONAR_HOST_URL: 'https://next.sonarqube.com/'
+ with:
+ cache-binaries: ${{ matrix.cache }}
+
+ - name: SONAR_HOST_URL is set
+ shell: bash
+ run: |
+ [[ $SONAR_HOST_URL == "https://next.sonarqube.com/" ]]
+
+ - name: sonar-scanner is installed and in PATH
+ run: |
+ sonar-scanner --help | grep "INFO: usage: sonar-scanner "
+
+ - name: sonar-scanner-binary output is correct
+ shell: bash
+ env:
+ BINARY: ${{ steps.run-action.outputs.sonar-scanner-binary }}
+ run: |
+ "$BINARY" --help | grep "INFO: usage: sonar-scanner "
+
+ # build-wrapper does not have --help or equivalent option.
+ # Pass to few arguments and ignore error code
+ - name: build-wrapper is installed and in PATH on Windows
+ if: runner.os == 'Windows'
+ shell: bash
+ run: |
+ (build-wrapper-win-x86-64.exe || true) | grep "build-wrapper, version "
+
+ - name: build-wrapper is installed and in PATH on Linux
+ if: runner.os == 'Linux'
+ shell: bash
+ run: |
+ (build-wrapper-linux-x86-64 || true) | grep "build-wrapper, version "
+
+ - name: build-wrapper is installed and in PATH on macOS
+ if: runner.os == 'macOs'
+ shell: bash
+ run: |
+ (build-wrapper-macosx-x86 || true) | grep "build-wrapper, version "
+
+ - name: build-wrapper-binary output is correct
+ shell: bash
+ env:
+ BINARY: ${{ steps.run-action.outputs.build-wrapper-binary }}
+ run: |
+ ("$BINARY" || true) | grep "build-wrapper, version "
diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml
new file mode 100644
index 0000000..6e9b43c
--- /dev/null
+++ b/.github/workflows/version_update.yml
@@ -0,0 +1,50 @@
+name: sonar-scanner version check
+on:
+ schedule:
+ - cron: '15 10 * * *'
+
+jobs:
+ update-version:
+ name: Prepare pull request for sonar-scanner version update
+ runs-on: ubuntu-latest
+ steps:
+ - run: sudo apt install -y jq
+
+ - uses: actions/checkout@v4
+ with:
+ ref: main
+ persist-credentials: true
+ fetch-depth: 0
+
+ - name: "Fetch currently used sonar-scanner version"
+ id: tagged-version
+ shell: bash
+ run: cat sonar-scanner-version >> $GITHUB_OUTPUT
+
+ - name: "Fetch lastest sonar-scanner version"
+ id: latest-version
+ shell: bash
+ run: |
+ ./scripts/fetch_latest_version.sh > sonar-scanner-version
+ cat sonar-scanner-version >> $GITHUB_OUTPUT
+
+ - name: "Create Pull Request for version update"
+ if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version
+ shell: bash
+ env:
+ UPDATE_BRANCH: update-to-sonar-scanner-${{ steps.latest-version.outputs.sonar-scanner-version }}
+ TITLE: "Update sonar-scanner-version to ${{ steps.latest-version.outputs.sonar-scanner-version }}"
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ git config --global user.name "SonarTech"
+ git config --global user.email "sonartech@sonarsource.com"
+ git checkout -b ${UPDATE_BRANCH}
+ git add sonar-scanner-version
+ git commit -m "${TITLE}"
+ git push --force-with-lease origin ${UPDATE_BRANCH}
+ gh pr list
+
+ if [[ $(gh pr list -H "${UPDATE_BRANCH}" | grep "${UPDATE_BRANCH}" | wc -l) -eq 0 ]]; then
+ gh pr create -B main -H ${UPDATE_BRANCH} --title "${TITLE}" --body "Automatic updated of sonar-scanner version value. Needs to be tagged for release."
+ fi
+
diff --git a/README.md b/README.md
index a0e6490..0d75814 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,125 @@
-# sonarqube-github-c-cpp
-Integrate SonarQube code analysis to GitHub Actions when build-wrapper or relative paths support is required. Use https://github.com/SonarSource/sonarqube-scan-action otherwise.
+# Scan your code with SonarQube [![Tests](https://github.com/SonarSource/sonarqube-github-c-cpp/actions/workflows/tests.yml/badge.svg)](https://github.com/SonarSource/sonarqube-github-c-cpp/actions/workflows/tests.yml)
+
+Using this GitHub Action, achieve [Clean Code](https://www.sonarsource.com/solutions/clean-code/?utm_medium=referral&utm_source=github&utm_campaign=clean-code&utm_content=sonarqube-scan-action)
+with [SonarQube](https://www.sonarqube.org/) by scanning to detect Bugs, Vulnerabilities, and Code Smells in C, C++ and Objective-C!
+
+
+
+SonarQube is the leading product for Continuous Code Quality and code Security.
+It supports most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and many more.
+
+## Requirements
+
+To run an analysis on your code, you first need to set up your project on SonarQube.
+Your SonarQube instance must be accessible from GitHub, and you will need a Project analysis token or a Global analysis token to run the analysis (more information below under **Environment variables**).
+
+Read more information on how to analyze your code [here](https://docs.sonarqube.org/latest/analysis/github-integration/).
+
+
+## Usage
+
+
+Project metadata, including the location to the sources to be analyzed, must be declared in the file `sonar-project.properties` in the base directory:
+
+```properties
+sonar.projectKey=
+
+# relative paths to source directories. More details and properties are described
+# in https://docs.sonarsource.com/sonarqube/latest/project-administration/analysis-scope/
+sonar.sources=.
+```
+
+The workflow, usually declared in `.github/workflows/build.yml`, looks like:
+
+```yaml
+on:
+ # Trigger analysis when pushing in master or pull requests, and when creating
+ # a pull request.
+ push:
+ branches:
+ - master
+ pull_request:
+ types: [opened, synchronize, reopened]
+name: Main Workflow
+jobs:
+ sonarqube:
+ runs-on: ubuntu-latest
+ env:
+ BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ # Disabling shallow clone is recommended for improving relevancy of reporting
+ fetch-depth: 0
+ - name: Install sonar-scanner and build-wrapper
+ uses: sonarsource/sonarqube-github-c-cpp@v1
+ env:
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
+ - name: Run build-wrapper
+ run: |
+ #here goes your compilation wrapped with build-wrapper; See https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/languages/c-family/#using-build-wrapper for more information
+ # build-preparation steps
+ # build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} build-command
+ - name: Run sonar-scanner
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ run: sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" #Consult https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
+```
+
+You can change the `build-wrapper` and `sonar-scanner` installation path by using the optional input `installation-path` like this:
+
+```yaml
+uses: sonarsource/sonarqube-github-c-cpp@v1
+with:
+ installation-path: my/custom/directory/path
+```
+Also, the absolute paths to the installed build-wrapper and sonar-scanner binaries are returned as outputs from the action.
+
+Moreover, by default the action will cache sonar-scanner installation. However, you can disable caching by using the optional input: `cache-binaries` like this:
+```yaml
+uses: sonarsource/sonarqube-github-c-cpp@v1
+with:
+ cache-binaries: false
+```
+
+If your SonarQube server uses a self-signed certificate, you can pass a root certificate (in PEM format) to the java certificate store:
+
+```yaml
+uses: sonarsource/sonarqube-github-c-cpp@v1
+env:
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
+```
+
+See also [example configurations](https://github.com/sonarsource-cfamily-examples?q=gh-actions-sc&type=all&language=&sort=)
+
+### Secrets and environment variables
+
+Following secrets are required for successful invocation of sonar-scanner:
+- `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens [here](https://docs.sonarqube.org/latest/user-guide/user-token/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended).
+- *`GITHUB_TOKEN` – Provided by Github (see [Authenticating with the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)).*
+
+Environment variables:
+- `SONAR_HOST_URL` – **Required** this tells the scanner where SonarQube is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended).
+- `SONAR_ROOT_CERT` – Holds an additional root certificate (in PEM format) that is used to validate the SonarQube server certificate. You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended).
+
+## Do not use this GitHub action if you are in the following situations
+
+* You want to analyze code written in a language other than C, C++ or Objective-C?. Use the [SonarQube Scan GitHub Action](https://github.com/SonarSource/sonarqube-scan-action) instead
+* You want to run the action on a 32-bits system - build wrappers support only 64-bits OS
+
+## Additional information
+
+This action installs `coreutils` if run on macOS
+
+## Have question or feedback?
+
+To provide feedback (requesting a feature or reporting a bug) please post on the [SonarSource Community Forum](https://community.sonarsource.com/) with the tag `sonarqube`.
+
+## License
+
+The action file and associated scripts and documentation in this project are released under the LGPLv3 License.
diff --git a/action.yml b/action.yml
new file mode 100644
index 0000000..27c7b7b
--- /dev/null
+++ b/action.yml
@@ -0,0 +1,123 @@
+name: 'SonarQube Scan for C and C++'
+description: 'Scan your C and C++ code with SonarQube to detect bugs, vulnerabilities and code smells.'
+branding:
+ icon: check
+ color: green
+inputs:
+ installation-path:
+ description: 'Directory where the sonar-scanner and build wrapper will be installed. Created if does not exists.'
+ required: false
+ default: '.sonar'
+ cache-binaries:
+ description: 'Controls if installed binaries are cached using GitHub cache.'
+ required: false
+ default: 'true'
+
+outputs:
+ sonar-scanner-binary:
+ description: "Absolute path to sonar-scanner binary."
+ value: ${{ steps.setup-outputs.outputs.sonar-scanner-binary }}
+ build-wrapper-binary:
+ description: "Absolute path to build-wrapper binary."
+ value: ${{ steps.setup-outputs.outputs.build-wrapper-binary }}
+
+runs:
+ using: "composite"
+ steps:
+ # install packaged required for greadlink and sha256sum command on macOS
+ - name: Install required packages for macOS
+ if: runner.os == 'macOS'
+ shell: bash
+ run: brew install coreutils
+
+ - name: Verify and create installation path
+ shell: bash
+ env:
+ INSTALL_PATH: ${{ inputs.installation-path }}
+ run: ${GITHUB_ACTION_PATH}/scripts/create_install_path.sh
+
+ - name: Set version of sonar-scanner
+ id: sonar-scanner-version
+ shell: bash
+ run: cat ${GITHUB_ACTION_PATH}/sonar-scanner-version >> $GITHUB_OUTPUT
+
+ - name: Configure paths
+ id: configure_paths
+ shell: bash
+ env:
+ OS: ${{ runner.os }}
+ ARCH: ${{ runner.arch }}
+ INSTALL_PATH: ${{ inputs.installation-path }}
+ SONAR_SCANNER_VERSION: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-version }}
+ SONAR_SCANNER_URL_WINDOWS: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-windows }}
+ SONAR_SCANNER_SHA_WINDOWS: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-windows }}
+ SONAR_SCANNER_URL_LINUX: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-linux }}
+ SONAR_SCANNER_SHA_LINUX: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-linux }}
+ SONAR_SCANNER_URL_MACOSX: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-macosx }}
+ SONAR_SCANNER_SHA_MACOSX: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-macosx }}
+ run: ${GITHUB_ACTION_PATH}/scripts/configure_paths.sh >> $GITHUB_OUTPUT
+
+ - name: Cache sonar-scanner installation
+ id: cache-sonar-tools
+ if: inputs.cache-binaries == 'true'
+ uses: actions/cache@v3
+ env:
+ # The default value is 60mins. Reaching timeout is treated the same as a cache miss.
+ SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
+ with:
+ key: sonar-scanner-${{ runner.os }}-${{ steps.sonar-scanner-version.outputs.sonar-scanner-version }}
+ path: ${{ steps.configure_paths.outputs.sonar-scanner-dir }}
+
+ - name: Download and install sonar-scanner
+ if: steps.cache-sonar-tools.outputs.cache-hit != 'true'
+ shell: bash
+ env:
+ DOWNLOAD_URL: ${{ steps.configure_paths.outputs.sonar-scanner-url }}
+ EXPECTED_SHA: ${{ steps.configure_paths.outputs.sonar-scanner-sha }}
+ INSTALL_PATH: ${{ inputs.installation-path }}
+ TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip
+ run: ${GITHUB_ACTION_PATH}/scripts/download.sh -v
+
+ - name: Add the custom root certificate to java certificate store
+ shell: bash
+ run: ${GITHUB_ACTION_PATH}/scripts/cert.sh
+
+ - name: Download and install build-wrapper
+ shell: bash
+ env:
+ DOWNLOAD_URL: ${{ steps.configure_paths.outputs.build-wrapper-url }}
+ INSTALL_PATH: ${{ inputs.installation-path }}
+ TMP_ZIP_PATH: ${{ runner.temp }}/build-wrapper.zip
+ run: ${GITHUB_ACTION_PATH}/scripts/download.sh
+
+ - name: Setup action outputs
+ id: setup-outputs
+ shell: bash
+ env:
+ SONAR_SCANNER_DIR: ${{ steps.configure_paths.outputs.sonar-scanner-dir }}
+ SONAR_SCANNER_BIN: ${{ steps.configure_paths.outputs.sonar-scanner-bin }}
+ BUILD_WRAPPER_DIR: ${{ steps.configure_paths.outputs.build-wrapper-dir }}
+ BUILD_WRAPPER_BIN: ${{ steps.configure_paths.outputs.build-wrapper-bin }}
+ run: |
+ source ${GITHUB_ACTION_PATH}/scripts/utils.sh
+
+ echo "::group::Action outputs"
+ echo "SONAR_HOST_URL=${SONAR_HOST_URL}" >> $GITHUB_ENV
+ echo "'SONAR_HOST_URL' environment variable set to '${SONAR_HOST_URL}'"
+
+ SONAR_SCANNER_BIN_DIR=$(realpath "${SONAR_SCANNER_DIR}/bin")
+ echo "${SONAR_SCANNER_BIN_DIR}" >> $GITHUB_PATH
+ echo "'${SONAR_SCANNER_BIN_DIR}' added to the path"
+
+ SONAR_SCANNER_BIN=$(realpath "${SONAR_SCANNER_BIN}")
+ echo "sonar-scanner-binary=${SONAR_SCANNER_BIN}" >> $GITHUB_OUTPUT
+ echo "'sonar-scanner-binary' output set to '${SONAR_SCANNER_BIN}'"
+
+ BUILD_WRAPPER_BIN_DIR=$(realpath "${BUILD_WRAPPER_DIR}")
+ echo "${BUILD_WRAPPER_BIN_DIR}" >> $GITHUB_PATH
+ echo "'${BUILD_WRAPPER_BIN_DIR}' added to the path"
+
+ BUILD_WRAPPER_BIN=$(realpath "${BUILD_WRAPPER_BIN}")
+ echo "build-wrapper-binary=${BUILD_WRAPPER_BIN}" >> $GITHUB_OUTPUT
+ echo "'build-wrapper-binary' output set to '${BUILD_WRAPPER_BIN}'"
+ echo "::endgroup::"
diff --git a/images/SonarQube-72px.png b/images/SonarQube-72px.png
new file mode 100644
index 0000000..400830b
Binary files /dev/null and b/images/SonarQube-72px.png differ
diff --git a/scripts/cert.sh b/scripts/cert.sh
new file mode 100755
index 0000000..2c2a2a5
--- /dev/null
+++ b/scripts/cert.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [[ -n "${SONAR_ROOT_CERT}" ]]; then
+ echo "Adding custom root certificate to java certificate store"
+ rm -f /tmp/tmpcert.pem
+ echo "${SONAR_ROOT_CERT}" > /tmp/tmpcert.pem
+ keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem
+fi
diff --git a/scripts/configure_paths.sh b/scripts/configure_paths.sh
new file mode 100755
index 0000000..8a8ed2b
--- /dev/null
+++ b/scripts/configure_paths.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+if [[ ${ARCH} != "X64" ]]; then
+ echo "::error::Architecture '${ARCH}' is unsupported by build-wrapper"
+ exit 1
+fi
+
+case ${OS} in
+ Windows)
+ SONAR_SCANNER_SUFFIX="windows"
+ BUILD_WRAPPER_SUFFIX="win-x86"
+ SONAR_SCANNER_NAME="sonar-scanner.bat"
+ BUILD_WRAPPER_NAME="build-wrapper-win-x86-64.exe"
+ SONAR_SCANNER_URL="${SONAR_SCANNER_URL_WINDOWS}"
+ SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_WINDOWS}"
+ ;;
+ Linux)
+ SONAR_SCANNER_SUFFIX="linux"
+ BUILD_WRAPPER_SUFFIX="linux-x86"
+ SONAR_SCANNER_NAME="sonar-scanner"
+ BUILD_WRAPPER_NAME="build-wrapper-linux-x86-64"
+ SONAR_SCANNER_URL="${SONAR_SCANNER_URL_LINUX}"
+ SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_LINUX}"
+ ;;
+ macOS)
+ SONAR_SCANNER_SUFFIX="macosx"
+ BUILD_WRAPPER_SUFFIX="macosx-x86"
+ SONAR_SCANNER_NAME="sonar-scanner"
+ BUILD_WRAPPER_NAME="build-wrapper-macosx-x86"
+ SONAR_SCANNER_URL="${SONAR_SCANNER_URL_MACOSX}"
+ SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_MACOSX}"
+ ;;
+ *)
+ echo "::error::Unsupported runner OS '${OS}'"
+ exit 1
+ ;;
+esac
+
+
+echo "sonar-scanner-url=${SONAR_SCANNER_URL}"
+echo "sonar-scanner-sha=${SONAR_SCANNER_SHA}"
+
+SONAR_SCANNER_DIR="${INSTALL_PATH}/sonar-scanner-${SONAR_SCANNER_VERSION}-${SONAR_SCANNER_SUFFIX}"
+echo "sonar-scanner-dir=${SONAR_SCANNER_DIR}"
+echo "sonar-scanner-bin=${SONAR_SCANNER_DIR}/bin/${SONAR_SCANNER_NAME}"
+
+BUILD_WRAPPER_DIR="${INSTALL_PATH}/build-wrapper-${BUILD_WRAPPER_SUFFIX}"
+echo "build-wrapper-url=${SONAR_HOST_URL}/static/cpp/build-wrapper-${BUILD_WRAPPER_SUFFIX}.zip"
+echo "build-wrapper-dir=${BUILD_WRAPPER_DIR}"
+echo "build-wrapper-bin=${BUILD_WRAPPER_DIR}/${BUILD_WRAPPER_NAME}"
+
diff --git a/scripts/create_install_path.sh b/scripts/create_install_path.sh
new file mode 100755
index 0000000..6c65831
--- /dev/null
+++ b/scripts/create_install_path.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+source "$(dirname -- "$0")/utils.sh"
+
+echo "Installation path is '${INSTALL_PATH}'"
+
+test ! -z "${INSTALL_PATH}"
+check_status "Empty installation path specified"
+
+if [[ ! -e "${INSTALL_PATH}" ]]; then
+ mkdir -p "${INSTALL_PATH}"
+ check_status "Failed to create non-existing installation path '${INSTALL_PATH}'"
+fi
+
+ABSOLUTE_INSTALL_PATH=$(realpath "${INSTALL_PATH}")
+echo "Absolute installation path is '${ABSOLUTE_INSTALL_PATH}'"
+
+test -d ${INSTALL_PATH}
+check_status "Installation path '${INSTALL_PATH}' is not a directory (absolute path is '${ABSOLUTE_INSTALL_PATH}')"
+
+test -r "${INSTALL_PATH}"
+check_status "Installation path '${INSTALL_PATH}' is not readable (absolute path is '${ABSOLUTE_INSTALL_PATH}')"
+
+test -w "${INSTALL_PATH}"
+check_status "Installation path '${INSTALL_PATH}' is not writeable (absolute path is '${ABSOLUTE_INSTALL_PATH}')"
+
diff --git a/scripts/download.sh b/scripts/download.sh
new file mode 100755
index 0000000..9e1aefa
--- /dev/null
+++ b/scripts/download.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+source "$(dirname -- "$0")/utils.sh"
+
+VERIFY_CORRECTNESS=false
+
+help() {
+ cat <