From 31b9e61adb212a042f1f34674bffb749dc08b60c Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Mon, 21 Sep 2026 18:37:10 +0200 Subject: [PATCH 1/4] ci: add pre-merge version-and-changelog check for PRs into main --- .gitea/workflows/pr-version-check.yml | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .gitea/workflows/pr-version-check.yml diff --git a/.gitea/workflows/pr-version-check.yml b/.gitea/workflows/pr-version-check.yml new file mode 100644 index 0000000..3f5a2d8 --- /dev/null +++ b/.gitea/workflows/pr-version-check.yml @@ -0,0 +1,40 @@ +name: version-changelog + +on: + pull_request: + branches: [main] + +jobs: + version-changelog: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check version bump and changelog entry + run: | + set -e + PR_VERSION=$(grep -m1 '"version"' composer.json | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/') + MAIN_VERSION=$(git show origin/main:composer.json | grep -m1 '"version"' | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/') + + echo "main version: $MAIN_VERSION" + echo "PR version: $PR_VERSION" + + if [ "$MAIN_VERSION" = "$PR_VERSION" ]; then + echo "::error::composer.json version ($PR_VERSION) was not bumped from main ($MAIN_VERSION)" + exit 1 + fi + + HIGHEST=$(printf '%s\n%s\n' "$MAIN_VERSION" "$PR_VERSION" | sort -V | tail -n1) + if [ "$HIGHEST" != "$PR_VERSION" ]; then + echo "::error::composer.json version ($PR_VERSION) is not greater than main's ($MAIN_VERSION)" + exit 1 + fi + + if ! grep -qF "## [$PR_VERSION]" CHANGELOG.md; then + echo "::error::CHANGELOG.md is missing a '## [$PR_VERSION]' heading" + exit 1 + fi + + echo "OK: version bumped to $PR_VERSION and documented in CHANGELOG.md" -- 2.54.0 From b2c2a8d80b6a3f756b3ae7683be341ebb15e957e Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Mon, 21 Sep 2026 18:53:22 +0200 Subject: [PATCH 2/4] ci: add post-merge tag, package, and release workflow --- .gitea/workflows/release.yml | 97 ++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..4547181 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,97 @@ +name: release + +on: + push: + branches: [main] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.RELEASE_TOKEN }} + + - name: Determine version and guard against re-release + id: version + run: | + set -e + VERSION=$(grep -m1 '"version"' composer.json | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/') + TAG="v${VERSION}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + if git ls-remote --tags origin "refs/tags/${TAG}" | grep -q "${TAG}"; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "Tag ${TAG} already exists, nothing to release." + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Extract changelog section + if: steps.version.outputs.skip == 'false' + run: | + awk -v ver="${{ steps.version.outputs.version }}" ' + BEGIN { found=0 } + /^## \[/ { + if (found) exit + if ($0 ~ "\[" ver "\]") { found=1; next } + } + found { print } + ' CHANGELOG.md > release-notes.md + cat release-notes.md + + - name: Create and push tag + if: steps.version.outputs.skip == 'false' + run: | + git config user.name "gitea-actions" + git config user.email "actions@git.arthurerlich.de" + git tag "${{ steps.version.outputs.tag }}" + git push origin "${{ steps.version.outputs.tag }}" + + - name: Install shopware-cli + if: steps.version.outputs.skip == 'false' + run: | + curl -sL -o /tmp/shopware-cli.tar.gz \ + https://github.com/shopware/shopware-cli/releases/latest/download/shopware-cli_Linux_x86_64.tar.gz + mkdir -p /tmp/swcli-extract + tar -xzf /tmp/shopware-cli.tar.gz -C /tmp/swcli-extract + cp /tmp/swcli-extract/shopware-cli /usr/local/bin/shopware-cli + + - name: Validate extension (informational only, does not gate the release) + if: steps.version.outputs.skip == 'false' + run: shopware-cli extension validate . || true + + - name: Package Store-style zip for the Gitea Release asset + if: steps.version.outputs.skip == 'false' + run: | + shopware-cli extension package . --output-directory .build \ + --filename "AeonDumpManager-${{ steps.version.outputs.tag }}.zip" + + - name: Build root-level zip for the Composer registry + if: steps.version.outputs.skip == 'false' + run: git archive --format=zip -o "composer-package-${{ steps.version.outputs.tag }}.zip" "${{ steps.version.outputs.tag }}" + + - name: Create Gitea Release + if: steps.version.outputs.skip == 'false' + uses: akkuman/gitea-release-action@v1 + with: + server_url: ${{ vars.SERVER_URL }} + token: ${{ secrets.RELEASE_TOKEN }} + tag_name: ${{ steps.version.outputs.tag }} + name: ${{ steps.version.outputs.tag }} + body_path: release-notes.md + files: .build/AeonDumpManager-${{ steps.version.outputs.tag }}.zip + + - name: Publish to Composer registry + if: steps.version.outputs.skip == 'false' + run: | + STATUS=$(curl -s -o /tmp/composer-publish.log -w "%{http_code}" \ + -u "haylan:${{ secrets.RELEASE_TOKEN }}" \ + -T "composer-package-${{ steps.version.outputs.tag }}.zip" \ + "https://git.arthurerlich.de/api/packages/haylan/composer") + cat /tmp/composer-publish.log + if [ "$STATUS" != "201" ] && [ "$STATUS" != "409" ]; then + echo "Unexpected HTTP status $STATUS publishing to the Composer registry" + exit 1 + fi -- 2.54.0 From 1ee83aad37452f2874fafa423611b9ab13863172 Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Mon, 21 Sep 2026 19:10:24 +0200 Subject: [PATCH 3/4] ci: hardcode SERVER_URL as a workflow env var instead of an Actions variable --- .gitea/workflows/release.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 4547181..d941600 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -4,6 +4,9 @@ on: push: branches: [main] +env: + SERVER_URL: https://git.arthurerlich.de + jobs: release: runs-on: ubuntu-latest @@ -76,7 +79,7 @@ jobs: if: steps.version.outputs.skip == 'false' uses: akkuman/gitea-release-action@v1 with: - server_url: ${{ vars.SERVER_URL }} + server_url: ${{ env.SERVER_URL }} token: ${{ secrets.RELEASE_TOKEN }} tag_name: ${{ steps.version.outputs.tag }} name: ${{ steps.version.outputs.tag }} -- 2.54.0 From 161c35dc8a9ac890e44128695844b27bde2ebdfe Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Mon, 21 Sep 2026 19:18:06 +0200 Subject: [PATCH 4/4] chore(release): bump to 0.0.2 for the CI/CD release pipeline itself --- CHANGELOG.md | 11 +++++++++++ composer.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb34e0..931f37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to AeonDumpManager will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.0.2] - 2026-09-21 + +### Added + +- Automated release pipeline: a pre-merge check enforcing a semver version bump and a matching + CHANGELOG entry on every PR into `main`, and a post-merge workflow that tags the release, + packages the plugin with `shopware-cli`, publishes a Gitea Release with the packaged zip, and + publishes the package to this Gitea instance's Composer registry. +- `main` is now a protected branch: no direct pushes, merges require the version/changelog check + to pass. + ## [Unreleased] ### Added diff --git a/composer.json b/composer.json index 9d7c2ac..adc23b7 100755 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Export database dumps for Shopware 6 environments.", "type": "shopware-platform-plugin", "license": "MIT", - "version": "0.0.1", + "version": "0.0.2", "keywords": [ "shopware", "shopware6", -- 2.54.0