mirror of
https://github.com/storytold/craft-common-actions.git
synced 2026-11-07 03:01:35 +00:00
Bumps the actions group with 1 update in the / directory: [taiki-e/install-action](https://github.com/taiki-e/install-action). Updates `taiki-e/install-action` from 2.88.1 to 2.89.1 - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/68a389c788b2cd04016ce8c80ee23b80d2ab3d68...682ce6c3c696a4cd5168a05f98e51aa02b877941) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.89.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
424 lines
20 KiB
YAML
424 lines
20 KiB
YAML
name: SonarCloud
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
project-key:
|
|
description: "SonarCloud project key (defaults to storytold_<repo>)"
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
fonts-ref:
|
|
description: "craft-fonts commit for tests that lay out text (empty skips the checkout)"
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
pdf-test-fonts:
|
|
description: "Provision the caller's pinned PDF test fonts with scripts/fetch-pdf-test-fonts.py"
|
|
type: boolean
|
|
required: false
|
|
default: false
|
|
python-coverage-source:
|
|
description: "Optional Python source directory to measure; requires python-coverage-script"
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
python-coverage-script:
|
|
description: "Optional Python test script; requires python-coverage-source"
|
|
type: string
|
|
required: false
|
|
default: ""
|
|
timeout-minutes:
|
|
description: "Maximum job runtime, including coverage generation and the scan"
|
|
type: number
|
|
required: false
|
|
default: 90
|
|
shards:
|
|
description: >-
|
|
Run the Rust tests as this many parallel partitions of one prebuilt instrumented
|
|
archive (1 keeps the single `cargo llvm-cov` job; default 4). Doctests are not run when sharded.
|
|
type: number
|
|
required: false
|
|
default: 4
|
|
secrets:
|
|
SONAR_TOKEN:
|
|
description: "Legacy or repository-level SonarCloud analysis token"
|
|
required: false
|
|
SONAR_CLOUD_PAT:
|
|
description: "Organization-level SonarCloud personal access token"
|
|
required: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
# Vendored code and xtask, plus the test code cargo llvm-cov leaves out on its own (tests/,
|
|
# examples/, benches/, tests.rs, *_tests.rs): the sharded merge calls llvm-cov export directly,
|
|
# which would otherwise report that test code as covered source.
|
|
COVERAGE_IGNORE: '(^|/)(vendor|xtask|tests|examples|benches)/|/(tests\.rs|[0-9a-zA-Z_-]+[_-]tests\.rs)$'
|
|
|
|
jobs:
|
|
plan:
|
|
name: Plan coverage shards
|
|
if: inputs.shards > 1
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
outputs:
|
|
matrix: ${{ steps.matrix.outputs.matrix }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Build shard matrix
|
|
id: matrix
|
|
env:
|
|
SONAR_TOKEN: ${{ secrets.SONAR_CLOUD_PAT || secrets.SONAR_TOKEN }}
|
|
SHARDS: ${{ inputs.shards }}
|
|
run: |
|
|
# The matrix caps at 256 jobs, and nextest partitions need whole numbers.
|
|
case "$SHARDS" in
|
|
''|*[!0-9]*) echo "::error::shards must be a whole number, got '$SHARDS'"; exit 1 ;;
|
|
esac
|
|
if [ "$SHARDS" -gt 256 ]; then
|
|
echo "::error::shards must be at most 256 (the GitHub Actions matrix limit), got $SHARDS"
|
|
exit 1
|
|
fi
|
|
# Same gate as the scan job: no token or no Rust workspace means no coverage to shard.
|
|
if [ -n "$SONAR_TOKEN" ] && [ -f Cargo.toml ]; then
|
|
echo "matrix={\"shard\":[$(seq -s, 1 "$SHARDS")]}" >>"$GITHUB_OUTPUT"
|
|
else
|
|
echo 'matrix={"shard":[]}' >>"$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
build:
|
|
name: Build instrumented test archive
|
|
needs: plan
|
|
if: needs.plan.outputs.matrix != '{"shard":[]}'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Check out craft-fonts
|
|
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
|
|
with:
|
|
ref: ${{ inputs.fonts-ref }}
|
|
- name: Require requested craft-fonts
|
|
if: inputs.fonts-ref != ''
|
|
shell: bash
|
|
env:
|
|
CRAFT_FONTS_PATH: ${{ github.workspace }}/craft-fonts
|
|
run: |
|
|
echo "CRAFT_FONTS_DIR=$CRAFT_FONTS_PATH" >> "$GITHUB_ENV"
|
|
echo "CRAFT_FONTS_REQUIRED=1" >> "$GITHUB_ENV"
|
|
- name: Free disk space
|
|
run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
|
|
- name: Install Linux build dependencies
|
|
uses: storytold/craft-common-actions/actions/install-apt-packages@main
|
|
with:
|
|
packages: >-
|
|
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev
|
|
libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libasound2-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev
|
|
libgl1-mesa-dev mesa-vulkan-drivers
|
|
- name: Install Rust and cargo-llvm-cov
|
|
run: |
|
|
rustup toolchain install stable --profile minimal --component llvm-tools-preview
|
|
rustup default stable
|
|
- uses: taiki-e/install-action@682ce6c3c696a4cd5168a05f98e51aa02b877941 # v2.89.1
|
|
with:
|
|
tool: cargo-llvm-cov,cargo-nextest@0.9.150
|
|
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
|
|
with:
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Provision pinned PDF test fonts
|
|
if: inputs.pdf-test-fonts
|
|
shell: bash
|
|
run: |
|
|
python3 scripts/fetch-pdf-test-fonts.py "$RUNNER_TEMP/craft-pdf-test-fonts"
|
|
echo "CRAFT_PDF_TEST_FONT_DIR=$RUNNER_TEMP/craft-pdf-test-fonts" >> "$GITHUB_ENV"
|
|
- name: Build instrumented test archive
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
# Coverage comes from instrumentation, not DWARF; debuginfo is most of target/.
|
|
CARGO_PROFILE_DEV_DEBUG: "0"
|
|
run: |
|
|
# show-env sets the instrumentation flags the same way the unsharded run gets them.
|
|
# shellcheck disable=SC1090 # generated by cargo-llvm-cov at runtime
|
|
source <(cargo llvm-cov show-env --sh)
|
|
cargo nextest archive --workspace --archive-file nextest-archive.tar.zst
|
|
- name: Record the toolchain that built the archive
|
|
run: |
|
|
rustc -vV | sed -n 's/^release: //p' > rustc-release.txt
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: nextest-archive
|
|
path: |
|
|
nextest-archive.tar.zst
|
|
rustc-release.txt
|
|
retention-days: 1
|
|
|
|
coverage:
|
|
name: Tests ${{ matrix.shard }}/${{ inputs.shards }}
|
|
needs: [plan, build]
|
|
if: needs.plan.outputs.matrix != '{"shard":[]}'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.plan.outputs.matrix) }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Check out craft-fonts
|
|
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
|
|
with:
|
|
ref: ${{ inputs.fonts-ref }}
|
|
- name: Require requested craft-fonts
|
|
if: inputs.fonts-ref != ''
|
|
shell: bash
|
|
env:
|
|
CRAFT_FONTS_PATH: ${{ github.workspace }}/craft-fonts
|
|
run: |
|
|
echo "CRAFT_FONTS_DIR=$CRAFT_FONTS_PATH" >> "$GITHUB_ENV"
|
|
echo "CRAFT_FONTS_REQUIRED=1" >> "$GITHUB_ENV"
|
|
- name: Install Linux build dependencies
|
|
uses: storytold/craft-common-actions/actions/install-apt-packages@main
|
|
with:
|
|
packages: >-
|
|
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev
|
|
libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libasound2-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev
|
|
libgl1-mesa-dev mesa-vulkan-drivers
|
|
- uses: taiki-e/install-action@682ce6c3c696a4cd5168a05f98e51aa02b877941 # v2.89.1
|
|
with:
|
|
tool: cargo-nextest@0.9.150
|
|
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
with:
|
|
name: nextest-archive
|
|
path: archive
|
|
- name: Provision pinned PDF test fonts
|
|
if: inputs.pdf-test-fonts
|
|
shell: bash
|
|
run: |
|
|
python3 scripts/fetch-pdf-test-fonts.py "$RUNNER_TEMP/craft-pdf-test-fonts"
|
|
echo "CRAFT_PDF_TEST_FONT_DIR=$RUNNER_TEMP/craft-pdf-test-fonts" >> "$GITHUB_ENV"
|
|
- name: Run this shard's tests
|
|
env:
|
|
# Each instrumented binary writes its profile here; the scan job merges them.
|
|
LLVM_PROFILE_FILE: ${{ github.workspace }}/profraw/shard-${{ matrix.shard }}-%p-%m.profraw
|
|
run: |
|
|
mkdir -p profraw
|
|
# nextest exits 100 when tests fail. A red test must not hide the static analysis, so
|
|
# that alone keeps the job green. Any other exit means the shard could not run its
|
|
# tests at all (for example a test binary nextest cannot list): fail the job, because a
|
|
# shard that runs nothing would scan an empty coverage report.
|
|
rc=0
|
|
cargo nextest run --archive-file archive/nextest-archive.tar.zst \
|
|
--partition count:${{ matrix.shard }}/${{ inputs.shards }} --no-fail-fast || rc=$?
|
|
if [ "$rc" -ne 0 ] && [ "$rc" -ne 100 ]; then
|
|
echo "::error::nextest could not run shard ${{ matrix.shard }} (exit $rc)"
|
|
exit "$rc"
|
|
fi
|
|
if ! ls profraw/*.profraw >/dev/null 2>&1; then
|
|
echo "::error::shard ${{ matrix.shard }} produced no coverage profiles"
|
|
exit 1
|
|
fi
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: profraw-${{ matrix.shard }}
|
|
path: profraw/
|
|
if-no-files-found: ignore
|
|
retention-days: 1
|
|
|
|
sonarcloud:
|
|
name: SonarCloud Scan
|
|
needs: [plan, build, coverage]
|
|
# Scan unless a prerequisite failed outright; a red test shard still lets the scan measure what ran.
|
|
if: ${{ !cancelled() && contains(fromJSON('["success","skipped"]'), needs.plan.result) && contains(fromJSON('["success","skipped"]'), needs.build.result) && contains(fromJSON('["success","skipped"]'), needs.coverage.result) }}
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
- name: Check for SonarCloud token
|
|
id: token
|
|
env:
|
|
SONAR_TOKEN: ${{ secrets.SONAR_CLOUD_PAT || secrets.SONAR_TOKEN }}
|
|
run: |
|
|
if [ -n "$SONAR_TOKEN" ]; then
|
|
echo "available=true" >>"$GITHUB_OUTPUT"
|
|
else
|
|
echo "available=false" >>"$GITHUB_OUTPUT"
|
|
echo "::notice::SONAR_TOKEN is not available (e.g. a fork pull request); skipping SonarCloud scan."
|
|
fi
|
|
- name: Validate SonarCloud project key
|
|
id: project
|
|
if: steps.token.outputs.available == 'true'
|
|
shell: bash
|
|
env:
|
|
PROJECT_KEY: ${{ inputs.project-key != '' && inputs.project-key || format('storytold_{0}', github.event.repository.name) }}
|
|
LC_ALL: C
|
|
run: |
|
|
# The scan action splits args; reject characters that could introduce properties.
|
|
if [[ ! "$PROJECT_KEY" =~ ^[a-zA-Z0-9_][a-zA-Z0-9_.:-]*$ || ${#PROJECT_KEY} -gt 400 ]]; then
|
|
echo "::error::Invalid SonarCloud project key: must start with an alphanumeric character or underscore and contain only letters, digits, dash, underscore, period or colon (max 400 characters)."
|
|
exit 1
|
|
fi
|
|
printf 'key=%s\n' "$PROJECT_KEY" >>"$GITHUB_OUTPUT"
|
|
- name: Check out craft-fonts
|
|
if: steps.token.outputs.available == 'true' && inputs.shards <= 1
|
|
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
|
|
with:
|
|
ref: ${{ inputs.fonts-ref }}
|
|
- name: Require requested craft-fonts
|
|
if: inputs.fonts-ref != '' && steps.token.outputs.available == 'true' && inputs.shards <= 1
|
|
shell: bash
|
|
env:
|
|
CRAFT_FONTS_PATH: ${{ github.workspace }}/craft-fonts
|
|
run: |
|
|
echo "CRAFT_FONTS_DIR=$CRAFT_FONTS_PATH" >> "$GITHUB_ENV"
|
|
echo "CRAFT_FONTS_REQUIRED=1" >> "$GITHUB_ENV"
|
|
- name: Free disk space
|
|
# The instrumented workspace build overflows the ~14 GB free on a stock runner.
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
|
|
- name: Install Linux build dependencies
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
uses: storytold/craft-common-actions/actions/install-apt-packages@main
|
|
with:
|
|
packages: >-
|
|
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev
|
|
libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libasound2-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev
|
|
libgl1-mesa-dev mesa-vulkan-drivers
|
|
- name: Install Rust and cargo-llvm-cov
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
run: |
|
|
rustup toolchain install stable --profile minimal --component llvm-tools-preview
|
|
rustup default stable
|
|
- uses: taiki-e/install-action@682ce6c3c696a4cd5168a05f98e51aa02b877941 # v2.89.1
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
with:
|
|
tool: cargo-llvm-cov
|
|
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
with:
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Provision pinned PDF test fonts
|
|
if: inputs.pdf-test-fonts && steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
shell: bash
|
|
run: |
|
|
python3 scripts/fetch-pdf-test-fonts.py "$RUNNER_TEMP/craft-pdf-test-fonts"
|
|
echo "CRAFT_PDF_TEST_FONT_DIR=$RUNNER_TEMP/craft-pdf-test-fonts" >> "$GITHUB_ENV"
|
|
- name: Generate Rust coverage
|
|
id: coverage
|
|
if: steps.token.outputs.available == 'true' && hashFiles('Cargo.toml') != '' && inputs.shards <= 1
|
|
# A red test must not hide the static analysis, so keep going and scan what was measured.
|
|
continue-on-error: true
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
# Coverage comes from instrumentation, not DWARF; debuginfo is most of target/.
|
|
CARGO_PROFILE_DEV_DEBUG: "0"
|
|
run: >
|
|
cargo llvm-cov --workspace --ignore-run-fail --lcov --output-path lcov.info
|
|
--ignore-filename-regex "$COVERAGE_IGNORE"
|
|
- name: Download shard profiles and archive
|
|
if: steps.token.outputs.available == 'true' && inputs.shards > 1 && hashFiles('Cargo.toml') != ''
|
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
with:
|
|
pattern: profraw-*
|
|
path: profraw
|
|
merge-multiple: true
|
|
- name: Download test archive
|
|
if: steps.token.outputs.available == 'true' && inputs.shards > 1 && hashFiles('Cargo.toml') != ''
|
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
with:
|
|
name: nextest-archive
|
|
path: archive
|
|
- name: Install LLVM tools for the archive's toolchain
|
|
if: steps.token.outputs.available == 'true' && inputs.shards > 1 && hashFiles('Cargo.toml') != ''
|
|
run: rustup toolchain install "$(cat archive/rustc-release.txt)" --profile minimal --component llvm-tools-preview
|
|
- name: Combine shard coverage
|
|
if: steps.token.outputs.available == 'true' && inputs.shards > 1 && hashFiles('Cargo.toml') != ''
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
toolchain="$(cat archive/rustc-release.txt)"
|
|
llvm_bin="$(rustup run "$toolchain" rustc --print sysroot)/lib/rustlib/$(rustup run "$toolchain" rustc -vV | sed -n 's/^host: //p')/bin"
|
|
# Unpack outside the checkout: the scanner analyses everything under the workspace, and build
|
|
# output (generated sources) there would be counted as duplicated code.
|
|
extracted="$RUNNER_TEMP/coverage-archive"
|
|
mkdir -p "$extracted"
|
|
tar --zstd -xf archive/nextest-archive.tar.zst -C "$extracted"
|
|
# Only test binaries run on the target; helpers and proc-macros are not instrumented profile sources.
|
|
objects=()
|
|
while IFS= read -r name; do
|
|
while IFS= read -r -d '' file; do objects+=("$file"); done < <(find "$extracted" -type f -name "$name" -print0)
|
|
done < <(jq -r '."rust-binaries"[] | select(."build-platform" == "target") | ."binary-path" | split("/") | last' "$extracted/target/nextest/binaries-metadata.json")
|
|
if [ "${#objects[@]}" -eq 0 ]; then
|
|
echo "::error::No test binaries found in the archive metadata"
|
|
exit 1
|
|
fi
|
|
"$llvm_bin/llvm-profdata" merge -sparse profraw/*.profraw -o coverage.profdata
|
|
extra=()
|
|
for object in "${objects[@]:1}"; do extra+=(-object "$object"); done
|
|
"$llvm_bin/llvm-cov" export -format=lcov -instr-profile=coverage.profdata \
|
|
"${objects[0]}" "${extra[@]}" -ignore-filename-regex="$COVERAGE_IGNORE" >lcov.info
|
|
- name: Generate Python coverage
|
|
if: steps.token.outputs.available == 'true' && (inputs.python-coverage-source != '' || inputs.python-coverage-script != '')
|
|
shell: bash
|
|
env:
|
|
PYTHON_COVERAGE_SOURCE: ${{ inputs.python-coverage-source }}
|
|
PYTHON_COVERAGE_SCRIPT: ${{ inputs.python-coverage-script }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -z "$PYTHON_COVERAGE_SOURCE" || -z "$PYTHON_COVERAGE_SCRIPT" ]]; then
|
|
echo '::error::Python coverage requires both source and test script inputs'
|
|
exit 1
|
|
fi
|
|
if [[ ! -d "$PYTHON_COVERAGE_SOURCE" || ! -f "$PYTHON_COVERAGE_SCRIPT" ]]; then
|
|
echo '::error::Python coverage source directory or test script is missing'
|
|
exit 1
|
|
fi
|
|
source_dir=$(realpath -- "$PYTHON_COVERAGE_SOURCE")
|
|
test_script=$(realpath -- "$PYTHON_COVERAGE_SCRIPT")
|
|
workspace_dir=$(pwd -P)
|
|
case "$source_dir" in
|
|
"$workspace_dir"|"$workspace_dir"/*) ;;
|
|
*) echo '::error::Python coverage source must be inside the checkout'; exit 1 ;;
|
|
esac
|
|
case "$test_script" in
|
|
"$workspace_dir"/*) ;;
|
|
*) echo '::error::Python test script must be inside the checkout'; exit 1 ;;
|
|
esac
|
|
case "$source_dir$test_script" in
|
|
*','*|*'['*|*']'*|*'*'*|*'?'*) echo '::error::Python coverage paths must not contain commas or glob characters'; exit 1 ;;
|
|
esac
|
|
coverage_env=$(mktemp -d "$RUNNER_TEMP/python-coverage.XXXXXX")
|
|
python3 -m venv "$coverage_env"
|
|
"$coverage_env/bin/python" -m pip install --disable-pip-version-check coverage==7.10.7
|
|
export COVERAGE_FILE="$coverage_env/.coverage"
|
|
export PYTHON_COVERAGE_SOURCE_REAL="$source_dir"
|
|
export PYTHON_COVERAGE_SCRIPT_REAL="$test_script"
|
|
coverage_config="$coverage_env/coverage.ini"
|
|
# Environment substitution keeps paths literal and shares selection with reporting.
|
|
printf '%s\n' '[run]' 'branch = true' 'source = ${PYTHON_COVERAGE_SOURCE_REAL}' 'omit = ${PYTHON_COVERAGE_SCRIPT_REAL}' > "$coverage_config"
|
|
status=0
|
|
"$coverage_env/bin/python" -m coverage run --rcfile="$coverage_config" "$test_script" || status=$?
|
|
"$coverage_env/bin/python" -m coverage xml --rcfile="$coverage_config" -o python-coverage.xml
|
|
exit "$status"
|
|
- name: SonarCloud Scan
|
|
if: steps.token.outputs.available == 'true'
|
|
uses: SonarSource/sonarqube-scan-action@4d1dc0c91ee400dcf8a6dddf2f705ac36542e304 # v8.4.0
|
|
env:
|
|
SONAR_TOKEN: ${{ secrets.SONAR_CLOUD_PAT || secrets.SONAR_TOKEN }}
|
|
SONAR_HOST_URL: https://sonarcloud.io
|
|
with:
|
|
args: >
|
|
"-Dsonar.projectKey=${{ steps.project.outputs.key }}"
|
|
-Dsonar.organization=storytold
|
|
-Dsonar.rust.lcov.reportPaths=lcov.info
|
|
"-Dsonar.cpd.exclusions=**/i18n/**"
|