mirror of
https://github.com/storytold/craft-common-actions.git
synced 2026-11-15 15:02:24 +00:00
Merge pull request #241 from storytold/codex/sonar-rust-test-threads
ci: expose Rust test thread limit for single-job coverage
This commit is contained in:
2 files changed
+67
-1
No files matched your search
@@ -67,6 +67,13 @@ on:
|
||||
type: number
|
||||
required: false
|
||||
default: 4
|
||||
rust-test-threads:
|
||||
description: >-
|
||||
Optional positive Rust test-harness thread count for the single-job cargo llvm-cov path
|
||||
(shards <= 1). Empty keeps the test harness default; ignored by sharded nextest runs.
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
secrets:
|
||||
SONAR_TOKEN:
|
||||
description: "Legacy or repository-level SonarCloud analysis token"
|
||||
@@ -670,13 +677,19 @@ jobs:
|
||||
CARGO_PROFILE_DEV_DEBUG: "0"
|
||||
SQLX_OFFLINE_INPUT: ${{ inputs.sqlx-offline }}
|
||||
CARGO_FEATURES: ${{ inputs.cargo-features }}
|
||||
RUST_TEST_THREADS_INPUT: ${{ inputs.rust-test-threads }}
|
||||
run: |
|
||||
# Opt-in build settings; validated because they reach the cargo command line.
|
||||
if [[ ! "$CARGO_FEATURES" =~ ^[A-Za-z0-9_/,-]*$ ]]; then
|
||||
echo "::error::cargo-features may only hold feature names, '/', '-', '_' and ',', got '$CARGO_FEATURES'"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$RUST_TEST_THREADS_INPUT" && ! "$RUST_TEST_THREADS_INPUT" =~ ^[1-9][0-9]*$ ]]; then
|
||||
echo "::error::rust-test-threads must be a positive integer, got '$RUST_TEST_THREADS_INPUT'"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$SQLX_OFFLINE_INPUT" = true ]; then export SQLX_OFFLINE=true; fi
|
||||
if [ -n "$RUST_TEST_THREADS_INPUT" ]; then export RUST_TEST_THREADS="$RUST_TEST_THREADS_INPUT"; fi
|
||||
features=()
|
||||
if [ -n "$CARGO_FEATURES" ]; then features=(--features "$CARGO_FEATURES"); fi
|
||||
# Run every instrumented test and remember failures, but still create coverage so
|
||||
|
||||
@@ -174,7 +174,8 @@ class SonarCloudTests(unittest.TestCase):
|
||||
cwd=root,
|
||||
env={**os.environ, **coverage.get('env', {}), 'PATH': f'{bin_dir}:{os.environ["PATH"]}',
|
||||
'CARGO_CALLS': str(calls), 'GITHUB_OUTPUT': str(output),
|
||||
'CARGO_FEATURES': '', 'SQLX_OFFLINE_INPUT': 'false', 'COVERAGE_IGNORE': ''},
|
||||
'CARGO_FEATURES': '', 'SQLX_OFFLINE_INPUT': 'false',
|
||||
'RUST_TEST_THREADS_INPUT': '', 'COVERAGE_IGNORE': ''},
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
@@ -186,6 +187,58 @@ class SonarCloudTests(unittest.TestCase):
|
||||
self.assertIn('--no-report --no-fail-fast', invocations[0])
|
||||
self.assertEqual(invocations[1], 'llvm-cov report --lcov --output-path lcov.info --ignore-filename-regex ')
|
||||
|
||||
def test_rust_test_threads_input_is_validated_and_exported(self):
|
||||
coverage = next(step for step in self.steps if step.get('id') == 'coverage')
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
bin_dir = root / 'bin'
|
||||
bin_dir.mkdir()
|
||||
cargo = bin_dir / 'cargo'
|
||||
cargo.write_text(
|
||||
'#!/usr/bin/env bash\n'
|
||||
'printf "%s\\n" "${RUST_TEST_THREADS-unset}" >> "$THREADS_CALLS"\n'
|
||||
'if [[ "$*" == *"--no-report"* ]]; then exit 0; fi\n'
|
||||
'printf "TN:\\n" > lcov.info\n'
|
||||
)
|
||||
cargo.chmod(0o755)
|
||||
calls = root / 'threads'
|
||||
result = subprocess.run(
|
||||
['bash', '--noprofile', '--norc', '-e', '-o', 'pipefail', '-c', coverage['run']],
|
||||
cwd=root,
|
||||
env={**os.environ, **coverage.get('env', {}), 'PATH': f'{bin_dir}:{os.environ["PATH"]}',
|
||||
'THREADS_CALLS': str(calls), 'GITHUB_OUTPUT': str(root / 'output'),
|
||||
'CARGO_FEATURES': '', 'SQLX_OFFLINE_INPUT': 'false',
|
||||
'RUST_TEST_THREADS_INPUT': '1', 'COVERAGE_IGNORE': ''},
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(calls.read_text().splitlines(), ['1', '1'])
|
||||
|
||||
def test_invalid_rust_test_threads_cannot_start_coverage(self):
|
||||
coverage = next(step for step in self.steps if step.get('id') == 'coverage')
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
bin_dir = root / 'bin'
|
||||
bin_dir.mkdir()
|
||||
cargo = bin_dir / 'cargo'
|
||||
cargo.write_text('#!/usr/bin/env bash\nprintf called >> "$CARGO_CALLS"\n')
|
||||
cargo.chmod(0o755)
|
||||
calls = root / 'calls'
|
||||
result = subprocess.run(
|
||||
['bash', '--noprofile', '--norc', '-e', '-o', 'pipefail', '-c', coverage['run']],
|
||||
cwd=root,
|
||||
env={**os.environ, **coverage.get('env', {}), 'PATH': f'{bin_dir}:{os.environ["PATH"]}',
|
||||
'CARGO_CALLS': str(calls), 'GITHUB_OUTPUT': str(root / 'output'),
|
||||
'CARGO_FEATURES': '', 'SQLX_OFFLINE_INPUT': 'false',
|
||||
'RUST_TEST_THREADS_INPUT': '0', 'COVERAGE_IGNORE': ''},
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn('rust-test-threads must be a positive integer', result.stdout)
|
||||
self.assertFalse(calls.exists())
|
||||
|
||||
def test_coverage_generation_failure_is_blocking_after_scan(self):
|
||||
coverage = next(step for step in self.steps if step.get('id') == 'coverage')
|
||||
failure = next(step for step in self.steps
|
||||
|
||||
Reference in new issue
Block a user