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
300 changes: 300 additions & 0 deletions .github/workflows/pr-quality-gates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
name: PR Quality Gates

on:
pull_request:
branches: [main]
push:
branches: [main]

permissions:
contents: read
pull-requests: read

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and test tools
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest
- name: pytest passes
run: python -m pytest -q tests

line-coverage:
name: Line Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and coverage tools
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest pytest-cov coverage[toml]
- name: 100% line coverage
run: python -m pytest -q --cov=aethermesh_core --cov-report=term-missing --cov-fail-under=100 tests

branch-coverage:
name: Branch Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and coverage tools
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest pytest-cov coverage[toml]
- name: 100% branch coverage
run: python -m pytest -q --cov=aethermesh_core --cov-branch --cov-report=term-missing --cov-fail-under=100 tests

mutation-score:
name: Mutation Score
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and mutation tools
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest mutmut
- name: mutation score >= 95%
run: |
mutmut run --max-children 4
python scripts/ci_quality_gates.py mutation-score --minimum 95

ruff-check:
name: Ruff Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install ruff
run: python -m pip install --upgrade ruff
- name: ruff check passes
run: ruff check src tests scripts

ruff-format:
name: Ruff Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install ruff
run: python -m pip install --upgrade ruff
- name: ruff format check passes
run: ruff format --check src tests scripts

strict-type-check:
name: Strict Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and mypy
run: |
python -m pip install --upgrade pip
python -m pip install -e . mypy
- name: mypy strict passes
run: mypy --strict src scripts

duplicate-code:
name: Duplicate Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: duplicate code check passes
run: npx --yes jscpd@5.0.11 src --format python --threshold 0 --reporters console --ignore "**/__pycache__/**" --no-tips

complexity:
name: Complexity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install radon
run: python -m pip install --upgrade radon
- name: complexity check passes
run: radon cc src tests -s -n E

dead-code:
name: Dead Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install vulture
run: python -m pip install --upgrade vulture
- name: dead code check passes
run: vulture src tests --min-confidence 100

bandit:
name: Bandit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install bandit
run: python -m pip install --upgrade bandit
- name: bandit security scan passes
run: bandit -q -r src

pip-audit:
name: Pip Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install pip-audit
run: python -m pip install --upgrade pip-audit
- name: pip-audit passes
run: python scripts/ci_quality_gates.py dependency-audit

secret-scan:
name: Secret Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: '1.25.x'
- name: no secrets detected
run: |
go install github.com/zricethezav/gitleaks/v8@latest
"$HOME/go/bin/gitleaks" detect --no-banner --source . --redact --verbose

test-integrity:
name: Test Integrity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: no unjustified skip/xfail/type-ignore/noqa/coverage-ignore
run: python scripts/ci_quality_gates.py test-integrity

dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: no new dependency without justification
run: |
git fetch origin "${GITHUB_BASE_REF:-main}" --depth=1
python scripts/ci_quality_gates.py dependency-review --base "origin/${GITHUB_BASE_REF:-main}"

build-install:
name: Build Install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Build package
run: |
python -m pip install --upgrade pip build
python -m build
- name: Install from scratch and smoke test
run: |
python -m venv /tmp/aethermesh-install-check
/tmp/aethermesh-install-check/bin/python -m pip install --upgrade pip
/tmp/aethermesh-install-check/bin/python -m pip install --force-reinstall dist/*.whl
/tmp/aethermesh-install-check/bin/aethermesh-core --help

python-workflow-security-check:
name: Python - Workflow Security Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: workflow security check passes
run: python scripts/ci_quality_gates.py workflow-security

python-pr-size-check:
name: Python - PR Size Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: PR size stays reviewable
run: |
git fetch origin "${GITHUB_BASE_REF:-main}" --depth=1
python scripts/ci_quality_gates.py pr-size --base "origin/${GITHUB_BASE_REF:-main}" --max-files 80 --max-lines 10000 --max-binary-files 0

python-flaky-test-check:
name: Python - Flaky Test Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install package and test tools
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest
- name: repeated pytest passes
run: |
for seed in 1 2 3; do
echo "Flaky-test pass with PYTHONHASHSEED=${seed}"
PYTHONHASHSEED="${seed}" python -m pytest -q tests
done

python-artifact-provenance-check:
name: Python - Artifact Provenance Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Build artifacts from source
run: |
python -m pip install --upgrade pip build
rm -rf dist build *.egg-info src/*.egg-info
python -m build
- name: Verify artifact provenance metadata
run: python scripts/ci_quality_gates.py artifact-provenance --dist dist
15 changes: 14 additions & 1 deletion graphify-out/.graphify_labels.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"0": "Community 0",
"1": "Community 1",
"2": "Community 2",
"3": "Community 3",
"4": "Community 4",
Expand All @@ -15,5 +16,17 @@
"14": "Community 14",
"15": "Community 15",
"16": "Community 16",
"19": "Community 19"
"17": "Community 17",
"18": "Community 18",
"19": "Community 19",
"20": "Community 20",
"21": "Community 21",
"22": "Community 22",
"23": "Community 23",
"24": "Community 24",
"25": "Community 25",
"26": "Community 26",
"27": "Community 27",
"28": "Community 28",
"29": "Community 29"
}
Loading
Loading