feat: plugin skeleton for Shopware 6.6 and 6.7 with CI and release pipeline
- composer.json (MIT, shopware/core ~6.6.0 || ~6.7.0, PHP ^8.2), plugin class, placeholder icon - PR checks and release workflow taken over from AeonDumpManager; phpunit runs as a 6.6/6.7 matrix - CHANGELOG, LICENSE, README, CLAUDE.md, smoke test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fb6bdf6e8d
commit
be549d4a51
21 files changed
+997
-48
No files matched your search
@@ -0,0 +1,195 @@
|
||||
name: plugin-checks
|
||||
|
||||
# Plugin-agnostic: nothing below names this plugin. Name, version and paths come from composer.json.
|
||||
# shopware-cli runs from its official Docker image, intentionally unpinned (latest); a red build
|
||||
# after a CLI release means fix the config.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# A new push to the PR cancels the superseded run.
|
||||
concurrency:
|
||||
group: plugin-checks-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# Every PR into main must bump the version and document it in CHANGELOG.md.
|
||||
version-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# The version must be higher than the latest *published release* (not just higher than main), so main can
|
||||
# carry a version whose release failed or was withdrawn without blocking the next PR.
|
||||
- name: Check version is unreleased and changelog entry exists
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
PR_VERSION=$(grep -m1 '"version"' composer.json | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
|
||||
LATEST=$(curl -sf -H "Authorization: token ${TOKEN}" "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/releases?limit=100" \
|
||||
| jq -r '.[].tag_name' | sed 's/^v//' | sort -V | tail -n1)
|
||||
LATEST="${LATEST:-0.0.0}"
|
||||
|
||||
echo "latest release: $LATEST"
|
||||
echo "PR version: $PR_VERSION"
|
||||
|
||||
if [ "$PR_VERSION" = "$LATEST" ] || [ "$(printf '%s\n%s\n' "$LATEST" "$PR_VERSION" | sort -V | tail -n1)" != "$PR_VERSION" ]; then
|
||||
echo "::error::composer.json version ($PR_VERSION) is not greater than the latest release ($LATEST)"
|
||||
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: $PR_VERSION is unreleased and documented in CHANGELOG.md"
|
||||
|
||||
# Packages the extension (builds admin/storefront assets) and validates the resulting zip,
|
||||
# which is the artifact that ships. A separate directory validate would only repeat these checks.
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/shopware/shopware-cli:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.gitea/actions/package
|
||||
# The release workflow reuses this tested zip when main ends up with the same tree
|
||||
# (it falls back to packaging again otherwise).
|
||||
- name: Tree hash of the packaged commit
|
||||
id: tree
|
||||
run: echo "hash=$(git rev-parse "${GITHUB_SHA}^{tree}")" >> "$GITHUB_OUTPUT"
|
||||
- name: Save tested zip for the release
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .build/package.zip
|
||||
key: plugin-zip-${{ steps.tree.outputs.hash }}
|
||||
|
||||
# One run per supported Shopware minor (keep in sync with require.shopware/core in composer.json).
|
||||
phpunit:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shopware: ['6.6', '6.7']
|
||||
# Same image as above: it already ships PHP, Composer and Node, so no apt install.
|
||||
container:
|
||||
image: ghcr.io/shopware/shopware-cli:latest
|
||||
services:
|
||||
database:
|
||||
# Shopware 6.6 and 6.7 both support MariaDB 10.11; 11.4 broke 6.6's own migrations.
|
||||
image: mariadb:10.11
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: root
|
||||
env:
|
||||
# Already the *_test name: Shopware's TestBootstrapper would otherwise append _test and run every migration a second time.
|
||||
DATABASE_URL: mysql://root:root@database:3306/shopware_test
|
||||
APP_ENV: test
|
||||
APP_URL: http://localhost
|
||||
APP_SECRET: ci-secret-not-for-production
|
||||
INSTANCE_ID: ci
|
||||
COMPOSER_MEMORY_LIMIT: '-1'
|
||||
COMPOSER_ALLOW_SUPERUSER: '1'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: plugin-src
|
||||
# The cache key follows the Shopware version: a new release inside the plugin's supported range changes
|
||||
# the key, so the old project + database are never reused. Bump -v1 to force a refresh by hand.
|
||||
- name: Resolve the latest Shopware Version
|
||||
id: sw
|
||||
run: |
|
||||
set -e
|
||||
# The matrix minor (e.g. ~6.6.0) decides which versions are acceptable;
|
||||
# Composer lists the matching ones newest first, the first stable one is the latest.
|
||||
CONSTRAINT="~${{ matrix.shopware }}.0"
|
||||
VERSION=$(composer show shopware/core "$CONSTRAINT" --all --format=json --no-interaction 2>/dev/null \
|
||||
| php -r '$d = json_decode(stream_get_contents(STDIN), true); foreach ($d["versions"] as $v) { if (preg_match("/^v?\d+(\.\d+)+$/", $v)) { echo ltrim($v, "v"); exit; } }')
|
||||
test -n "$VERSION" || { echo "::error::could not resolve a Shopware version for ${CONSTRAINT}"; exit 1; }
|
||||
echo "Shopware ${VERSION} (constraint ${CONSTRAINT})"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "constraint=${CONSTRAINT}" >> "$GITHUB_OUTPUT"
|
||||
# Project (vendor/, phpunit, config) and the installed database as a SQL dump. Neither depends on the plugin.
|
||||
- name: Restore Shopware project and database
|
||||
id: shopware
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
shopware
|
||||
!shopware/var/cache
|
||||
!shopware/var/log
|
||||
shopware-db.sql.gz
|
||||
key: shopware-${{ steps.sw.outputs.version }}-installed-v1
|
||||
- name: Create Shopware project
|
||||
if: steps.shopware.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -e
|
||||
# shopware/production pins one exact core version and is not tagged for every core patch
|
||||
# (e.g. core 6.6.10.31, template only up to 6.6.10.30): take the newest template inside the
|
||||
# constraint, then require the resolved core version on top of it.
|
||||
composer create-project "shopware/production:${{ steps.sw.outputs.constraint }}" shopware --no-interaction --no-scripts --no-install
|
||||
composer require "shopware/core:${{ steps.sw.outputs.version }}" --no-update -d shopware
|
||||
composer require --dev phpunit/phpunit:^10 --no-update -d shopware
|
||||
composer update -W --no-interaction --no-scripts -d shopware
|
||||
- name: Ensure the MariaDB client
|
||||
run: |
|
||||
command -v mariadb-dump >/dev/null || command -v mysqldump >/dev/null && exit 0
|
||||
(apt-get update -q && apt-get install -y -q --no-install-recommends mariadb-client) || apk add --no-cache mariadb-client
|
||||
- name: Wait for the database
|
||||
run: |
|
||||
for i in $(seq 60); do
|
||||
(echo > /dev/tcp/database/3306) 2>/dev/null && exit 0
|
||||
sleep 2
|
||||
done
|
||||
echo "::error::database service did not come up"; exit 1
|
||||
- name: Relax database durability (throwaway CI database, speeds up the install and the restore)
|
||||
run: |
|
||||
php -r '$p = new PDO("mysql:host=database;port=3306", "root", "root"); $p->exec("SET GLOBAL innodb_flush_log_at_trx_commit=0"); $p->exec("SET GLOBAL sync_binlog=0");'
|
||||
# One install into shopware_test; the bootstrapper then sees an installed DB, skips its own install and
|
||||
# only activates the plugin (tests/TestBootstrap.php forces plugin installation).
|
||||
- name: Install Shopware
|
||||
if: steps.shopware.outputs.cache-hit != 'true'
|
||||
working-directory: shopware
|
||||
run: bin/console system:install --basic-setup --create-database --force --no-interaction
|
||||
- name: Dump the installed database
|
||||
if: steps.shopware.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -e
|
||||
DUMP=$(command -v mariadb-dump || command -v mysqldump)
|
||||
"$DUMP" -h database -P 3306 -u root -proot --skip-ssl --single-transaction --routines --triggers \
|
||||
--databases shopware_test | gzip > shopware-db.sql.gz
|
||||
ls -l shopware-db.sql.gz
|
||||
- name: Save Shopware project and database
|
||||
if: steps.shopware.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
shopware
|
||||
!shopware/var/cache
|
||||
!shopware/var/log
|
||||
shopware-db.sql.gz
|
||||
key: shopware-${{ steps.sw.outputs.version }}-installed-v1
|
||||
- name: Restore the database from the cache
|
||||
if: steps.shopware.outputs.cache-hit == 'true'
|
||||
run: |
|
||||
set -e
|
||||
CLIENT=$(command -v mariadb || command -v mysql)
|
||||
gunzip -c shopware-db.sql.gz | "$CLIENT" -h database -P 3306 -u root -proot --skip-ssl
|
||||
- name: Resolve plugin name and install the plugin sources
|
||||
run: |
|
||||
# plugin directory name = short class name of extra.shopware-plugin-class
|
||||
CLASS=$(php -r 'echo json_decode(file_get_contents("plugin-src/composer.json"), true)["extra"]["shopware-plugin-class"];')
|
||||
PLUGIN_NAME="${CLASS##*\\}"
|
||||
echo "PLUGIN_NAME=${PLUGIN_NAME}" >> "$GITHUB_ENV"
|
||||
rm -rf "shopware/custom/plugins/${PLUGIN_NAME}"
|
||||
cp -r plugin-src "shopware/custom/plugins/${PLUGIN_NAME}"
|
||||
- name: Run phpunit
|
||||
working-directory: shopware
|
||||
run: vendor/bin/phpunit -c "custom/plugins/${PLUGIN_NAME}/phpunit.xml"
|
||||
Reference in new issue
Block a user