Skip to content

Merge pull request #1167 from Nanle-code/dependabot/npm_and_yarn/regi… #284

Merge pull request #1167 from Nanle-code/dependabot/npm_and_yarn/regi…

Merge pull request #1167 from Nanle-code/dependabot/npm_and_yarn/regi… #284

name: Mutation Testing (Wallet Import)
on:
push:
branches: [main, master, develop]
paths:
- 'src/utils/wallet_import.rs'
- 'src/utils/crypto.rs'
- '.cargo-mutants.toml'
- '.github/workflows/mutation-testing.yml'
- 'Cargo.toml'
pull_request:
paths:
- 'src/utils/wallet_import.rs'
- 'src/utils/crypto.rs'
- '.cargo-mutants.toml'
- '.github/workflows/mutation-testing.yml'
- 'Cargo.toml'
# Weekly mutation testing run (Monday 3 AM UTC) to detect regressions
schedule:
- cron: '0 3 * * 1'
# Allow manual dispatch with configurable parameters
workflow_dispatch:
inputs:
max_mutants:
description: 'Maximum mutants to generate (0 = unlimited)'
required: false
default: '0'
min_kill_rate:
description: 'Minimum kill rate threshold (0.0-1.0)'
required: false
default: '0.85'
# Cancel in-progress runs when a new commit is pushed to the same branch
concurrency:
group: mutation-testing-${{ github.ref }}
cancel-in-progress: true
jobs:
mutation-testing:
name: Mutation Testing - Wallet Import/Backup
runs-on: ubuntu-latest
timeout-minutes: 120
env:
MIN_KILL_RATE: ${{ github.event.inputs.min_kill_rate || '0.85' }}
MAX_MUTANTS: ${{ github.event.inputs.max_mutants || '0' }}
steps:
- uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-mutants
run: cargo install cargo-mutants
- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y libudev-dev
- name: Cache cargo registry and target
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-mutants-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-mutants-
- name: Run baseline tests
run: cargo test --lib wallet_import --locked
- name: Generate mutation testing report for wallet_import
run: |
mkdir -p mutation-reports
cargo mutants \
--file src/utils/wallet_import.rs \
--jobs 4 \
$([ "$MAX_MUTANTS" != "0" ] && echo "--max-mutants $MAX_MUTANTS" || echo "") \
2>&1 | tee mutation-reports/wallet_import.log || EXIT_CODE=$?
# cargo mutants writes results under mutants.out/; copy them into our report dir.
if [ -d mutants.out ]; then
cp -r mutants.out/* mutation-reports/ 2>/dev/null || true
fi
- name: Parse mutation testing results
id: parse_results
run: python3 scripts/parse-mutants-report.py
- name: Comment PR with mutation results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const kill_rate = '${{ steps.parse_results.outputs.kill_rate }}';
const killed = '${{ steps.parse_results.outputs.killed }}';
const survived = '${{ steps.parse_results.outputs.survived }}';
const total = '${{ steps.parse_results.outputs.total }}';
const threshold = '${{ env.MIN_KILL_RATE }}';
const comment = `## 🧬 Mutation Testing Results
| Metric | Value |

Check failure on line 106 in .github/workflows/mutation-testing.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/mutation-testing.yml

Invalid workflow file

You have an error in your yaml syntax on line 106
|--------|-------|
| **Kill Rate** | ${(parseFloat(kill_rate) * 100).toFixed(1)}% |
| **Killed** | ${killed}/${total} mutants |
| **Survived** | ${survived}/${total} mutants |
| **Threshold** | ${(parseFloat(threshold) * 100).toFixed(1)}% |
Module: \`src/utils/wallet_import.rs\` (wallet backup/import cryptographic code)
${parseFloat(kill_rate) >= parseFloat(threshold) ? '✓ **PASSED**: Kill rate meets threshold' : '❌ **FAILED**: Kill rate below threshold'}
See [mutation-reports](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Upload mutation reports as artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: mutation-reports
path: |
mutation-reports/
mutants.out/
retention-days: 30
- name: Check kill rate threshold
run: |
kill_rate="${{ steps.parse_results.outputs.kill_rate }}"
threshold="${{ env.MIN_KILL_RATE }}"
python3 -c "
kill_rate = float('$kill_rate') if '$kill_rate' else 0.0
threshold = float('$threshold')
if kill_rate < threshold:
print(f'❌ Mutation kill rate {kill_rate:.1%} is below threshold {threshold:.1%}')
raise SystemExit(1)
print(f'✓ Mutation kill rate {kill_rate:.1%} meets threshold {threshold:.1%}')
"
- name: Report to pull request
if: failure() && github.event_name == 'pull_request'
run: |
echo "## ❌ Mutation Testing Failed"
echo ""
echo "The wallet import/backup module's test suite is not sensitive enough to catch potential logic errors."
echo ""
echo "**Next steps:**"
echo "1. Review surviving mutants in the artifacts"
echo "2. Add or strengthen tests to kill surviving mutants"
echo "3. See MUTATION_TESTING.md for interpretation guide"