diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index f2df5e1..0000000 --- a/.codecov.yml +++ /dev/null @@ -1,26 +0,0 @@ -coverage: - status: - project: - default: - target: 80% - threshold: 5% - patch: - default: - target: 80% - threshold: 5% - -comment: - layout: "reach,diff,flags,tree" - behavior: default - require_changes: false - -ignore: - - "test_*.cpp" - - "builddir/**/*" - - "**/*.hpp" # Header files typically don't need coverage - -flags: - unittests: - paths: - - handler.cpp - - main.cpp diff --git a/.dockerignore b/.dockerignore index 68876ba..12bf808 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,9 @@ builddir/ testbuild/ +# Rust port (separate build, own Dockerfile) +rust/ + # Git .git/ .gitignore diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml new file mode 100644 index 0000000..dd08bf1 --- /dev/null +++ b/.gitea/workflows/docker-build-push.yml @@ -0,0 +1,56 @@ +name: docker-build-push + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + build-push-deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # act_runner bind-mounts the admin host's real Docker socket into every + # job container (Docker-outside-of-Docker, not a nested daemon), so + # `docker` here talks straight to the host's daemon โ€” no separate + # dockerd to start. The Dockerfile's builder stage runs `meson test`, + # so a failing test fails this build before anything gets pushed. + - name: Build, test, and push image + env: + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + SHA="${{ github.sha }}" + IMAGE="gitea.blairhaus.net/pmb/finger" + + docker build -t "$IMAGE:$SHA" -t "$IMAGE:latest" . + printf '%s' "$REGISTRY_TOKEN" | docker login gitea.blairhaus.net -u pmb --password-stdin + docker push "$IMAGE:$SHA" + docker push "$IMAGE:latest" + docker logout gitea.blairhaus.net + + echo "pushed $IMAGE:$SHA and $IMAGE:latest" + + # Deploy: hop into the admin host itself (job containers can only reach + # host.docker.internal directly), then from there reuse admin's own + # already-configured `ssh mammut`/`ssh bsd` aliases to reach the two + # real deploy targets. + - name: Deploy to mammut and bsd + env: + ADMIN_HOST_SSH_KEY: ${{ secrets.ADMIN_HOST_SSH_KEY }} + run: | + mkdir -p ~/.ssh + printf '%s\n' "$ADMIN_HOST_SSH_KEY" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + ssh-keyscan -H host.docker.internal >> ~/.ssh/known_hosts 2>/dev/null + + scp -i ~/.ssh/id_ed25519 update-fingerd.sh pmb@host.docker.internal:/tmp/update-fingerd.sh + + ssh -i ~/.ssh/id_ed25519 pmb@host.docker.internal bash -s <<'EOF' + set -euo pipefail + ssh mammut "cd ~/finger && docker compose pull && docker compose up -d" < /dev/null + ssh bsd 'sh -s' < /tmp/update-fingerd.sh + rm -f /tmp/update-fingerd.sh + EOF + + echo "deployed to mammut + bsd" diff --git a/.github/SETUP.md b/.github/SETUP.md deleted file mode 100644 index 353d9b5..0000000 --- a/.github/SETUP.md +++ /dev/null @@ -1,179 +0,0 @@ -# GitHub Actions CI/CD Setup - -This repository includes a comprehensive GitHub Actions workflow for C++20 compilation, testing, and code coverage reporting. - -## Features - -### ๐Ÿ”ง Multi-Platform Build & Test -- **Ubuntu Latest**: Primary development target with GCC -- **macOS Latest**: Cross-platform compatibility with Clang -- **Windows Latest**: Broader compatibility with GCC via vcpkg - -### ๐Ÿงช Comprehensive Testing -- Runs all Google Test unit tests -- Validates security features (directory traversal protection) -- Fails build on any test failures -- Uploads test logs as artifacts - -### ๐Ÿ“Š Code Coverage Reporting -- **Coverage Tool**: gcov + lcov for detailed coverage analysis -- **Integration**: Automatic upload to Codecov.io -- **Reports**: HTML coverage reports as downloadable artifacts -- **Thresholds**: Configurable coverage targets (default: 80%) -- **PR Comments**: Automatic coverage change reporting - -## Workflow Structure - -``` -CI Workflow -โ”œโ”€โ”€ Build & Test Matrix (Ubuntu, macOS, Windows) -โ”‚ โ”œโ”€โ”€ Install Dependencies (Boost, Google Test) -โ”‚ โ”œโ”€โ”€ Meson Setup & Configure -โ”‚ โ”œโ”€โ”€ Compile with C++20 -โ”‚ โ”œโ”€โ”€ Run Unit Tests -โ”‚ โ””โ”€โ”€ Upload Test Artifacts -โ””โ”€โ”€ Coverage Analysis (Ubuntu only) - โ”œโ”€โ”€ Build with Coverage Flags - โ”œโ”€โ”€ Run Tests with Coverage Collection - โ”œโ”€โ”€ Generate lcov Reports - โ”œโ”€โ”€ Upload to Codecov - โ””โ”€โ”€ Generate HTML Reports -``` - -## Setup Instructions - -### 1. Repository Setup -1. Push this repository to GitHub -2. Update the badge URLs in `README.md`: - ```markdown - [![CI](https://github.com/YOUR_USERNAME/YOUR_REPO_NAME/workflows/CI/badge.svg)](https://github.com/YOUR_USERNAME/YOUR_REPO_NAME/actions) - [![codecov](https://codecov.io/gh/YOUR_USERNAME/YOUR_REPO_NAME/branch/main/graph/badge.svg)](https://codecov.io/gh/YOUR_USERNAME/YOUR_REPO_NAME) - ``` - -### 2. Codecov Integration -1. Visit [codecov.io](https://codecov.io) and sign in with GitHub -2. Add your repository to Codecov -3. No additional setup required - the workflow handles token-free uploads - -### 3. Branch Protection (Optional) -Configure branch protection rules in GitHub: -- Require status checks to pass before merging -- Require branches to be up to date before merging -- Include the "Build and Test" and "Code Coverage" checks - -## Configuration Files - -### `.github/workflows/ci.yml` -Main CI/CD workflow with: -- Multi-platform build matrix -- Dependency management for each OS -- Test execution and artifact collection -- Coverage analysis and reporting - -### `.codecov.yml` -Codecov configuration with: -- Coverage targets (80% project, 80% patch) -- File exclusions (test files, build directories) -- PR comment formatting -- Coverage flags for different components - -### `.gitignore` Updates -Added coverage-related file exclusions: -- `*.gcda`, `*.gcno`, `*.gcov` - Coverage data files -- `coverage/` - Coverage report directories -- `coverage*.info` - lcov report files - -## Workflow Triggers - -The CI workflow runs on: -- **Push** to `main` and `develop` branches -- **Pull Requests** targeting `main` and `develop` branches - -## Artifacts Generated - -### Test Results -- Test logs from all platforms -- Available for 90 days after workflow completion - -### Coverage Reports -- HTML coverage reports (viewable in browser) -- lcov data files for further analysis -- Codecov integration for web-based viewing - -## Coverage Analysis - -The coverage analysis focuses on: -- `handler.cpp` - Core business logic -- Security validation functions -- File I/O operations -- Excludes test files and system headers - -### Coverage Thresholds -- **Project Coverage**: 80% minimum -- **Patch Coverage**: 80% minimum for new code -- **Threshold**: 5% tolerance for coverage changes - -## Troubleshooting - -### Common Issues - -1. **Dependency Installation Failures** - - Check if package names are correct for the target OS - - Verify vcpkg installation on Windows - -2. **Coverage Upload Failures** - - Coverage uploads are set to non-blocking (`fail_ci_if_error: false`) - - Check Codecov repository configuration - -3. **Test Failures** - - Review test logs in the workflow artifacts - - Ensure all tests pass locally before pushing - -### Local Testing - -Test the workflow components locally: - -```bash -# Standard build and test -meson setup builddir -meson compile -C builddir -meson test -C builddir --verbose - -# Coverage build and test -meson setup builddir-coverage -Db_coverage=true -meson compile -C builddir-coverage -meson test -C builddir-coverage -``` - -## Customization - -### Adding New Platforms -Extend the build matrix in `.github/workflows/ci.yml`: -```yaml -matrix: - os: [ubuntu-latest, macos-latest, windows-latest, ubuntu-20.04] -``` - -### Changing Coverage Targets -Modify `.codecov.yml`: -```yaml -coverage: - status: - project: - default: - target: 90% # Increase to 90% -``` - -### Adding Static Analysis -Add steps to the workflow for tools like: -- cppcheck -- clang-tidy -- AddressSanitizer/UBSan (already partially enabled) - -## Security Considerations - -The workflow includes security best practices: -- Pinned action versions (`@v4`, `@v3`) -- No secrets required for basic functionality -- Minimal permissions for workflow execution -- Static linking to reduce runtime dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index fbfd026..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,138 +0,0 @@ -name: CI - -on: - push: - branches: [ main, develop ] - pull_request: - branches: [ main, develop ] - -jobs: - build-and-test: - name: Build and Test - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - include: - - os: ubuntu-latest - cc: gcc - cxx: g++ - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Install Meson and Ninja - run: | - python -m pip install --upgrade pip - pip install meson ninja - - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y libboost-system-dev libgtest-dev libgmock-dev build-essential - - - name: Setup build directory - run: | - meson setup builddir - env: - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - - name: Compile - run: | - meson compile -C builddir - - - name: Run tests - run: | - meson test -C builddir --verbose - - - name: Upload test results - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-results-${{ matrix.os }} - path: builddir/meson-logs/ - - coverage: - name: Code Coverage - runs-on: ubuntu-latest - needs: build-and-test - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Install Meson and Ninja - run: | - python -m pip install --upgrade pip - pip install meson ninja - - - name: Install dependencies and coverage tools - run: | - sudo apt-get update - sudo apt-get install -y libboost-system-dev libgtest-dev libgmock-dev build-essential lcov - - - name: Setup build directory with coverage - run: | - meson setup builddir -Db_coverage=true - env: - CC: gcc - CXX: g++ - - - name: Compile with coverage - run: | - meson compile -C builddir - - - name: Run tests with coverage - run: | - meson test -C builddir --verbose - - - name: Generate coverage report - run: | - # Create coverage directory - mkdir -p coverage - - # Capture coverage data - lcov --capture --directory builddir --output-file coverage/coverage.info --ignore-errors mismatch,mismatch,unused - - # Remove system headers and test files from coverage - lcov --remove coverage/coverage.info '/usr/*' '*/test_*' '*/gtest/*' --output-file coverage/coverage_filtered.info --ignore-errors mismatch,mismatch,unused - - # Generate HTML report - genhtml coverage/coverage_filtered.info --output-directory coverage/html - - # Display coverage summary - lcov --summary coverage/coverage_filtered.info --ignore-errors mismatch,mismatch,unused - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 - with: - file: coverage/coverage_filtered.info - flags: unittests - name: codecov-umbrella - fail_ci_if_error: false - - - name: Upload coverage HTML report - uses: actions/upload-artifact@v4 - with: - name: coverage-report - path: coverage/html/ - - - name: Coverage Summary - run: | - echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY - echo "Coverage data has been uploaded to Codecov and HTML report is available as an artifact." >> $GITHUB_STEP_SUMMARY - lcov --summary coverage/coverage_filtered.info >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index 8925608..0000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Build and Publish Docker Image - -on: - push: - branches: [ "main" ] - tags: [ 'v*.*.*' ] - pull_request: - branches: [ "main" ] - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build-and-test: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential \ - meson \ - ninja-build \ - pkg-config \ - libboost-all-dev \ - libgtest-dev \ - libgmock-dev - - - name: Setup build directory - run: meson setup builddir --buildtype=release - - - name: Build project - run: meson compile -C builddir - - - name: Run tests - run: meson test -C builddir - - - name: Upload test results - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-results - path: builddir/meson-logs/testlog.txt - - build-and-push-image: - runs-on: ubuntu-latest - needs: build-and-test - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha,prefix={{branch}}- - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Generate artifact attestation - if: github.event_name != 'pull_request' - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - subject-digest: ${{ steps.build.outputs.digest }} - push-to-registry: true - - security-scan: - runs-on: ubuntu-latest - needs: build-and-push-image - if: github.event_name != 'pull_request' - permissions: - contents: read - security-events: write - - steps: - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - format: 'sarif' - output: 'trivy-results.sarif' - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' diff --git a/README.md b/README.md index f90f164..e57046a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # finger -[![CI](https://github.com/waffle2k/finger/workflows/CI/badge.svg)](https://github.com/waffle2k/finger/actions) -[![codecov](https://codecov.io/gh/waffle2k/finger/branch/main/graph/badge.svg)](https://codecov.io/gh/waffle2k/finger) - A silly finger service written in c++20 # Compiling: