Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ jobs:
poetry-cache-dir: .cache/pypoetry # Poetry cache directory
repox-url: https://repox.jfrog.io # Repox URL
sonar-platform: next # SonarQube platform (next, sqc-eu, or sqc-us)
run-shadow-scans: false # Run SonarQube scans on all 3 platforms (next, sqc-eu, sqc-us)
```

### Inputs
Expand Down
23 changes: 19 additions & 4 deletions build-poetry/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ inputs:
sonar-platform:
description: SonarQube primary platform (next, sqc-eu, or sqc-us)
default: next
run-shadow-scans:
description: If true, run sonar scanner on all 3 platforms using the provided URL and token.
If false, run on the platform provided by SONAR_PLATFORM.
default: 'false'

outputs:
project-version:
Expand Down Expand Up @@ -66,10 +70,15 @@ runs:
uses: SonarSource/vault-action-wrapper@320bd31b03e5dacaac6be51bbbb15adf7caccc32 # 3.1.0
with:
secrets: |
development/kv/data/${{ inputs.sonar-platform == 'sqc-eu' && 'sonarcloud' || (inputs.sonar-platform == 'sqc-us' && 'sonarqube-us' || 'next') }} url | SONAR_HOST_URL;
development/kv/data/${{ inputs.sonar-platform == 'sqc-eu' && 'sonarcloud' || (inputs.sonar-platform == 'sqc-us' && 'sonarqube-us' || 'next') }} token | SONAR_TOKEN;
development/artifactory/token/{REPO_OWNER_NAME_DASH}-${{ env.ARTIFACTORY_READER_ROLE }} access_token | ARTIFACTORY_ACCESS_TOKEN;
development/artifactory/token/{REPO_OWNER_NAME_DASH}-${{ env.ARTIFACTORY_DEPLOYER_ROLE }} access_token | ARTIFACTORY_DEPLOY_ACCESS_TOKEN;

development/kv/data/next url | NEXT_URL;
development/kv/data/next token | NEXT_TOKEN;
development/kv/data/sonarqube-us url | SQC_US_URL;
development/kv/data/sonarqube-us token | SQC_US_TOKEN;
development/kv/data/sonarcloud url | SQC_EU_URL;
development/kv/data/sonarcloud token | SQC_EU_TOKEN;
# yamllint enable rule:line-length
- name: Build, Analyze and deploy
shell: bash
Expand All @@ -90,7 +99,13 @@ runs:
POETRY_CACHE_DIR: ${{ github.workspace }}/${{ inputs.poetry-cache-dir }}

# Vault secrets
SONAR_HOST_URL: ${{ fromJSON(steps.secrets.outputs.vault).SONAR_HOST_URL }}
SONAR_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SONAR_TOKEN }}
SQC_EU_URL: ${{ fromJSON(steps.secrets.outputs.vault).SQC_EU_URL }}
SQC_US_URL: ${{ fromJSON(steps.secrets.outputs.vault).SQC_US_URL }}
NEXT_URL: ${{ fromJSON(steps.secrets.outputs.vault).NEXT_URL }}
NEXT_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).NEXT_TOKEN }}
SQC_EU_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SQC_EU_TOKEN }}
SQC_US_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SQC_US_TOKEN }}
SONAR_PLATFORM: ${{ inputs.sonar-platform }}
RUN_SHADOW_SCANS: ${{ inputs.run-shadow-scans }}
run: |
${GITHUB_ACTION_PATH}/build.sh
68 changes: 63 additions & 5 deletions build-poetry/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
#
# Required inputs (must be explicitly provided):
# - BUILD_NUMBER: Build number for versioning
# - SONAR_HOST_URL: URL of SonarQube server
# - SONAR_TOKEN: Access token to send analysis reports to SonarQube
# - ARTIFACTORY_URL: URL to Artifactory repository
# - ARTIFACTORY_PYPI_REPO: Repository to install dependencies from
# - ARTIFACTORY_ACCESS_TOKEN: Access token to access the repository
# - ARTIFACTORY_DEPLOY_REPO: Deployment repository name
# - ARTIFACTORY_DEPLOY_ACCESS_TOKEN: Access token to deploy to the repository
# - DEFAULT_BRANCH: Default branch name (e.g. main)
# - PULL_REQUEST: Pull request number (e.g. 1234) or empty string
# - SONAR_PLATFORM: SonarQube primary platform (next, sqc-eu, or sqc-us)
# - NEXT_URL: URL of SonarQube server for next platform
# - NEXT_TOKEN: Access token to send analysis reports to SonarQube for next platform
# - SQC_US_URL: URL of SonarQube server for sqc-us platform
# - SQC_US_TOKEN: Access token to send analysis reports to SonarQube for sqc-us platform
# - SQC_EU_URL: URL of SonarQube server for sqc-eu platform
# - SQC_EU_TOKEN: Access token to send analysis reports to SonarQube for sqc-eu platform
# - RUN_SHADOW_SCANS: If true, run sonar scanner on all 3 platforms. If false, run on the platform provided by SONAR_PLATFORM.
#
# GitHub Actions auto-provided:
# - GITHUB_REF_NAME: Git branch name
Expand All @@ -39,7 +45,8 @@ set -euo pipefail
: "${GITHUB_REF_NAME:?}" "${BUILD_NUMBER:?}" "${GITHUB_REPOSITORY:?}" "${GITHUB_EVENT_NAME:?}" "${GITHUB_EVENT_PATH:?}"
: "${PULL_REQUEST?}" "${DEFAULT_BRANCH:?}"
: "${GITHUB_ENV:?}" "${GITHUB_OUTPUT:?}" "${GITHUB_SHA:?}" "${GITHUB_RUN_ID:?}"
: "${SONAR_HOST_URL:?}" "${SONAR_TOKEN:?}"
: "${SONAR_PLATFORM:?}" "${NEXT_URL:?}" "${NEXT_TOKEN:?}" "${SQC_US_URL:?}" "${SQC_US_TOKEN:?}" "${SQC_EU_URL:?}" "${SQC_EU_TOKEN:?}"
: "${RUN_SHADOW_SCANS:?}"
: "${DEPLOY_PULL_REQUEST:=false}"
export ARTIFACTORY_URL DEPLOY_PULL_REQUEST

Expand All @@ -63,6 +70,36 @@ git_fetch_unshallow() {
fi
}

set_sonar_platform_vars() {
local platform="$1"

# TODO: The SONAR_REGION variable can be removed once SCANPY-203 is fixed

case "$platform" in
"next")
export SONAR_HOST_URL="$NEXT_URL"
export SONAR_TOKEN="$NEXT_TOKEN"
export SONAR_REGION=""
;;
"sqc-us")
export SONAR_HOST_URL="$SQC_US_URL"
export SONAR_TOKEN="$SQC_US_TOKEN"
export SONAR_REGION="us"
;;
"sqc-eu")
export SONAR_HOST_URL="$SQC_EU_URL"
export SONAR_TOKEN="$SQC_EU_TOKEN"
export SONAR_REGION=""
;;
*)
echo "ERROR: Unknown sonar platform '$platform'. Expected: next, sqc-us, or sqc-eu" >&2
return 1
;;
esac

echo "Using Sonar platform: $platform (URL: $SONAR_HOST_URL)"
}

run_sonar_scanner() {
local additional_params=("$@")

Expand All @@ -77,7 +114,28 @@ run_sonar_scanner() {
-Dsonar.analysis.sha1="${GITHUB_SHA}" \
-Dsonar.analysis.repository="${GITHUB_REPOSITORY}" \
"${additional_params[@]}"
echo "SonarQube scanner finished"
echo "SonarQube scanner finished for platform: $(basename "$SONAR_HOST_URL")"
}

run_sonar_analysis() {
local sonar_args=("$@")

if [ "${RUN_SHADOW_SCANS}" = "true" ]; then
echo "=== Running Sonar analysis on all platforms (shadow scan enabled) ==="
local platforms=("next" "sqc-us" "sqc-eu")

for platform in "${platforms[@]}"; do
echo "--- Analyzing with platform: $platform ---"
set_sonar_platform_vars "$platform"
run_sonar_scanner "${sonar_args[@]}"
done

echo "=== Completed Sonar analysis on all platforms ==="
else
echo "=== Running Sonar analysis on selected platform: $SONAR_PLATFORM ==="
set_sonar_platform_vars "$SONAR_PLATFORM"
run_sonar_scanner "${sonar_args[@]}"
fi
}

# FIXME BUILD-8337? this is similar to source github-env <BUILD|BUILD-PRIVATE>
Expand Down Expand Up @@ -231,7 +289,7 @@ build_poetry() {

if [ "${BUILD_ENABLE_SONAR}" = "true" ]; then
read -ra sonar_args <<< "$BUILD_SONAR_ARGS"
run_sonar_scanner "${sonar_args[@]}"
run_sonar_analysis "${sonar_args[@]}"
fi

if [ "${BUILD_ENABLE_DEPLOY}" = "true" ]; then
Expand Down
122 changes: 101 additions & 21 deletions spec/build-poetry_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export SONAR_HOST_URL="https://sonarqube.test"
export SONAR_TOKEN="dummy-sonar-token"
export GITHUB_SHA="dummy-sha"
export GITHUB_RUN_ID="dummy-run-id"
export SONAR_PLATFORM="next"
export NEXT_URL="https://next.sonarqube.com"
export NEXT_TOKEN="next-token"
export SQC_US_URL="https://sonarqube-us.com"
export SQC_US_TOKEN="sqc-us-token"
export SQC_EU_URL="https://sonarcloud.io"
export SQC_EU_TOKEN="sqc-eu-token"
export RUN_SHADOW_SCANS="false"

Describe 'build-poetry/build.sh'
It 'does not run build_poetry() if the script is sourced'
Expand Down Expand Up @@ -126,6 +134,38 @@ Describe 'set_build_env()'
End

Describe 'helper functions'
Describe 'set_sonar_platform_vars()'
It 'sets correct URL and token for next platform'
When call set_sonar_platform_vars "next"
The status should be success
The line 1 should equal 'Using Sonar platform: next (URL: https://next.sonarqube.com)'
The variable SONAR_HOST_URL should equal "https://next.sonarqube.com"
The variable SONAR_TOKEN should equal "next-token"
End

It 'sets correct URL and token for sqc-us platform'
When call set_sonar_platform_vars "sqc-us"
The status should be success
The line 1 should equal 'Using Sonar platform: sqc-us (URL: https://sonarqube-us.com)'
The variable SONAR_HOST_URL should equal "https://sonarqube-us.com"
The variable SONAR_TOKEN should equal "sqc-us-token"
End

It 'sets correct URL and token for sqc-eu platform'
When call set_sonar_platform_vars "sqc-eu"
The status should be success
The line 1 should equal 'Using Sonar platform: sqc-eu (URL: https://sonarcloud.io)'
The variable SONAR_HOST_URL should equal "https://sonarcloud.io"
The variable SONAR_TOKEN should equal "sqc-eu-token"
End

It 'returns error for unknown platform'
When call set_sonar_platform_vars "unknown"
The status should be failure
The line 1 of error should equal 'ERROR: Unknown sonar platform '"'"'unknown'"'"'. Expected: next, sqc-us, or sqc-eu'
End
End

Describe 'is_maintenance_branch()'
It 'returns true for branch-* pattern'
export GITHUB_REF_NAME="branch-1.2"
Expand Down Expand Up @@ -283,16 +323,18 @@ Describe 'build_poetry()'
The line 4 should equal 'Deploy Pull Request: false'
The line 5 should equal '======= Building main branch ======='
The line 8 should equal 'poetry build'
The line 9 should equal 'poetry run pip install pysonar'
The line 10 should equal 'poetry run pysonar -Dsonar.host.url=https://sonarqube.test -Dsonar.token=dummy-sonar-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo'
The line 11 should equal 'SonarQube scanner finished'
The line 12 should equal 'jf config remove repox'
The line 13 should equal 'jf config add repox --artifactory-url https://dummy.repox --access-token <deploy token>'
The line 14 should include '/dist'
The line 15 should equal 'jf rt upload ./ <deploy repo>/poetry/1.0.0.42/ --module=poetry:1.0.0.42 --build-name=my-repo --build-number=42'
The line 17 should equal 'jf rt build-collect-env my-repo 42'
The line 18 should include 'jf rt build-publish my-repo 42'
The line 19 should include '=== Build completed successfully ==='
The line 9 should equal '=== Running Sonar analysis on selected platform: next ==='
The line 10 should equal 'Using Sonar platform: next (URL: https://next.sonarqube.com)'
The line 11 should equal 'poetry run pip install pysonar'
The line 12 should equal 'poetry run pysonar -Dsonar.host.url=https://next.sonarqube.com -Dsonar.token=next-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo'
The line 13 should equal 'SonarQube scanner finished for platform: next.sonarqube.com'
The line 14 should equal 'jf config remove repox'
The line 15 should equal 'jf config add repox --artifactory-url https://dummy.repox --access-token <deploy token>'
The line 16 should include '/dist'
The line 17 should equal 'jf rt upload ./ <deploy repo>/poetry/1.0.0.42/ --module=poetry:1.0.0.42 --build-name=my-repo --build-number=42'
The line 19 should equal 'jf rt build-collect-env my-repo 42'
The line 20 should include 'jf rt build-publish my-repo 42'
The line 21 should include '=== Build completed successfully ==='
The status should be success
End

Expand All @@ -309,9 +351,12 @@ Describe 'build_poetry()'
The line 5 should equal '======= Building pull request ======='
The line 6 should equal '======= no deploy ======='
The line 9 should equal 'poetry build'
The line 11 should equal 'poetry run pysonar -Dsonar.host.url=https://sonarqube.test -Dsonar.token=dummy-sonar-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo -Dsonar.analysis.prNumber=123'
The line 12 should equal 'SonarQube scanner finished'
The line 13 should equal '=== Build completed successfully ==='
The line 10 should equal '=== Running Sonar analysis on selected platform: next ==='
The line 11 should equal 'Using Sonar platform: next (URL: https://next.sonarqube.com)'
The line 12 should equal 'poetry run pip install pysonar'
The line 13 should equal 'poetry run pysonar -Dsonar.host.url=https://next.sonarqube.com -Dsonar.token=next-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo -Dsonar.analysis.prNumber=123'
The line 14 should equal 'SonarQube scanner finished for platform: next.sonarqube.com'
The line 15 should equal '=== Build completed successfully ==='
The status should be success
End

Expand All @@ -329,14 +374,17 @@ Describe 'build_poetry()'
The line 5 should equal '======= Building pull request ======='
The line 6 should equal '======= with deploy ======='
The line 9 should equal 'poetry build'
The line 11 should equal 'poetry run pysonar -Dsonar.host.url=https://sonarqube.test -Dsonar.token=dummy-sonar-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo -Dsonar.analysis.prNumber=123'
The line 12 should equal 'SonarQube scanner finished'
The line 13 should equal "jf config remove repox"
The line 14 should equal "jf config add repox --artifactory-url https://dummy.repox --access-token <deploy token>"
The line 15 should include "/dist"
The line 16 should equal "jf rt upload ./ <deploy repo>/poetry/1.0.0.42/ --module=poetry:1.0.0.42 --build-name=my-repo --build-number=42"
The line 18 should equal "jf rt build-collect-env my-repo 42"
The line 19 should include "jf rt build-publish my-repo 42"
The line 10 should equal '=== Running Sonar analysis on selected platform: next ==='
The line 11 should equal 'Using Sonar platform: next (URL: https://next.sonarqube.com)'
The line 12 should equal 'poetry run pip install pysonar'
The line 13 should equal 'poetry run pysonar -Dsonar.host.url=https://next.sonarqube.com -Dsonar.token=next-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo -Dsonar.analysis.prNumber=123'
The line 14 should equal 'SonarQube scanner finished for platform: next.sonarqube.com'
The line 15 should equal "jf config remove repox"
The line 16 should equal "jf config add repox --artifactory-url https://dummy.repox --access-token <deploy token>"
The line 17 should include "/dist"
The line 18 should equal "jf rt upload ./ <deploy repo>/poetry/1.0.0.42/ --module=poetry:1.0.0.42 --build-name=my-repo --build-number=42"
The line 20 should equal "jf rt build-collect-env my-repo 42"
The line 21 should include "jf rt build-publish my-repo 42"
The status should be success
End

Expand Down Expand Up @@ -393,4 +441,36 @@ Describe 'build_poetry()'
The variable BUILD_ENABLE_SONAR should equal "false"
The variable BUILD_ENABLE_DEPLOY should equal "false"
End

It 'runs shadow scans on all platforms when RUN_SHADOW_SCANS is true'
export PULL_REQUEST=""
export GITHUB_REF_NAME="main"
export RUN_SHADOW_SCANS="true"

When call build_poetry
The line 1 should equal '=== Poetry Build, Deploy, and Analyze ==='
The line 2 should equal 'Branch: main'
The line 3 should equal 'Pull Request: '
The line 4 should equal 'Deploy Pull Request: false'
The line 5 should equal '======= Building main branch ======='
The line 8 should equal 'poetry build'
The line 9 should equal '=== Running Sonar analysis on all platforms (shadow scan enabled) ==='
The line 10 should equal '--- Analyzing with platform: next ---'
The line 11 should equal 'Using Sonar platform: next (URL: https://next.sonarqube.com)'
The line 12 should equal 'poetry run pip install pysonar'
The line 13 should equal 'poetry run pysonar -Dsonar.host.url=https://next.sonarqube.com -Dsonar.token=next-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo'
The line 14 should equal 'SonarQube scanner finished for platform: next.sonarqube.com'
The line 15 should equal '--- Analyzing with platform: sqc-us ---'
The line 16 should equal 'Using Sonar platform: sqc-us (URL: https://sonarqube-us.com)'
The line 17 should equal 'poetry run pip install pysonar'
The line 18 should equal 'poetry run pysonar -Dsonar.host.url=https://sonarqube-us.com -Dsonar.token=sqc-us-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo'
The line 19 should equal 'SonarQube scanner finished for platform: sonarqube-us.com'
The line 20 should equal '--- Analyzing with platform: sqc-eu ---'
The line 21 should equal 'Using Sonar platform: sqc-eu (URL: https://sonarcloud.io)'
The line 22 should equal 'poetry run pip install pysonar'
The line 23 should equal 'poetry run pysonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.token=sqc-eu-token -Dsonar.analysis.buildNumber=42 -Dsonar.analysis.pipeline=dummy-run-id -Dsonar.analysis.sha1=dummy-sha -Dsonar.analysis.repository=my-org/my-repo'
The line 24 should equal 'SonarQube scanner finished for platform: sonarcloud.io'
The line 25 should equal '=== Completed Sonar analysis on all platforms ==='
The status should be success
End
End