# Spec: Shopware plugin guideline compliance (build/release pipeline) Outcome of the Wayfinder map `.scratch/shopware-guideline-compliance/` (tickets 01-05; research evidence on branches `research/shopware-guideline-checklist`, `research/shopware-cli-ci-behaviour`, `research/gitea-28-pipeline-standards`). Target: **Store-ready** artifacts, published to Gitea only (Gitea Release + Composer registry). Uploading to the Shopware Store is out of scope. ## 1. Principles - Workflows are **plugin-agnostic**: no plugin name, package name, owner, repo or host is hard-coded; all derive from `composer.json` and the `gitea` context. The same files must work unchanged for a second plugin and be extractable to Gitea's shared-workflow repository later. - One artifact: the `shopware-cli extension package` zip (prebuilt admin/storefront JS) is the Gitea Release asset; the Composer registry gets the same content repacked root-level (the registry needs `composer.json` at the zip root, see section 4). - `shopware-cli` is intentionally **unpinned** (`latest`). Known tradeoff: a CLI release can turn PRs red without a repo change; treat that as a signal to fix config. - `RELEASE_TOKEN` is the only token (release, assets, registry publish, link). Workflows still declare `permissions:`. ## 2. Plugin changes | # | Change | |---|--------| | P1 | Commit `src/Resources/config/plugin.png` (256x256). Do not ship `plugin-transparent.png`. | | P2 | Logging: monolog channel `aeon_dump_manager` (`Resources/config/packages/monolog.yaml`, `build()` in the plugin class loading `packages/*.yaml`); inject `monolog.logger.aeon_dump_manager` into `PurgeDumpsTaskHandler`, `DumpService`, `CreateDumpHandler`; log dump job start/finish/failure. | | P3 | Migrate `services.xml` -> `services.yaml` and `routes.php` -> `routes.yaml`. No validation ignore for this. Update the "XML services" rule in `CLAUDE.md`. | | P4 | `composer.json`: `php` -> `^8.2`. Verify Shopware 6.6's own PHP requirement. | | P5 | Delete the empty lifecycle overrides in `AeonDumpManager`; keep `uninstall`. | | P6 | `.config/shopware-extension.yml` for build excludes and validation settings (add ignores only for real, accepted findings). | | P7 | Keep Keep-a-Changelog `CHANGELOG.md`; verify with a local `shopware-cli extension package --release` how the changelog is read. | ## 3. Pipeline ### PR workflows Jobs (all required checks on `main`): `plugin-checks.yml` (the former `pr-version-check.yml` was deleted; `version-changelog` is now a job in it): 0. `version-changelog` - version bump vs `main` and matching CHANGELOG heading. 1. `package` - `extension package` with `--git-commit "$GITHUB_SHA"`, `extension validate` on the resulting zip (hard gate; replaces a separate directory validate, which only repeats those checks), then `scripts/ci/assert-built-assets.sh` (built admin/storefront JS present when sources exist). All shopware-cli jobs run in `ghcr.io/shopware/shopware-cli:latest`; npm and shopware-cli caches via `actions/cache`. 2. `phpunit` - `composer create-project shopware/production` (6.6.x) + MariaDB service, copy the plugin into `custom/plugins`, install/activate, run phpunit. Runs in the same `shopware-cli` image (PHP and Composer included; `shivammathur/setup-php` hangs on this runner and apt installs cost ~4.5 min). MariaDB 10.11, because 11.4 broke Shopware's own migrations. ### Release workflow (`.gitea/workflows/release.yml`) On push to `main`, guarded against re-release by an existing tag: `extension package --git-commit "$GITHUB_SHA"` -> **validate the zip** -> assert built assets -> create the Gitea release via API (`POST /repos/{owner}/{repo}/releases`, creates the tag) with the zip as asset -> upload the same zip to the Composer registry -> link package to repository. Removes the manual `git tag` step, the `akkuman` action and the `git archive` zip. Packaging happens before the tag exists, so a failed build leaves no orphan tag. ### Branch protection (one-time, manual) `scripts/protect-main.sh` using `tea api PATCH repos/{owner}/{repo}/branch_protections/main` to set the required status-check contexts (now `plugin-checks / version-changelog|package|phpunit (pull_request)`, set on `main`). `tea branches protect` cannot set status checks. Not run by the pipeline. ## 4. Open items (status after the first pipeline run) - Release POST creates a missing tag: **resolved** - the POST created the tag and release for v0.1.0 (release id 55). - Meaning of HTTP 400 on the package-link endpoint: **open** (not evidenced yet). - Whether bare `validate` runs PHPStan/ESLint; Node availability on the runner image: **open** (not evidenced; the zip validate passes in the `shopware-cli` image). - Accepted size for `metadata.icon.size`; error-vs-warning rule list of validate: **resolved** - `validate` on the zip reports "No problems found", so the icon size is accepted. - Whether `routes.php` is flagged by validate: **resolved** - not flagged ("No problems found"). `shopware-cli extension fix` correctness for the YAML migration: **open**. - Exact status-check context names: **resolved** - final: `plugin-checks / version-changelog (pull_request)`, `plugin-checks / package (pull_request)`, `plugin-checks / phpunit (pull_request)`, set on `main`. - **Finding:** the Composer registry rejected the `shopware-cli` zip with "composer.json file is missing"; Gitea needs `composer.json` at the zip root, while the `shopware-cli` zip nests everything in a top-level folder. Fix (implemented separately): repack the zip with the top-level folder stripped for the registry upload; the Release asset stays the `shopware-cli` zip. ## 5. Out of scope / later Shopware Store upload; Gitea shared-workflow repository; phpunit lowest-version matrix; Store listing metadata.