From f9b72d20d2ab0aec5ec94764383ca8a632a98298 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Thu, 19 Mar 2026 01:07:19 +0100 Subject: [PATCH] Add Forgejo CI workflow with lint, PHPStan, tests, and coverage --- .forgejo/workflows/ci.yml | 113 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 .forgejo/workflows/ci.yml diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..80bd8e4 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,113 @@ +name: CI + +on: + push: + branches: ['release/*'] + pull_request: + branches: [main] + +jobs: + ci: + runs-on: docker + container: + image: catthehacker/ubuntu:act-latest + steps: + - uses: https://data.forgejo.org/actions/checkout@v4 + + - name: Set up PHP + uses: https://github.com/shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: pdo_sqlite, mbstring, xml, dom + coverage: pcov + + - name: Cache Composer dependencies + uses: https://data.forgejo.org/actions/cache@v4 + with: + path: ~/.composer/cache + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Prepare environment + run: cp .env.testing .env + + - name: Lint + run: vendor/bin/pint --test + + - name: Static analysis + run: vendor/bin/phpstan analyse --memory-limit=512M + + - name: Tests + run: php artisan test --coverage-clover coverage.xml --coverage-text + + - name: Parse coverage + if: github.event_name == 'pull_request' + id: coverage + run: | + COVERAGE=$(php -r ' + $xml = simplexml_load_file("coverage.xml"); + if ($xml === false || !isset($xml->project->metrics)) { + echo "0"; + exit; + } + $metrics = $xml->project->metrics; + $statements = (int) $metrics["statements"]; + $covered = (int) $metrics["coveredstatements"]; + echo $statements > 0 ? round(($covered / $statements) * 100, 2) : 0; + ') + echo "percentage=$COVERAGE" >> "$GITHUB_OUTPUT" + + - name: Comment coverage on PR + if: github.event_name == 'pull_request' + env: + FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + COVERAGE: ${{ steps.coverage.outputs.percentage }} + REPO: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + COMMIT_SHA: ${{ github.sha }} + run: | + API_URL="${SERVER_URL}/api/v1/repos/${REPO}/issues/${PR_NUMBER}/comments" + MARKER="" + + BODY="${MARKER} + ## Code Coverage Report + + | Metric | Value | + |--------|-------| + | **Line Coverage** | ${COVERAGE}% | + + _Updated by CI — commit ${COMMIT_SHA}_" + + # Find existing coverage comment + EXISTING=$(curl -sf -H "Authorization: token ${FORGEJO_TOKEN}" \ + "${API_URL}?limit=50" | \ + php -r ' + $comments = json_decode(file_get_contents("php://stdin"), true); + if (!is_array($comments)) exit; + foreach ($comments as $c) { + if (str_contains($c["body"], "")) { + echo $c["id"]; + exit; + } + } + ' || true) + + if [ -n "$EXISTING" ]; then + # Update existing comment + curl -sf -X PATCH \ + -H "Authorization: token ${FORGEJO_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$(php -r 'echo json_encode(["body" => $argv[1]]);' "$BODY")" \ + "${SERVER_URL}/api/v1/repos/${REPO}/issues/comments/${EXISTING}" > /dev/null + else + # Create new comment + curl -sf -X POST \ + -H "Authorization: token ${FORGEJO_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$(php -r 'echo json_encode(["body" => $argv[1]]);' "$BODY")" \ + "${API_URL}" > /dev/null + fi