Skip to content
Draft
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
400 changes: 400 additions & 0 deletions .github/COVERAGE.md

Large diffs are not rendered by default.

128 changes: 128 additions & 0 deletions .github/coverage-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Coverage Configuration for VisualSign Parser
# This file defines coverage thresholds and policies for different packages

# Global thresholds (apply to all packages unless overridden)
global:
critical: 50 # Below this is considered critical
warning: 70 # Below this generates a warning
good: 80 # At or above this is considered good

# Fail PR if coverage drops by more than this percentage
max_drop: 5.0

# Fail PR if any package is below critical threshold
fail_on_critical: true

# Per-package thresholds (override global settings)
packages:
# Core library - high standards
visualsign:
critical: 80
warning: 85
good: 90
max_drop: 3.0

# Chain parsers - good standards
visualsign-ethereum:
critical: 60
warning: 70
good: 80
max_drop: 5.0

visualsign-solana:
critical: 70
warning: 75
good: 85
max_drop: 5.0

visualsign-sui:
critical: 60
warning: 70
good: 80
max_drop: 5.0

# Parser app - critical service
parser_app:
critical: 60
warning: 70
good: 80
max_drop: 5.0

# Stub implementations - lower requirements
visualsign-tron:
critical: 30
warning: 50
good: 70
max_drop: 10.0

visualsign-unspecified:
critical: 50
warning: 60
good: 70
max_drop: 10.0

# Package groups for reporting
groups:
core:
- visualsign

chain_parsers:
- visualsign-ethereum
- visualsign-solana
- visualsign-sui
- visualsign-tron
- visualsign-unspecified

services:
- parser_app
- parser_cli
- parser_host

infrastructure:
- generated
- metrics
- health_check
- integration

# Coverage report options
report:
# Include module-level breakdown in PR comments
show_modules: true

# Show file-level coverage for critical packages
show_files_for_critical: true

# Include trend chart (if base coverage available)
show_trends: true

# Add suggestions for improving coverage
show_suggestions: true

# CI behavior
ci:
# Post comment on every PR
comment_on_pr: true

# Update existing comment instead of creating new ones
update_comment: true

# Run coverage on push to main
run_on_main: true

# Cache base coverage for faster comparisons
cache_base_coverage: true

# Upload to codecov.io
upload_to_codecov: false # Set to true if you have CODECOV_TOKEN

# Dependency tracking
dependencies:
# Automatically test packages that depend on changed packages
test_dependents: true

# Maximum depth for dependency traversal
max_depth: 3

# Exclude certain packages from dependent testing
exclude_dependents:
- generated # Always generated, doesn't need coverage
54 changes: 54 additions & 0 deletions .github/scripts/check-coverage-thresholds.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/bash
set -euo pipefail

# Check if coverage meets minimum thresholds
# Returns non-zero exit code if any package is below threshold

echo "🎯 Checking coverage thresholds..."

# Define thresholds
CRITICAL_THRESHOLD=50
WARNING_THRESHOLD=70
GOOD_THRESHOLD=80

# Track failures
FAILED=false
WARNINGS=0

# Check each package
if [ -d "coverage-artifacts" ]; then
for artifact_dir in coverage-artifacts/coverage-*; do
if [ -d "$artifact_dir" ]; then
pkg_name=$(basename "$artifact_dir" | sed 's/^coverage-//')
stats_file="$artifact_dir/coverage-${pkg_name}-stats.json"

if [ -f "$stats_file" ]; then
coverage=$(jq -r '.coverage_pct' "$stats_file")

if (( $(echo "$coverage < $CRITICAL_THRESHOLD" | bc -l) )); then
echo "❌ $pkg_name: ${coverage}% (below critical threshold of ${CRITICAL_THRESHOLD}%)"
FAILED=true
elif (( $(echo "$coverage < $WARNING_THRESHOLD" | bc -l) )); then
echo "⚠️ $pkg_name: ${coverage}% (below warning threshold of ${WARNING_THRESHOLD}%)"
WARNINGS=$((WARNINGS + 1))
elif (( $(echo "$coverage < $GOOD_THRESHOLD" | bc -l) )); then
echo "🟢 $pkg_name: ${coverage}% (acceptable)"
else
echo "✅ $pkg_name: ${coverage}% (excellent)"
fi
fi
fi
done
fi

echo ""
if [ "$FAILED" = true ]; then
echo "❌ Coverage check FAILED - some packages below critical threshold"
exit 1
elif [ $WARNINGS -gt 0 ]; then
echo "⚠️ Coverage check PASSED with $WARNINGS warning(s)"
exit 0
else
echo "✅ All packages meet coverage thresholds!"
exit 0
fi
134 changes: 134 additions & 0 deletions .github/scripts/detect-changed-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/bin/bash
set -euo pipefail

# This script detects which Rust packages have changed and which packages depend on them
# It outputs JSON arrays for use in GitHub Actions matrix

echo "🔍 Detecting changed packages..."

# Determine base ref
if [ "${GITHUB_BASE_REF:-}" != "" ]; then
BASE_REF="origin/${GITHUB_BASE_REF}"
else
BASE_REF="HEAD~1"
fi

# Get changed files
CHANGED_FILES=$(git diff --name-only "$BASE_REF"...HEAD | grep -E '^src/.*\.(rs|toml)$' || true)

if [ -z "$CHANGED_FILES" ]; then
echo "No Rust files changed"
echo "packages=[]" >> "$GITHUB_OUTPUT"
echo "dependents=[]" >> "$GITHUB_OUTPUT"
echo "all_affected=[]" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "Changed files:"
echo "$CHANGED_FILES"

# Extract package names from changed files
declare -A CHANGED_PACKAGES
declare -A ALL_AFFECTED_PACKAGES

for file in $CHANGED_FILES; do
# Extract package directory (e.g., src/visualsign or src/chain_parsers/visualsign-solana)
if [[ $file =~ ^src/([^/]+)(/([^/]+))?/ ]]; then
if [ "${BASH_REMATCH[3]}" != "" ]; then
# Path like src/chain_parsers/visualsign-solana/...
pkg="${BASH_REMATCH[3]}"
else
# Path like src/visualsign/... or src/parser/app/...
if [[ $file =~ ^src/parser/([^/]+)/ ]]; then
pkg="parser_${BASH_REMATCH[1]}"
else
pkg="${BASH_REMATCH[1]}"
fi
fi

# Normalize package name (replace - with _)
pkg_normalized=$(echo "$pkg" | tr '-' '_')
CHANGED_PACKAGES[$pkg_normalized]=1
ALL_AFFECTED_PACKAGES[$pkg_normalized]=1
fi
done

echo ""
echo "📦 Directly changed packages:"
for pkg in "${!CHANGED_PACKAGES[@]}"; do
echo " - $pkg"
done

# Function to find packages that depend on a given package
find_dependents() {
local target_pkg=$1
local dependents=()

# Parse workspace Cargo.toml to get all packages
cd src

# Get all workspace members
while IFS= read -r member; do
if [ -f "$member/Cargo.toml" ]; then
# Check if this package depends on the target
if grep -q "^${target_pkg} = " "$member/Cargo.toml" 2>/dev/null || \
grep -q "path = \".*${target_pkg}\"" "$member/Cargo.toml" 2>/dev/null; then
# Extract package name from path
pkg_name=$(basename "$member")
dependents+=("$pkg_name")
fi
fi
done < <(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.source == null) | .manifest_path' | xargs -I {} dirname {} | sed 's|^.*/src/||')

cd ..

# Return dependents
printf '%s\n' "${dependents[@]}"
}

# Find all dependents
echo ""
echo "🔗 Finding dependent packages..."

for pkg in "${!CHANGED_PACKAGES[@]}"; do
# Convert package name format (e.g., visualsign_ethereum -> visualsign-ethereum)
pkg_with_dashes=$(echo "$pkg" | tr '_' '-')

while IFS= read -r dependent; do
if [ -n "$dependent" ]; then
dependent_normalized=$(echo "$dependent" | tr '-' '_')
if [ ! "${CHANGED_PACKAGES[$dependent_normalized]:-}" ]; then
ALL_AFFECTED_PACKAGES[$dependent_normalized]=1
echo " - $dependent (depends on $pkg)"
fi
fi
done < <(find_dependents "$pkg_with_dashes")
done

# Convert to JSON arrays
CHANGED_JSON=$(printf '%s\n' "${!CHANGED_PACKAGES[@]}" | jq -R -s -c 'split("\n") | map(select(length > 0))')
ALL_AFFECTED_JSON=$(printf '%s\n' "${!ALL_AFFECTED_PACKAGES[@]}" | jq -R -s -c 'split("\n") | map(select(length > 0))')

# Calculate dependents (all_affected - changed)
DEPENDENTS=()
for pkg in "${!ALL_AFFECTED_PACKAGES[@]}"; do
if [ ! "${CHANGED_PACKAGES[$pkg]:-}" ]; then
DEPENDENTS+=("$pkg")
fi
done

DEPENDENTS_JSON=$(printf '%s\n' "${DEPENDENTS[@]}" | jq -R -s -c 'split("\n") | map(select(length > 0))')

echo ""
echo "📊 Summary:"
echo " Directly changed: $(echo "$CHANGED_JSON" | jq 'length')"
echo " Dependents affected: $(echo "$DEPENDENTS_JSON" | jq 'length')"
echo " Total packages to test: $(echo "$ALL_AFFECTED_JSON" | jq 'length')"

# Output for GitHub Actions
echo "packages=$CHANGED_JSON" >> "$GITHUB_OUTPUT"
echo "dependents=$DEPENDENTS_JSON" >> "$GITHUB_OUTPUT"
echo "all_affected=$ALL_AFFECTED_JSON" >> "$GITHUB_OUTPUT"

echo ""
echo "✅ Detection complete"
Loading
Loading