Skip to content

🔒 Security: Bump pytest>=9.0.3, cryptography>=46.0.7 #19

🔒 Security: Bump pytest>=9.0.3, cryptography>=46.0.7

🔒 Security: Bump pytest>=9.0.3, cryptography>=46.0.7 #19

# -*- coding: utf-8 -*-
# ============================================================================ #
# DockerDiscordControl (DDC) - Performance Testing CI/CD Workflow #
# https://ddc.bot #
# Copyright (c) 2025 MAX #
# Licensed under the MIT License #
# ============================================================================ #
#
# This workflow runs performance tests on every push and pull request.
# It includes performance gates that fail the build if thresholds are exceeded.
name: Performance Tests
on:
push:
branches:
- main
- v2.0
- develop
paths:
- '**.py'
- 'tests/performance/**'
- 'pytest.ini'
- 'requirements*.txt'
- '.github/workflows/performance-tests.yml'
pull_request:
branches:
- main
- v2.0
paths:
- '**.py'
- 'tests/performance/**'
- 'pytest.ini'
- 'requirements*.txt'
workflow_dispatch: # Allow manual trigger
inputs:
test_scope:
description: 'Test scope (all, docker, config, mech)'
required: false
default: 'all'
permissions:
contents: write # Checkout code + push performance reports
actions: read # Download artifacts
pull-requests: write # Comment on PRs
jobs:
performance-tests:
name: Performance Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for accurate comparison
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ca-certificates \
curl
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run performance tests - All
if: ${{ github.event.inputs.test_scope == 'all' || github.event.inputs.test_scope == '' }}
run: |
python -m pytest tests/performance/ \
-v \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-save-data \
--benchmark-json=benchmark-results-all.json
- name: Run performance tests - Docker Async Queue
if: ${{ github.event.inputs.test_scope == 'docker' }}
run: |
python -m pytest tests/performance/test_docker_async_queue_performance.py \
-v \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-json=benchmark-results-docker.json
- name: Run performance tests - ConfigService
if: ${{ github.event.inputs.test_scope == 'config' }}
run: |
python -m pytest tests/performance/test_config_service_performance.py \
-v \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-json=benchmark-results-config.json
- name: Run performance tests - MechService
if: ${{ github.event.inputs.test_scope == 'mech' }}
run: |
python -m pytest tests/performance/test_mech_service_performance.py \
-v \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-json=benchmark-results-mech.json
- name: Upload benchmark results
if: always()
uses: actions/upload-artifact@v4
with:
name: benchmark-results-${{ matrix.python-version }}
path: |
benchmark-results-*.json
.benchmarks/**/*
retention-days: 30
- name: Comment PR with performance results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('benchmark-results-all.json', 'utf8'));
let comment = '## Performance Test Results\n\n';
comment += `**Python Version:** ${{ matrix.python-version }}\n\n`;
comment += '### Benchmark Summary\n\n';
comment += '| Test | Mean | StdDev | Min | Max |\n';
comment += '|------|------|--------|-----|-----|\n';
results.benchmarks.forEach(bench => {
const name = bench.name.substring(0, 50);
const mean = (bench.stats.mean * 1000).toFixed(3);
const stddev = (bench.stats.stddev * 1000).toFixed(3);
const min = (bench.stats.min * 1000).toFixed(3);
const max = (bench.stats.max * 1000).toFixed(3);
comment += `| ${name} | ${mean}ms | ${stddev}ms | ${min}ms | ${max}ms |\n`;
});
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
performance-comparison:
name: Performance Comparison (Main vs PR)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout PR code
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run PR performance tests
run: |
python -m pytest tests/performance/ \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-json=benchmark-pr.json
- name: Checkout main branch
uses: actions/checkout@v4
with:
ref: main
- name: Run main branch performance tests
run: |
python -m pytest tests/performance/ \
-m performance \
--benchmark-only \
--benchmark-autosave \
--benchmark-json=benchmark-main.json
- name: Compare performance
run: |
python -m pytest tests/performance/ \
-m performance \
--benchmark-compare=benchmark-main.json \
--benchmark-compare=benchmark-pr.json \
--benchmark-compare-fail=mean:20% # Fail if PR is 20% slower
- name: Upload comparison results
if: always()
uses: actions/upload-artifact@v4
with:
name: performance-comparison
path: |
benchmark-pr.json
benchmark-main.json
retention-days: 30
memory-profiling:
name: Memory Profiling
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-test.txt
pip install memory-profiler
- name: Run memory profiling tests
run: |
# Run ALL performance tests (including non-benchmark tests like memory tests)
# Don't use --benchmark-only so memory tests are included
python -m pytest tests/performance/test_config_service_performance.py::TestConfigServicePerformance::test_memory_usage_with_large_config \
-v \
-m performance
performance-dashboard:
name: Update Performance Dashboard
runs-on: ubuntu-latest
needs: [performance-tests]
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/v2.0'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download benchmark results
uses: actions/download-artifact@v4
with:
name: benchmark-results-3.10
path: benchmarks/
- name: Generate performance report
run: |
echo "## Performance Dashboard" > performance-summary.txt
echo "" >> performance-summary.txt
echo "**Last Updated:** $(date)" >> performance-summary.txt
echo "**Branch:** ${{ github.ref_name }}" >> performance-summary.txt
echo "**Commit:** ${{ github.sha }}" >> performance-summary.txt
echo "" >> performance-summary.txt
echo "### Benchmark Results" >> performance-summary.txt
echo "" >> performance-summary.txt
# Performance reports are available as artifacts, no need to commit
cat performance-summary.txt