diff --git a/.cirrus.star b/.cirrus.star deleted file mode 100644 index 462c380..0000000 --- a/.cirrus.star +++ /dev/null @@ -1,5 +0,0 @@ -load("github.com/SonarSource/cirrus-modules@v3", "load_features") - - -def main(ctx): - return load_features(ctx, only_if=dict()) diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index de9ec08..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,159 +0,0 @@ -env: - CIRRUS_CLONE_DEPTH: "20" - CIRRUS_SHELL: bash - # Artifactory settings - ARTIFACTORY_URL: VAULT[development/kv/data/repox data.url] - ARTIFACTORY_PRIVATE_USERNAME: vault-${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-private-reader - ARTIFACTORY_PRIVATE_PASSWORD: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-private-reader access_token] - ARTIFACTORY_ACCESS_TOKEN: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-private-reader access_token] - ARTIFACTORY_DEPLOY_USERNAME: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-qa-deployer username] - ARTIFACTORY_DEPLOY_PASSWORD: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-qa-deployer access_token] - ARTIFACTORY_DEPLOY_REPO: sonarsource-public-qa - DEVELOCITY_TOKEN: VAULT[development/kv/data/develocity data.token] - DEVELOCITY_ACCESS_KEY: develocity.sonar.build=${DEVELOCITY_TOKEN} - DEPLOY_PULL_REQUEST: "true" - # Gradle settings - GRADLE_USER_HOME: ${CIRRUS_WORKING_DIR}/.gradle - - -eks_container: &CONTAINER_DEFINITION - image: ${CIRRUS_AWS_ACCOUNT}.dkr.ecr.eu-central-1.amazonaws.com/base:j17-g7-latest - cluster_name: ${CIRRUS_CLUSTER_NAME} - region: eu-central-1 - namespace: default - -setup_gradle_cache_template: &SETUP_GRADLE_CACHE - gradle_cache: - folder: .gradle/caches - fingerprint_script: - - echo $CIRRUS_OS - - cat **/*.gradle* **/gradle*.properties || true - create_gradle_directory_script: - - mkdir -p "${CIRRUS_WORKING_DIR}/.gradle" - -log_develocity_url_script: &log_develocity_url_script | - echo "Develocity URL: https://develocity.sonar.build/scans?search.publicHostnames=cirrus-ci-task-${CIRRUS_TASK_ID}" - -only_if_sonarsource_qa_template: &ONLY_IF_SONARSOURCE_QA - only_if: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_TAG == "" && ($CIRRUS_PR != "" || $CIRRUS_BRANCH == "master" || $CIRRUS_BRANCH =~ "branch-.*" || $CIRRUS_BRANCH =~ "dogfood-on-.*") - -qa_task_filter_template: &QA_TASK_FILTER - depends_on: - - build - <<: *ONLY_IF_SONARSOURCE_QA - -build_task: - eks_container: - <<: *CONTAINER_DEFINITION - cpu: 8 - memory: 4G - env: - SONAR_TOKEN: VAULT[development/kv/data/next data.token] - SONAR_HOST_URL: VAULT[development/kv/data/next data.url] - ORG_GRADLE_PROJECT_signingKey: VAULT[development/kv/data/sign data.key] - ORG_GRADLE_PROJECT_signingPassword: VAULT[development/kv/data/sign data.passphrase] - ORG_GRADLE_PROJECT_signingKeyId: VAULT[development/kv/data/sign data.key_id] - <<: *SETUP_GRADLE_CACHE - build_script: - - *log_develocity_url_script - - source cirrus-env BUILD - - function gradle(){ ./gradlew "$@"; }; export -f gradle - - gradle --version - - source set_gradle_build_version - - regular_gradle_build_deploy_analyze - on_failure: - error_log_artifacts: - path: "hs_err_pid*.log" - heap_dump_artifacts: - path: "*.hprof" - -sonar_shadow_scan_and_issue_replication_task: - depends_on: - - build - # Only run when triggered by the cirrus-ci cron job named "nightly" - only_if: $CIRRUS_CRON == "nightly" - eks_container: - <<: *CONTAINER_DEFINITION - cpu: 8 - memory: 4G - env: - SONAR_PROJECT_KEY: "SonarSource_sonar-scala" - SHADOW_ORGANIZATION: "sonarsource" - SHADOW_PROJECT_KEY: "SonarSource_sonar-scala" - # to replicate issue states from next - SONAR_TOKEN: VAULT[development/kv/data/next data.token] - SONAR_HOST_URL: https://next.sonarqube.com/sonarqube - matrix: - - name: "sonarcloud.io" - SHADOW_SONAR_TOKEN: VAULT[development/kv/data/sonarcloud data.token] - SHADOW_SONAR_HOST_URL: "https://sonarcloud.io" - - name: "sonarqube.us" - SHADOW_SONAR_TOKEN: VAULT[development/kv/data/sonarqube-us data.token] - SHADOW_SONAR_HOST_URL: "https://sonarqube.us" - <<: *SETUP_GRADLE_CACHE - build_script: - - *log_develocity_url_script - - source cirrus-env BUILD - - source set_gradle_build_version - - ./shadow-scan-and-issue-replication.sh - -qa_plugin_task: - <<: *QA_TASK_FILTER - eks_container: - <<: *CONTAINER_DEFINITION - cpu: 8 - memory: 8G - env: - GITHUB_TOKEN: VAULT[development/github/token/licenses-ro token] - matrix: - - SQ_VERSION: "LATEST_RELEASE" - - SQ_VERSION: "DEV" - <<: *SETUP_GRADLE_CACHE - plugin_script: - - *log_develocity_url_script - - source cirrus-env QA - - ./gradlew ":its:plugin:test" --project-prop plugin - "-Dsonar.runtimeVersion=${SQ_VERSION}" - "-Dorchestrator.artifactory.accessToken=${ARTIFACTORY_ACCESS_TOKEN}" - "-DbuildNumber=$BUILD_NUMBER" - -I "${GRADLE_HOME}/init.d/repoxAuth.init.gradle.kts" - --info --stacktrace --console plain --no-daemon --build-cache - -qa_ruling_task: - <<: *QA_TASK_FILTER - eks_container: - <<: *CONTAINER_DEFINITION - cpu: 8 - memory: 8G - env: - GITHUB_TOKEN: VAULT[development/github/token/licenses-ro token] - <<: *SETUP_GRADLE_CACHE - ruling_script: - - *log_develocity_url_script - - source cirrus-env QA - - git submodule update --init its/sources - - ./gradlew ":its:ruling:test" --project-prop ruling - "-Dsonar.runtimeVersion=LATEST_RELEASE" - "-Dorchestrator.artifactory.accessToken=${ARTIFACTORY_ACCESS_TOKEN}" - "-DbuildNumber=$BUILD_NUMBER" - -I "${GRADLE_HOME}/init.d/repoxAuth.init.gradle.kts" - --info --stacktrace --console plain --no-daemon --build-cache - -promote_task: - depends_on: - - build - - sonar_shadow_scan_and_issue_replication - - qa_plugin - - qa_ruling - eks_container: - <<: *CONTAINER_DEFINITION - cpu: 1 - memory: 1G - env: - ARTIFACTORY_URL: VAULT[development/kv/data/repox data.url] - ARTIFACTORY_PROMOTE_ACCESS_TOKEN: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-promoter access_token] - GITHUB_TOKEN: VAULT[development/github/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-promotion token] - promote_script: - - *log_develocity_url_script - - function gradle(){ ./gradlew "$@"; }; export -f gradle - - cirrus_promote_gradle multi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37c0304..a8eddde 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,14 +23,15 @@ jobs: id-token: write # Required for Vault OIDC authentication contents: write # Required for repository access and tagging outputs: - build-number: ${{ steps.build-gradle.outputs.BUILD_NUMBER }} + build-number: ${{ steps.build-step.outputs.BUILD_NUMBER }} + deployed: ${{ steps.build-step.outputs.deployed }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 with: version: 2025.7.12 - uses: SonarSource/ci-github-actions/build-gradle@v1 - id: build-gradle + id: build-step with: deploy-pull-request: true artifactory-reader-role: private-reader # Override for public repo using private access @@ -38,10 +39,11 @@ jobs: qa: needs: [build] + if: ${{ needs.build.outputs.deployed }} runs-on: github-ubuntu-latest-s # Public repository runner permissions: id-token: write # Required for Vault OIDC authentication - contents: write # Required for repository access + contents: read # Required for repository access strategy: fail-fast: false matrix: @@ -51,40 +53,37 @@ jobs: item: - { suite: "plugin", sq_version: "DEV", submodules: false} - { suite: "plugin", sq_version: "LATEST_RELEASE", submodules: false} - - { suite: "ruling", sq_version: "LATEST_RELEASE", submodules: true} + - { suite: "ruling", sq_version: "LATEST_RELEASE" } name: "QA Tests [${{ matrix.item.suite }}] - SQ : ${{ matrix.item.sq_version }}" steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: - submodules: ${{ matrix.item.submodules }} + submodules: ${{ matrix.item.suite == 'ruling' }} - name: Remove kotlin ITs as they are not relevant for ruling tests (and cause issues with wrapper validation) - if: ${{ matrix.item.submodules }} + if: ${{ matrix.item.suite == 'ruling' }} run: rm -r ./its/sources/kotlin - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 with: - cache_save: false version: 2025.7.12 - name: Get GitHub Token for QA Licenses id: secrets uses: SonarSource/vault-action-wrapper@v3 with: - # TODO Remove artifactory token when build-gradle provides it secrets: | development/github/token/licenses-ro token | GITHUB_TOKEN; development/artifactory/token/{REPO_OWNER_NAME_DASH}-private-reader access_token | ARTIFACTORY_ACCESS_TOKEN; - name: Configure Gradle - uses: SonarSource/ci-github-actions/build-gradle@v1 # TODO When config-gradle is released, use it and remove the gradle-args below + uses: SonarSource/ci-github-actions/build-gradle@v1 with: gradle-args: "-x build -x sonar -x artifactoryPublish" # Skip everything to only configure Gradle and Artifactory access - artifactory-reader-role: private-reader # Override for public repo using private access - artifactory-deployer-role: qa-deployer # TODO Should not be needed for config-gradle + artifactory-reader-role: private-reader + artifactory-deployer-role: qa-deployer - name: Run QA Tests env: GITHUB_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).GITHUB_TOKEN }} ARTIFACTORY_ACCESS_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_ACCESS_TOKEN }} SUITE: ${{ matrix.item.suite }} SQ_VERSION: ${{ matrix.item.sq_version }} - BUILD_NUMBER: ${{ needs.build.outputs.build-number }} run: | ./gradlew ":its:${SUITE}:test" --project-prop ${SUITE} \ "-Dsonar.runtimeVersion=${SQ_VERSION}" \ @@ -92,20 +91,16 @@ jobs: "-DbuildNumber=${BUILD_NUMBER}" \ --info --stacktrace --console plain --no-daemon --build-cache promote: + name: Promote needs: - build - qa runs-on: github-ubuntu-latest-s # Public repository runner - name: Promote + if: ${{ needs.build.outputs.deployed }} permissions: id-token: write # Required for Vault OIDC authentication contents: write # Required for repository access and tagging steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 - with: - cache_save: false - version: 2025.7.12 - uses: SonarSource/ci-github-actions/promote@v1 with: promote-pull-request: true # Enable PR artifact promotion diff --git a/build.gradle b/build.gradle index 40de85d..69bf1a5 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ allprojects { ext { buildNumber = System.getProperty("buildNumber") - sonarLinksCi = 'https://cirrus-ci.com/github/SonarSource/sonar-scala' + sonarLinksCi = 'https://github.com/SonarSource/sonar-scala/actions/workflows/build.yml' sonarLinksScm = 'https://github.com/SonarSource/sonar-scala' artifactsToPublish = '' diff --git a/shadow-scan-and-issue-replication.sh b/shadow-scan-and-issue-replication.sh deleted file mode 100755 index 1fe21b6..0000000 --- a/shadow-scan-and-issue-replication.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# IRIS: Issue Replication for Sonarqube -IRIS_JAR_URL="${ARTIFACTORY_URL}/sonarsource-private-releases/com/sonarsource/iris/iris/\[RELEASE\]/iris-\[RELEASE\]-jar-with-dependencies.jar" -IRIS_JAR_PATH="target/libs/iris.jar" - -function build_and_analyze_the_project() { - echo - echo "===== Build and analyze the project targeting a shadow SonarQube instance" - local BUILD_CMD - if [[ -e "gradlew" ]]; then - BUILD_CMD="./gradlew --info --stacktrace --console plain build sonar" - else - source set_maven_build_version "$BUILD_NUMBER" - BUILD_CMD="mvn -Pcoverage -Dmaven.test.redirectTestOutputToFile=false --batch-mode --errors --show-version verify sonar:sonar" - fi - ${BUILD_CMD} \ - -DbuildNumber="${BUILD_NUMBER}" \ - -Dsonar.host.url="${SHADOW_SONAR_HOST_URL}" \ - -Dsonar.token="${SHADOW_SONAR_TOKEN}" \ - -Dsonar.organization="${SHADOW_ORGANIZATION}" \ - -Dsonar.projectKey="${SHADOW_PROJECT_KEY}" \ - -Dsonar.analysis.buildNumber="${BUILD_NUMBER}" \ - -Dsonar.analysis.repository="${GITHUB_REPO}" \ - "$@" -} - -function download_iris() { - echo - echo "===== Download ${IRIS_JAR_URL}" - mkdir -p target/libs - curl --silent --fail-with-body --location --header "Authorization: Bearer ${ARTIFACTORY_PRIVATE_PASSWORD}" \ - --output "${IRIS_JAR_PATH}" "${IRIS_JAR_URL}" -} - -function sonarcloud_compute_engine_status_for_given_project() { - local PROJECT_KEY="$1" - local RESPONSE - RESPONSE="$( - curl --silent --fail-with-body --location --request GET \ - --header "Authorization: Bearer ${SHADOW_SONAR_TOKEN}" \ - --output - \ - "${SHADOW_SONAR_HOST_URL}/api/ce/component?component=${PROJECT_KEY}" - )" - local STATUS - # we first check if there is one or more 'PENDING' tasks in the queue - STATUS="$(echo "${RESPONSE}" | jq -r '.queue[].status')" - if [[ "${STATUS}" == "null" ]]; then - STATUS="" - fi - if [[ -z "${STATUS}" ]]; then - # otherwise we get the status of the current task - STATUS="$(echo "${RESPONSE}" | jq -r '.current.status')" - fi - echo -n "${STATUS}" -} - -function wait_for_sonarcloud_compute_engine_to_finish() { - local MAX_WAIT_TIME_SECONDS="300" # Default to 5 minutes - local SLEEP_INTERVAL_SECONDS="1" - local ELAPSED_TIME=0 - local LAST_STATUS="" - local STATUS - - echo "Waiting for SonarCloud compute engine to finish for project key: ${SHADOW_PROJECT_KEY}" - while (( ELAPSED_TIME < MAX_WAIT_TIME_SECONDS )); do - STATUS=$(sonarcloud_compute_engine_status_for_given_project "${SHADOW_PROJECT_KEY}") - if [[ "${STATUS}" != "${LAST_STATUS}" ]]; then - echo -n " ${STATUS} " - LAST_STATUS="${STATUS}" - fi - - if [[ "${STATUS}" == "PENDING" || "${STATUS}" == "IN_PROGRESS" ]]; then - echo -n "." - elif [[ "${STATUS}" == "FAILED" || "${STATUS}" == "CANCELED" ]]; then - echo -e "\nERROR: SonarCloud compute engine finished with status: ${STATUS}" - return 1 - elif [[ "${STATUS}" == "SUCCESS" ]]; then - echo -e "\nSonarCloud compute engine finished successfully." - return 0 - else - echo -e "\nERROR: Unknown status: ${STATUS}" - return 1 - fi - sleep "${SLEEP_INTERVAL_SECONDS}" - ELAPSED_TIME=$((ELAPSED_TIME + SLEEP_INTERVAL_SECONDS)) - done - echo -e "\nERROR: Timeout reached after ${MAX_WAIT_TIME_SECONDS} seconds." - return 1 -} - -function run_iris() { - local DRY_RUN="$1" - java \ - -Diris.source.projectKey="${SONAR_PROJECT_KEY}" \ - -Diris.source.url="${SONAR_HOST_URL}" \ - -Diris.source.token="${SONAR_TOKEN}" \ - -Diris.destination.projectKey="${SHADOW_PROJECT_KEY}" \ - -Diris.destination.organization="${SHADOW_ORGANIZATION}" \ - -Diris.destination.url="${SHADOW_SONAR_HOST_URL}" \ - -Diris.destination.token="${SHADOW_SONAR_TOKEN}" \ - -Diris.dryrun="${DRY_RUN}" \ - -jar "${IRIS_JAR_PATH}" -} - -function run_iris_with_and_without_dry_run() { - echo - echo "===== Execute IRIS as dry-run" - if run_iris true; then - echo "===== Successful IRIS execution as dry-run" - echo "===== Execute IRIS for real" - if run_iris false; then - echo "===== Successful IRIS execution for real" - return 0 - else - echo "===== Failed IRIS execution for real" - return 1 - fi - else - echo "===== Failed IRIS execution as dry-run" - return 1 - fi -} - -build_and_analyze_the_project "$@" -download_iris -wait_for_sonarcloud_compute_engine_to_finish -run_iris_with_and_without_dry_run