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
38 changes: 38 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
changelog:
exclude:
labels:
- skip-changelog
- release
categories:
- title: Features
labels:
- feature
- enhancement
- feat
- title: Fixes
labels:
- bug
- bugfix
- fix
- title: Documentation
labels:
- documentation
- docs
- title: Tests
labels:
- test
- tests
- title: CI
labels:
- ci
- github-actions
- title: Refactoring
labels:
- refactor
- title: Dependencies
labels:
- dependencies
- deps
- title: Other Changes
labels:
- "*"
18 changes: 18 additions & 0 deletions .github/workflows/ci-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: "CI PR"

on:
pull_request:
branches: [master]

jobs:
lint:
name: "Lint"
uses: ./.github/workflows/lint.yml

tests:
name: "Tests"
uses: ./.github/workflows/tests.yml

version-check:
name: "Version Check"
uses: ./.github/workflows/version-check.yml
74 changes: 74 additions & 0 deletions .github/workflows/ci-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: "CI Push"

on:
push:
branches: [master]

permissions:
contents: write

jobs:
lint:
name: "Lint"
uses: ./.github/workflows/lint.yml

tests:
name: "Tests"
uses: ./.github/workflows/tests.yml

version-check:
name: "Version Check"
uses: ./.github/workflows/version-check.yml

release:
name: "Release"
needs: [tests, version-check]
runs-on: ubuntu-latest
env:
VUH_VERSION: "v2.13.0"

steps:
- name: "Checkout"
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: "Download version-update-helper"
shell: bash
run: |
curl -fsSL "https://raw.githubusercontent.com/Greewil/version-update-helper/${VUH_VERSION}/vuh.sh" -o vuh.sh
chmod +x vuh.sh

- name: "Set release tag from vuh version"
id: version
shell: bash
run: |
version="$(./vuh.sh lv -q)"
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "tag=v${version}" >> "$GITHUB_OUTPUT"

- name: "Check if tag already exists"
id: tag
shell: bash
run: |
if git rev-parse -q --verify "refs/tags/${{ steps.version.outputs.tag }}" >/dev/null; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: "Release decision"
run: |
if [ "${{ steps.tag.outputs.exists }}" = "true" ]; then
echo "Decision: skip (tag already exists: ${{ steps.version.outputs.tag }})"
else
echo "Decision: create release ${{ steps.version.outputs.tag }}"
fi

- name: "Create GitHub release"
if: steps.tag.outputs.exists == 'false'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
target_commitish: ${{ github.sha }}
generate_release_notes: true
31 changes: 31 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "CodeQL"

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: "0 3 * * 1" # At 03:00 on Monday

permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
name: "Analyze (Python)"
runs-on: ubuntu-latest

steps:
- name: "Checkout"
uses: actions/checkout@v4

- name: "Initialize CodeQL"
uses: github/codeql-action/init@v4
with:
languages: python

- name: "Perform CodeQL Analysis"
uses: github/codeql-action/analyze@v4
21 changes: 21 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: "Lint"

on:
workflow_call:

jobs:
pre-commit:
name: "Pre-commit"
runs-on: ubuntu-latest

steps:
- name: "Checkout"
uses: actions/checkout@v4

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: "Run pre-commit"
uses: pre-commit/action@v3.0.1
203 changes: 203 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
name: "Tests"

on:
workflow_call:

jobs:
unit:
name: "Unit | Py${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
python-version: '3.7'
- os: ubuntu-22.04
python-version: '3.8'
- os: ubuntu-22.04
python-version: '3.9'
- os: ubuntu-22.04
python-version: '3.10'
- os: ubuntu-22.04
python-version: '3.11'
- os: ubuntu-22.04
python-version: '3.12'
- os: ubuntu-22.04
python-version: '3.13'
- os: ubuntu-22.04
python-version: '3.14'
- os: macos-latest
python-version: '3.13'
- os: windows-latest
python-version: '3.13'

steps:
- name: "Checkout"
uses: actions/checkout@v4

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: |
pyproject.toml
uv.lock

- name: "Install unit test dependencies"
run: python -m pip install --upgrade pip pytest pytest-cov httpx requests pyyaml

- name: "Run unit tests with coverage"
env:
COVERAGE_FILE: coverage-unit.dat
run: >
pytest -q tests/test_mellophone.py tests/test_structures.py
--cov=src/mellophone
--cov-report=

- name: "Upload unit coverage data"
if: matrix.os == 'ubuntu-22.04' && matrix.python-version == '3.13'
uses: actions/upload-artifact@v4
with:
name: coverage-unit-data
path: coverage-unit.dat

integration:
name: "Integration | Py3.13 on ubuntu-22.04"
runs-on: ubuntu-22.04

steps:
- name: "Checkout"
uses: actions/checkout@v4

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: '3.13'
cache: pip
cache-dependency-path: |
pyproject.toml
uv.lock

- name: "Install integration test dependencies"
run: python -m pip install --upgrade pip pytest pytest-cov httpx requests pyyaml

- name: "Cache Docker images"
id: docker-cache
uses: actions/cache@v4
with:
path: /tmp/docker-image-cache
key: docker-images-${{ runner.os }}-${{ hashFiles('docker-compose.yml') }}

- name: "Load cached Docker images"
if: steps.docker-cache.outputs.cache-hit == 'true'
shell: bash
run: |
[ -f /tmp/docker-image-cache/mellophone.tar ] && docker load -i /tmp/docker-image-cache/mellophone.tar || true
[ -f /tmp/docker-image-cache/postgres.tar ] && docker load -i /tmp/docker-image-cache/postgres.tar || true

- name: "Pull Docker images"
if: steps.docker-cache.outputs.cache-hit != 'true'
shell: bash
run: |
docker pull curs/mellophone2:1.6.1
docker pull postgres:16.3-alpine

- name: "Save Docker images to cache"
if: steps.docker-cache.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p /tmp/docker-image-cache
docker save curs/mellophone2:1.6.1 -o /tmp/docker-image-cache/mellophone.tar
docker save postgres:16.3-alpine -o /tmp/docker-image-cache/postgres.tar

- name: "Start DB and Mellophone"
run: docker compose up -d db mellophone

- name: "Wait for Mellophone"
shell: bash
run: |
for i in {1..20}; do
if curl -fsS "http://localhost:8082/mellophone/authentication.gif?sesid=ci-smoke" >/dev/null; then
echo "Mellophone is reachable"
exit 0
fi
sleep 2
done
docker compose logs
exit 1

- name: "Run integration tests with coverage"
env:
COVERAGE_FILE: coverage-integration.dat
run: >
pytest -q tests/test_integration_mellophone.py
--cov=src/mellophone
--cov-report=

- name: "Upload integration coverage data"
uses: actions/upload-artifact@v4
with:
name: coverage-integration-data
path: coverage-integration.dat

- name: "Stop services"
if: always()
run: docker compose down -v

coverage-report:
name: "Coverage Report"
needs: [unit, integration]
runs-on: ubuntu-22.04

steps:
- name: "Checkout"
uses: actions/checkout@v4

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: '3.13'

- name: "Download unit coverage data"
uses: actions/download-artifact@v4
with:
name: coverage-unit-data
path: coverage_data/unit

- name: "Download integration coverage data"
uses: actions/download-artifact@v4
with:
name: coverage-integration-data
path: coverage_data/integration

- name: "Install coverage tools"
run: python -m pip install --upgrade pip coverage

- name: "Combine and build coverage reports"
run: |
python -m coverage combine coverage_data/unit/coverage-unit.dat coverage_data/integration/coverage-integration.dat
python -m coverage report -m
python -m coverage xml -o coverage.xml
python -m coverage json -o coverage.json

- name: "Add coverage to job summary"
uses: actions/github-script@v7
with:
script: |
const fs = require("fs");
const report = JSON.parse(fs.readFileSync("coverage.json", "utf8"));
const total = report.totals.percent_covered_display;
core.summary
.addHeading("Coverage (unit + integration)", 2)
.addRaw(`- Total: ${total}%`)
.write();

- name: "Upload coverage artifacts"
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: |
coverage.xml
coverage.json
Loading
Loading