diff --git a/.github/scripts/renovate-changelog.sh b/.github/scripts/renovate-changelog.sh deleted file mode 100755 index 5f4ab6d..0000000 --- a/.github/scripts/renovate-changelog.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -# Called by Renovate postUpgradeTasks. Appends a single bullet under the -# `## [Unreleased]` section of CHANGELOG.md so the auto-release workflow has -# content to promote into a tagged release after the Renovate PR merges to main. -set -euo pipefail - -BRANCH="${1:-renovate/unknown}" -TITLE="${2:-Update dependencies}" - -# Skip if CHANGELOG.md was already touched this run (grouped PRs fire the hook -# more than once; we only want one bullet per PR). -if git diff --cached --name-only | grep -qx CHANGELOG.md; then - exit 0 -fi -if git diff --name-only | grep -qx CHANGELOG.md; then - exit 0 -fi - -ENTRY="- Renovate: ${TITLE} (\`${BRANCH}\`)" - -python3 - "$ENTRY" <<'PY' -import re, sys, pathlib -entry = sys.argv[1] -p = pathlib.Path("CHANGELOG.md") -text = p.read_text(encoding="utf-8") - -pattern = re.compile(r"(## \[Unreleased\]\n)(.*?)(\n## \[)", re.DOTALL) -m = pattern.search(text) -if not m: - # No [Unreleased] section yet — insert one after the intro paragraph - # (the first blank line after the H1 header). - head, _, rest = text.partition("\n\n") - text = f"{head}\n\n## [Unreleased]\n\n{entry}\n\n{rest}" -else: - body = m.group(2).rstrip("\n") - sep = "\n" if body else "" - text = pattern.sub( - lambda _m: f"{_m.group(1)}{body}{sep}{entry}\n{_m.group(3)}", - text, count=1, - ) - -p.write_text(text, encoding="utf-8") -PY diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml deleted file mode 100644 index 59c472b..0000000 --- a/.github/workflows/auto-release.yaml +++ /dev/null @@ -1,117 +0,0 @@ -# After a Renovate PR merges into `main`, promote the `[Unreleased]` section -# of CHANGELOG.md to the next patch version, commit, tag, push, and back-merge -# main into develop so the branches stay in sync. -# -# Required secrets: -# RELEASE_TOKEN PAT or GitHub App token with contents:write + workflows. -# Needed for the tag push to trigger github_build_release.yml -# (the default GITHUB_TOKEN cannot trigger other workflows) -# and for the back-merge push to `develop`. -# -# Gating: the existing pr.yaml is required by branch protection, so by the time -# a PR is merged into main, CI has already passed. We do not re-wait for checks -# on the merge commit (it has no associated check runs after a squash-merge). - -name: Auto Release on Renovate Merge - -on: - pull_request: - types: [closed] - branches: [main] - -permissions: - contents: read - -jobs: - release: - if: >- - github.event.pull_request.merged == true && - github.event.pull_request.user.login == 'renovate[bot]' - runs-on: ubuntu-latest - steps: - - name: Checkout main with full history - uses: actions/checkout@v6 - with: - ref: main - fetch-depth: 0 - token: ${{ secrets.RELEASE_TOKEN }} - - - name: Compute next patch version - id: version - run: | - latest=$(git tag -l '[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -1) - : "${latest:=0.0.0}" - IFS=. read -r maj min pat <<<"$latest" - next="${maj}.${min}.$((pat + 1))" - { - echo "current=$latest" - echo "next=$next" - echo "date=$(date -u +%Y-%m-%d)" - } >>"$GITHUB_OUTPUT" - echo "Will release: $latest -> $next" - - - name: Bail if [Unreleased] is empty - id: gate - run: | - body=$(awk '/^## \[Unreleased\]/{f=1;next} /^## \[/{f=0} f' CHANGELOG.md \ - | grep -v '^[[:space:]]*$' || true) - if [ -z "$body" ]; then - echo "Nothing under [Unreleased]; skipping release." - echo "skip=true" >>"$GITHUB_OUTPUT" - else - echo "skip=false" >>"$GITHUB_OUTPUT" - fi - - - name: Promote [Unreleased] -> ${{ steps.version.outputs.next }} - if: steps.gate.outputs.skip != 'true' - env: - VER: ${{ steps.version.outputs.next }} - DATE: ${{ steps.version.outputs.date }} - run: | - python3 - <<'PY' - import os, re, pathlib - ver = os.environ["VER"] - date = os.environ["DATE"] - p = pathlib.Path("CHANGELOG.md") - text = p.read_text(encoding="utf-8") - text = re.sub( - r"## \[Unreleased\]\n", - f"## [Unreleased]\n\n## [{ver}] - {date}\n", - text, count=1, - ) - p.write_text(text, encoding="utf-8") - PY - - - name: Commit on main, tag, push - if: steps.gate.outputs.skip != 'true' - env: - VER: ${{ steps.version.outputs.next }} - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add CHANGELOG.md - git commit -m "release: ${VER}" - git tag -a "${VER}" -m "Release ${VER}" - git push origin main - git push origin "${VER}" - - - name: Back-merge main into develop - if: steps.gate.outputs.skip != 'true' - env: - VER: ${{ steps.version.outputs.next }} - GH_TOKEN: ${{ secrets.RELEASE_TOKEN }} - run: | - git fetch origin develop - git checkout -B develop origin/develop - if git merge --no-ff main -m "chore: back-merge hotfix ${VER} into develop"; then - git push origin develop - echo "Back-merged ${VER} to develop." - else - git merge --abort || true - gh pr create \ - --repo "${GITHUB_REPOSITORY}" \ - --base develop \ - --head main \ - --title "Back-merge hotfix ${VER} into develop" \ - --body "Automated back-merge from \`main\` conflicted with \`develop\`. Resolve and merge to keep branches in sync after release ${VER}." - fi diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index bd9a238..5b24bf2 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -37,15 +37,13 @@ jobs: docker compose exec -e XDEBUG_MODE=coverage phpfpm bin/console --env=test doctrine:migrations:migrate --no-interaction --quiet docker compose exec -e XDEBUG_MODE=coverage phpfpm vendor/bin/phpunit --coverage-clover=coverage/unit.xml - # Codecov upload disabled on the fork — no CODECOV_TOKEN secret. - # Re-enable when promoting to upstream. - # - name: Upload coverage to Codecov - # uses: codecov/codecov-action@v5 - # with: - # token: ${{ secrets.CODECOV_TOKEN }} - # files: ./coverage/unit.xml - # fail_ci_if_error: true - # flags: unittests + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage/unit.xml + fail_ci_if_error: true + flags: unittests build-assets: runs-on: ubuntu-latest diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml deleted file mode 100644 index 69a1f1f..0000000 --- a/.github/workflows/renovate.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# Self-hosted Renovate runner. Runs on a schedule and on demand. -# Self-hosted is required because postUpgradeTasks (which writes CHANGELOG.md -# inline with the dep bump) is disabled on the Mend Renovate SaaS app. -# -# Required secrets: -# RENOVATE_TOKEN PAT or GitHub App token with repo write + workflows. -# Pushes by the default GITHUB_TOKEN don't re-trigger Actions, -# so a PAT/App token is needed to make CI re-run on -# Renovate's branch updates. - -name: Renovate - -on: - schedule: - - cron: "0 11 * * 1-5" # weekdays 11:00 UTC = 13:00 Copenhagen (CEST) / 12:00 (CET) - workflow_dispatch: - inputs: - logLevel: - description: Renovate log level - type: choice - default: info - options: [debug, info, warn, error] - dryRun: - description: Dry-run (no PRs) - type: choice - default: "null" - options: ["null", "full"] - -permissions: - contents: read - -concurrency: - group: renovate - cancel-in-progress: false - -jobs: - renovate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - # PHP/Composer are needed so Renovate can resolve composer.lock - # updates inside its container. - - uses: shivammathur/setup-php@v2 - with: - php-version: "8.3" - tools: composer:v2 - coverage: none - - - name: Run Renovate - uses: renovatebot/github-action@v43 - with: - configurationFile: renovate.json - token: ${{ secrets.RENOVATE_TOKEN }} - renovate-version: latest - env: - LOG_LEVEL: ${{ inputs.logLevel || 'info' }} - RENOVATE_DRY_RUN: ${{ inputs.dryRun || 'null' }} - RENOVATE_REPOSITORIES: ${{ github.repository }} - # Allow the changelog script to run from postUpgradeTasks. - RENOVATE_ALLOWED_POST_UPGRADE_COMMANDS: '["^bash \\.github/scripts/renovate-changelog\\.sh"]' - RENOVATE_ALLOW_POST_UPGRADE_COMMAND_TEMPLATING: "true" diff --git a/renovate.json b/renovate.json deleted file mode 100644 index afa00a6..0000000 --- a/renovate.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - ":dependencyDashboard", - ":semanticCommitsDisabled", - ":maintainLockFilesWeekly", - "schedule:weekdays" - ], - "baseBranches": ["main", "develop"], - "timezone": "Europe/Copenhagen", - "labels": ["dependencies", "renovate"], - "prConcurrentLimit": 5, - "prHourlyLimit": 2, - "rangeStrategy": "bump", - "rebaseWhen": "behind-base-branch", - "platformAutomerge": true, - "ignoreUnstable": true, - "respectLatest": true, - - "vulnerabilityAlerts": { - "enabled": true, - "labels": ["security", "dependencies"], - "automerge": true, - "automergeType": "pr", - "minimumReleaseAge": "0 days", - "prPriority": 10, - "commitMessagePrefix": "security:", - "matchBaseBranches": ["main"] - }, - "osvVulnerabilityAlerts": true, - - "lockFileMaintenance": { - "enabled": true, - "schedule": ["before 6am on Monday"], - "automerge": true, - "automergeType": "pr", - "commitMessageAction": "Refresh", - "matchBaseBranches": ["main"] - }, - - "composer": { "enabled": true, "ignorePlatformReqs": [] }, - "npm": { "enabled": true }, - "github-actions": { "enabled": true, "pinDigests": true }, - "docker-compose": { "enabled": true, "pinDigests": true }, - "dockerfile": { "enabled": true, "pinDigests": true }, - - "packageRules": [ - { - "description": "Hotfix: auto-merge patches/digests/lockfile on main after 7-day soak", - "matchBaseBranches": ["main"], - "matchUpdateTypes": [ - "patch", - "pin", - "digest", - "lockFileMaintenance" - ], - "automerge": true, - "automergeType": "pr", - "automergeStrategy": "squash", - "minimumReleaseAge": "7 days" - }, - { - "description": "Normal flow: minor/major on develop, dashboard approval, never auto-merge", - "matchBaseBranches": ["develop"], - "matchUpdateTypes": ["minor", "major"], - "dependencyDashboardApproval": true, - "automerge": false - }, - { - "description": "Suppress minor/major against main (those belong on develop)", - "matchBaseBranches": ["main"], - "matchUpdateTypes": ["minor", "major"], - "enabled": false - }, - { - "description": "Suppress patches against develop (they reach develop via back-merge after release)", - "matchBaseBranches": ["develop"], - "matchUpdateTypes": [ - "patch", - "pin", - "digest", - "lockFileMaintenance" - ], - "enabled": false - }, - { - "description": "Group Symfony patches into one PR on main", - "matchBaseBranches": ["main"], - "matchPackagePatterns": ["^symfony/"], - "matchUpdateTypes": ["patch"], - "groupName": "symfony (patch)" - }, - { - "description": "Group Doctrine patches on main", - "matchBaseBranches": ["main"], - "matchPackagePatterns": ["^doctrine/"], - "matchUpdateTypes": ["patch"], - "groupName": "doctrine (patch)" - }, - { - "description": "Group api-platform patches on main", - "matchBaseBranches": ["main"], - "matchPackagePatterns": ["^api-platform/"], - "matchUpdateTypes": ["patch"], - "groupName": "api-platform (patch)" - }, - { - "description": "Never auto-bump the PHP platform requirement", - "matchBaseBranches": ["develop"], - "matchPackageNames": ["php"], - "rangeStrategy": "in-range-only", - "automerge": false, - "dependencyDashboardApproval": true - }, - { - "description": "GitHub Actions: pin digests, auto-merge digest/patch on main", - "matchBaseBranches": ["main"], - "matchManagers": ["github-actions"], - "matchUpdateTypes": ["digest", "patch"], - "automerge": true - } - ], - - "postUpdateOptions": ["composerUpdateAllDependencies"], - - "postUpgradeTasks": { - "commands": [ - "bash .github/scripts/renovate-changelog.sh \"{{{branchName}}}\" \"{{{prTitle}}}\"" - ], - "fileFilters": ["CHANGELOG.md"], - "executionMode": "branch" - } -}