mirror of
https://github.com/ZGCA-Forge/Elevator.git
synced 2025-12-17 04:51:03 +00:00
Update ci
This commit is contained in:
352
.github/workflows/ci.yml
vendored
352
.github/workflows/ci.yml
vendored
@@ -1,203 +1,181 @@
|
||||
name: CI
|
||||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
||||
|
||||
name: Python package
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
branches: ["main", "dev"]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
schedule:
|
||||
# Run tests daily at 6 AM UTC
|
||||
- cron: '0 6 * * *'
|
||||
branches: ["main", "dev"]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
python-version: ['3.12']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/setup.py') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Check dependencies
|
||||
run: |
|
||||
python run_all_tests.py --check-deps
|
||||
|
||||
- name: Run linting
|
||||
run: |
|
||||
black --check elevator_saga tests
|
||||
isort --check-only elevator_saga tests
|
||||
|
||||
- name: Run type checking
|
||||
run: |
|
||||
mypy elevator_saga
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: |
|
||||
python -m pytest --cov=elevator_saga --cov-report=xml --cov-report=term-missing
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: false
|
||||
|
||||
test-examples:
|
||||
name: Test examples
|
||||
# Step 1: Code formatting and pre-commit validation (fast failure)
|
||||
code-format:
|
||||
name: Code formatting and pre-commit validation
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Run example tests
|
||||
run: |
|
||||
python run_all_tests.py --type examples
|
||||
|
||||
build:
|
||||
name: Build and check package
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10" # Use minimum version for consistency
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --all-files
|
||||
|
||||
# Step 2: Basic build and test with minimum Python version (3.10)
|
||||
basic-build:
|
||||
name: Basic build (Python 3.10, Ubuntu)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine check-manifest
|
||||
|
||||
- name: Check manifest
|
||||
run: check-manifest
|
||||
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
|
||||
- name: Check package
|
||||
run: twine check dist/*
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
needs: [code-format] # Only run after code formatting passes
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ubuntu-pip-3.10-${{ hashFiles('**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
ubuntu-pip-3.10-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pytest
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest -v
|
||||
|
||||
# Step 3: Security scan
|
||||
security:
|
||||
name: Security scan
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install security tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install bandit safety
|
||||
|
||||
- name: Run bandit security scan
|
||||
run: bandit -r elevator_saga/ -f json -o bandit-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run safety security scan
|
||||
run: safety check --json --output safety-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload security reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: security-reports
|
||||
path: |
|
||||
bandit-report.json
|
||||
safety-report.json
|
||||
if: always()
|
||||
needs: [basic-build] # Run in parallel with other tests after basic build
|
||||
|
||||
docs:
|
||||
name: Build documentation
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev][docs]
|
||||
|
||||
# 为将来的文档构建预留
|
||||
- name: Check documentation
|
||||
run: |
|
||||
echo "Documentation build placeholder"
|
||||
# sphinx-build -b html docs docs/_build/html
|
||||
|
||||
performance:
|
||||
name: Performance benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev]
|
||||
pip install pytest-benchmark
|
||||
|
||||
# 为将来的性能测试预留
|
||||
- name: Run benchmarks
|
||||
run: |
|
||||
echo "Performance benchmarks placeholder"
|
||||
# python -m pytest tests/benchmarks/ --benchmark-json=benchmark.json
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Run Safety CLI to check for vulnerabilities
|
||||
uses: pyupio/safety-action@v1
|
||||
with:
|
||||
api-key: ${{ secrets.SAFETY_CHECK }}
|
||||
output-format: json
|
||||
args: --detailed-output --output-format json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload security reports
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: security-reports
|
||||
path: |
|
||||
safety-report.json
|
||||
if: always()
|
||||
|
||||
# Step 4: Package build check
|
||||
package-build:
|
||||
name: Package build check
|
||||
runs-on: ubuntu-latest
|
||||
needs: [basic-build] # Run in parallel with other checks
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10" # Use minimum version for consistency
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine
|
||||
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
|
||||
- name: Check package
|
||||
run: twine check dist/*
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
|
||||
# Step 5: Full matrix build (only after all basic checks pass)
|
||||
full-matrix-build:
|
||||
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [security, package-build] # Wait for all prerequisite checks
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
||||
exclude:
|
||||
# Skip the combination we already tested in basic-build
|
||||
- os: ubuntu-latest
|
||||
python-version: "3.10"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}-
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install flake8 pytest
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings
|
||||
flake8 . --count --exit-zero --max-line-length=200 --extend-ignore=E203,W503,F401,E402,E721,F841 --statistics
|
||||
|
||||
- name: Type checking with mypy
|
||||
run: |
|
||||
mypy elevator_saga --disable-error-code=unused-ignore
|
||||
continue-on-error: true
|
||||
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest
|
||||
|
||||
269
.github/workflows/code-quality.yml
vendored
269
.github/workflows/code-quality.yml
vendored
@@ -1,269 +0,0 @@
|
||||
name: Code Quality
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
schedule:
|
||||
# Run weekly code quality checks
|
||||
- cron: '0 2 * * 1'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Linting and formatting
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-lint-${{ hashFiles('**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-lint-
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
pip install flake8 pylint
|
||||
|
||||
- name: Run Black formatting check
|
||||
run: |
|
||||
black --check --diff elevator_saga tests
|
||||
|
||||
- name: Run isort import sorting check
|
||||
run: |
|
||||
isort --check-only --diff elevator_saga tests
|
||||
|
||||
- name: Run flake8
|
||||
run: |
|
||||
flake8 elevator_saga tests --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
flake8 elevator_saga tests --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
|
||||
|
||||
- name: Run pylint
|
||||
run: |
|
||||
pylint elevator_saga --exit-zero --output-format=parseable --reports=no | tee pylint-report.txt
|
||||
|
||||
- name: Upload lint reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: lint-reports
|
||||
path: |
|
||||
pylint-report.txt
|
||||
if: always()
|
||||
|
||||
type-check:
|
||||
name: Type checking
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
|
||||
- name: Run mypy type checking
|
||||
run: |
|
||||
mypy elevator_saga --html-report mypy-report --txt-report mypy-report
|
||||
|
||||
- name: Upload type check reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: type-check-reports
|
||||
path: mypy-report/
|
||||
if: always()
|
||||
|
||||
complexity:
|
||||
name: Code complexity analysis
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install radon xenon
|
||||
|
||||
- name: Run cyclomatic complexity check
|
||||
run: |
|
||||
radon cc elevator_saga --min B --total-average
|
||||
|
||||
- name: Run maintainability index
|
||||
run: |
|
||||
radon mi elevator_saga --min B
|
||||
|
||||
- name: Run complexity with xenon
|
||||
run: |
|
||||
xenon --max-absolute B --max-modules B --max-average A elevator_saga
|
||||
continue-on-error: true
|
||||
|
||||
dependencies:
|
||||
name: Dependency analysis
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
pip install pip-audit pipdeptree
|
||||
|
||||
- name: Generate dependency tree
|
||||
run: |
|
||||
pipdeptree --freeze > requirements-freeze.txt
|
||||
pipdeptree --graph-output png > dependency-graph.png
|
||||
|
||||
- name: Check for known vulnerabilities
|
||||
run: |
|
||||
pip-audit --format=json --output=vulnerability-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload dependency reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dependency-reports
|
||||
path: |
|
||||
requirements-freeze.txt
|
||||
dependency-graph.png
|
||||
vulnerability-report.json
|
||||
if: always()
|
||||
|
||||
documentation:
|
||||
name: Documentation quality
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
pip install pydocstyle interrogate
|
||||
|
||||
- name: Check docstring style
|
||||
run: |
|
||||
pydocstyle elevator_saga --count --explain --source
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check docstring coverage
|
||||
run: |
|
||||
interrogate elevator_saga --ignore-init-method --ignore-magic --ignore-module --ignore-nested-functions --fail-under=70
|
||||
continue-on-error: true
|
||||
|
||||
pre-commit:
|
||||
name: Pre-commit hooks
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install pre-commit
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pre-commit
|
||||
|
||||
- name: Cache pre-commit
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
run: |
|
||||
pre-commit run --all-files --show-diff-on-failure
|
||||
continue-on-error: true
|
||||
|
||||
summary:
|
||||
name: Quality summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, type-check, complexity, dependencies, documentation, pre-commit]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Create quality report
|
||||
run: |
|
||||
echo "## 📊 Code Quality Report" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Format results
|
||||
if [ "${{ needs.lint.result }}" = "success" ]; then
|
||||
echo "| Linting | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Linting | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.type-check.result }}" = "success" ]; then
|
||||
echo "| Type Check | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Type Check | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.complexity.result }}" = "success" ]; then
|
||||
echo "| Complexity | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Complexity | ⚠️ Warning |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.dependencies.result }}" = "success" ]; then
|
||||
echo "| Dependencies | ✅ Secure |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Dependencies | ⚠️ Check needed |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.documentation.result }}" = "success" ]; then
|
||||
echo "| Documentation | ✅ Good |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Documentation | ⚠️ Needs improvement |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.pre-commit.result }}" = "success" ]; then
|
||||
echo "| Pre-commit | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| Pre-commit | ⚠️ Some hooks failed |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "📈 **Overall Quality:** ${{ needs.lint.result == 'success' && needs.type-check.result == 'success' && 'Good' || 'Needs attention' }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
34
.github/workflows/dependabot.yml
vendored
34
.github/workflows/dependabot.yml
vendored
@@ -1,34 +0,0 @@
|
||||
name: Dependabot Auto-merge
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
dependabot:
|
||||
name: Auto-merge Dependabot PRs
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
|
||||
steps:
|
||||
- name: Dependabot metadata
|
||||
id: metadata
|
||||
uses: dependabot/fetch-metadata@v1
|
||||
with:
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: Enable auto-merge for Dependabot PRs
|
||||
if: steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor'
|
||||
run: gh pr merge --auto --merge "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment on major version updates
|
||||
if: steps.metadata.outputs.update-type == 'version-update:semver-major'
|
||||
run: |
|
||||
gh pr comment "$PR_URL" --body "🚨 **Major version update detected!** Please review this PR carefully before merging."
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
87
.github/workflows/docs.yml
vendored
Normal file
87
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: Build and Deploy Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: "要部署文档的分支"
|
||||
required: false
|
||||
default: "main"
|
||||
type: string
|
||||
deploy_to_pages:
|
||||
description: "是否部署到 GitHub Pages"
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
# Build documentation
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch || github.ref }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
# Install package in development mode to get version info
|
||||
pip install -e .
|
||||
# Install documentation dependencies
|
||||
pip install -e .[docs]
|
||||
|
||||
- name: Setup Pages
|
||||
id: pages
|
||||
uses: actions/configure-pages@v5
|
||||
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||
|
||||
- name: Build Sphinx documentation
|
||||
run: |
|
||||
# Create docs directory if it doesn't exist
|
||||
mkdir -p docs
|
||||
# Placeholder for Sphinx build
|
||||
echo "Documentation build placeholder - configure Sphinx in docs/"
|
||||
# cd docs
|
||||
# make html
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||
with:
|
||||
path: docs/_build/html
|
||||
|
||||
# Deploy to GitHub Pages
|
||||
deploy:
|
||||
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_pages == 'true')
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
389
.github/workflows/publish.yml
vendored
389
.github/workflows/publish.yml
vendored
@@ -1,189 +1,258 @@
|
||||
name: Publish to PyPI
|
||||
# This workflow will upload a Python Package to PyPI when a release is created
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Upload PyPI package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
types: [published, edited]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_pypi:
|
||||
description: 'Publish to Test PyPI instead of PyPI'
|
||||
description: "Publish to Test PyPI instead of PyPI"
|
||||
required: false
|
||||
default: 'false'
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Run tests before publish
|
||||
# Step 1: Code formatting and pre-commit validation (fast failure)
|
||||
code-format:
|
||||
name: Code formatting and pre-commit validation
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
# - name: Install dependencies
|
||||
# run: |
|
||||
# python -m pip install --upgrade pip
|
||||
# pip install -e .
|
||||
|
||||
# - name: Run comprehensive tests
|
||||
# run: |
|
||||
# python -m pytest --cov=msgcenterpy --cov-fail-under=80
|
||||
|
||||
# - name: Run linting
|
||||
# run: |
|
||||
# black --check msgcenterpy tests
|
||||
# isort --check-only msgcenterpy tests
|
||||
# mypy msgcenterpy
|
||||
|
||||
build:
|
||||
name: Build package
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10" # Use minimum version for consistency
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --all-files
|
||||
|
||||
# Step 2: Basic build and test with minimum Python version (3.10)
|
||||
basic-build:
|
||||
name: Basic build (Python 3.10, Ubuntu)
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
# - name: Install build dependencies
|
||||
# run: |
|
||||
# python -m pip install --upgrade pip
|
||||
# pip install build twine check-manifest
|
||||
|
||||
# - name: Verify version consistency
|
||||
# run: |
|
||||
# # 检查版本号一致性
|
||||
# VERSION=$(python -c "import elevator_saga; print(elevator_saga.__version__)" 2>/dev/null || echo "unknown")
|
||||
# TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
# if [ "$GITHUB_EVENT_NAME" = "release" ]; then
|
||||
# if [ "$VERSION" != "$TAG_VERSION" ]; then
|
||||
# echo "Version mismatch: package=$VERSION, tag=$TAG_VERSION"
|
||||
# exit 1
|
||||
# fi
|
||||
# fi
|
||||
|
||||
# - name: Check manifest
|
||||
# run: check-manifest
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine check-manifest
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
# - name: Check package
|
||||
# run: |
|
||||
# twine check dist/*
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-${{ github.run_number }}
|
||||
path: dist/
|
||||
retention-days: 30
|
||||
needs: [code-format] # Only run after code formatting passes
|
||||
|
||||
publish-test:
|
||||
name: Publish to Test PyPI
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ubuntu-pip-3.10-${{ hashFiles('**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
ubuntu-pip-3.10-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pytest
|
||||
pip install -e .[dev]
|
||||
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest -v
|
||||
|
||||
# Step 3: Security scan
|
||||
security:
|
||||
name: Security scan
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.event.inputs.test_pypi == 'true' || (github.event_name == 'release' && github.event.release.prerelease)
|
||||
environment:
|
||||
name: test-pypi
|
||||
url: https://test.pypi.org/p/elevator-saga
|
||||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist-${{ github.run_number }}
|
||||
path: dist/
|
||||
|
||||
- name: Publish to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
||||
verbose: true
|
||||
needs: [basic-build] # Run in parallel with other tests after basic build
|
||||
|
||||
publish-pypi:
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Run Safety CLI to check for vulnerabilities
|
||||
uses: pyupio/safety-action@v1
|
||||
with:
|
||||
api-key: ${{ secrets.SAFETY_CHECK }}
|
||||
output-format: json
|
||||
args: --detailed-output --output-format json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload security reports
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: security-reports
|
||||
path: |
|
||||
safety-report.json
|
||||
if: always()
|
||||
|
||||
release-build:
|
||||
name: Build release distributions
|
||||
runs-on: ubuntu-latest
|
||||
needs: [basic-build]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10" # Use minimum version for consistency
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install build twine
|
||||
|
||||
- name: Verify version consistency
|
||||
if: github.event_name == 'release' && (github.event.action == 'published' || (github.event.action == 'edited' && !github.event.release.prerelease))
|
||||
run: |
|
||||
# Install package first
|
||||
pip install -e .
|
||||
|
||||
# Get package version (fail fast if not available)
|
||||
VERSION=$(python -c "import elevator_saga; print(elevator_saga.__version__)")
|
||||
|
||||
# Handle both v0.0.3 and 0.0.3 tag formats
|
||||
RAW_TAG="${GITHUB_REF#refs/tags/}"
|
||||
if [[ "$RAW_TAG" == v* ]]; then
|
||||
TAG_VERSION="${RAW_TAG#v}"
|
||||
else
|
||||
TAG_VERSION="$RAW_TAG"
|
||||
fi
|
||||
|
||||
echo "Package version: $VERSION"
|
||||
echo "Tag version: $TAG_VERSION"
|
||||
|
||||
if [ "$VERSION" != "$TAG_VERSION" ]; then
|
||||
echo "❌ Version mismatch: package=$VERSION, tag=$TAG_VERSION"
|
||||
echo "Please ensure the package version matches the git tag"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Version verification passed: $VERSION"
|
||||
|
||||
- name: Build release distributions
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Check package
|
||||
run: |
|
||||
twine check dist/*
|
||||
|
||||
- name: Upload distributions
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-dists
|
||||
path: dist/
|
||||
|
||||
pypi-publish:
|
||||
name: Publish to PyPI
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.event_name == 'release' && !github.event.release.prerelease && github.event.inputs.test_pypi != 'true'
|
||||
environment:
|
||||
name: pypi
|
||||
url: https://pypi.org/p/elevator-saga
|
||||
|
||||
needs:
|
||||
- release-build
|
||||
if: github.event_name == 'release' && !github.event.release.prerelease && github.event.inputs.test_pypi != 'true' && (github.event.action == 'published' || github.event.action == 'edited')
|
||||
permissions:
|
||||
# IMPORTANT: this permission is mandatory for trusted publishing
|
||||
id-token: write
|
||||
|
||||
# Note: For enhanced security, consider configuring deployment environments
|
||||
# in your GitHub repository settings with protection rules
|
||||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist-${{ github.run_number }}
|
||||
path: dist/
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
verbose: true
|
||||
- name: Retrieve release distributions
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: release-dists
|
||||
path: dist/
|
||||
|
||||
- name: Publish release distributions to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
||||
test-pypi-publish:
|
||||
name: Publish to Test PyPI
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- release-build
|
||||
if: github.event.inputs.test_pypi == 'true' || (github.event_name == 'release' && github.event.release.prerelease && (github.event.action == 'published' || github.event.action == 'edited'))
|
||||
permissions:
|
||||
# IMPORTANT: this permission is mandatory for trusted publishing
|
||||
id-token: write
|
||||
|
||||
# Note: For enhanced security, consider configuring deployment environments
|
||||
# in your GitHub repository settings with protection rules
|
||||
|
||||
steps:
|
||||
- name: Retrieve release distributions
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: release-dists
|
||||
path: dist/
|
||||
|
||||
- name: Publish release distributions to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
|
||||
create-github-release-assets:
|
||||
name: Add assets to GitHub release
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.event_name == 'release'
|
||||
|
||||
needs: release-build
|
||||
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'edited')
|
||||
permissions:
|
||||
contents: write # Need write access to upload release assets
|
||||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist-${{ github.run_number }}
|
||||
path: dist/
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: dist/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Retrieve release distributions
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: release-dists
|
||||
path: dist/
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: dist/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
post-publish:
|
||||
name: Post-publish tasks
|
||||
runs-on: ubuntu-latest
|
||||
needs: [publish-pypi, publish-test]
|
||||
if: always() && (needs.publish-pypi.result == 'success' || needs.publish-test.result == 'success')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create deployment summary
|
||||
run: |
|
||||
echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Item | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ needs.publish-pypi.result }}" = "success" ]; then
|
||||
echo "| PyPI | ✅ Published |" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.publish-test.result }}" = "success" ]; then
|
||||
echo "| Test PyPI | ✅ Published |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "| GitHub Release | ✅ Assets uploaded |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Version | ${{ github.event.release.tag_name || 'test' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# 为将来的通知预留
|
||||
- name: Notify team
|
||||
run: |
|
||||
echo "Package published successfully!"
|
||||
# 可以添加 Slack、Discord 等通知
|
||||
needs: [pypi-publish, test-pypi-publish]
|
||||
if: always() && (needs.pypi-publish.result == 'success' || needs.test-pypi-publish.result == 'success')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Create deployment summary
|
||||
run: |
|
||||
echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Item | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ needs.pypi-publish.result }}" = "success" ]; then
|
||||
echo "| PyPI | Published |" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.test-pypi-publish.result }}" = "success" ]; then
|
||||
echo "| Test PyPI | Published |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "| GitHub Release | Assets uploaded |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Version | ${{ github.event.release.tag_name || 'test' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
Reference in New Issue
Block a user