diff --git a/.gitea/actions/package/action.yml b/.gitea/actions/package/action.yml new file mode 100644 index 0000000..131f957 --- /dev/null +++ b/.gitea/actions/package/action.yml @@ -0,0 +1,35 @@ +name: package-extension +description: >- + Package the Shopware extension with shopware-cli (builds admin/storefront assets), validate the + zip and assert it contains the built JS. Shared by the PR checks and the release workflow. + Must run in the ghcr.io/shopware/shopware-cli image, after actions/checkout. + +inputs: + filename: + description: Name of the zip written to .build/ + default: package.zip + build: + description: "'false' skips packaging (a prebuilt zip is already in .build/) and only validates it" + default: 'true' + +runs: + using: composite + steps: + - uses: actions/cache@v4 + if: inputs.build == 'true' + with: + path: | + ~/.npm + ~/.cache/shopware-cli + key: swcli-${{ runner.os }}-${{ hashFiles('composer.json', 'src/Resources/app/**/package*.json') }} + restore-keys: swcli-${{ runner.os }}- + - name: Package extension + if: inputs.build == 'true' + shell: bash + run: shopware-cli extension package . --output-directory .build --filename "${{ inputs.filename }}" --git-commit "$GITHUB_SHA" + - name: Validate packaged zip + shell: bash + run: shopware-cli extension validate ".build/${{ inputs.filename }}" + - name: Assert built JS is in the zip + shell: bash + run: scripts/ci/assert-built-assets.sh ".build/${{ inputs.filename }}" diff --git a/.gitea/workflows/plugin-checks.yml b/.gitea/workflows/plugin-checks.yml index 2f8c8f4..2f75c74 100644 --- a/.gitea/workflows/plugin-checks.yml +++ b/.gitea/workflows/plugin-checks.yml @@ -17,6 +17,41 @@ concurrency: 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 + 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" + # 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: @@ -27,19 +62,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/cache@v4 - with: - path: | - ~/.npm - ~/.cache/shopware-cli - key: swcli-${{ runner.os }}-${{ hashFiles('composer.json', 'src/Resources/app/**/package*.json') }} - restore-keys: swcli-${{ runner.os }}- - - name: Package extension - run: shopware-cli extension package . --output-directory .build --filename package.zip --git-commit "$GITHUB_SHA" - - name: Validate packaged zip - run: shopware-cli extension validate .build/package.zip - - name: Assert built JS is in the zip - run: scripts/ci/assert-built-assets.sh .build/package.zip + - 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 @@ -68,6 +91,7 @@ jobs: APP_URL: http://localhost APP_SECRET: ci-secret-not-for-production INSTANCE_ID: ci + FORCE_INSTALL: '1' # TestBootstrapper then always installs its own test DB (no separate system:install) COMPOSER_MEMORY_LIMIT: '-1' COMPOSER_ALLOW_SUPERUSER: '1' steps: diff --git a/.gitea/workflows/pr-version-check.yml b/.gitea/workflows/pr-version-check.yml deleted file mode 100644 index 271dbc1..0000000 --- a/.gitea/workflows/pr-version-check.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: version-changelog - -on: - pull_request: - branches: [main] - -permissions: - contents: read - -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" diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 5719fa5..855327c 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -63,32 +63,16 @@ jobs: path: .build/package.zip key: plugin-zip-${{ steps.tree.outputs.hash }} - - uses: actions/cache@v4 - if: steps.meta.outputs.skip == 'false' && steps.prebuilt.outputs.cache-hit != 'true' - with: - path: | - ~/.npm - ~/.cache/shopware-cli - key: swcli-${{ runner.os }}-${{ hashFiles('composer.json', 'src/Resources/app/**/package*.json') }} - restore-keys: swcli-${{ runner.os }}- - - - name: Package extension (only if the tested zip is not available) - if: steps.meta.outputs.skip == 'false' && steps.prebuilt.outputs.cache-hit != 'true' - run: | - shopware-cli extension package . --output-directory .build --filename package.zip --git-commit "$GITHUB_SHA" - - - name: Name the zip - if: steps.meta.outputs.skip == 'false' + - name: Name the prebuilt zip + if: steps.meta.outputs.skip == 'false' && steps.prebuilt.outputs.cache-hit == 'true' run: mv .build/package.zip ".build/${{ steps.meta.outputs.zip }}" - # Cheap, and guards against a bad cache entry: always validate what ships. - - name: Validate packaged zip + # Packages only on a cache miss; always validates and asserts what ships (guards a bad cache entry). + - uses: ./.gitea/actions/package if: steps.meta.outputs.skip == 'false' - run: shopware-cli extension validate ".build/${{ steps.meta.outputs.zip }}" - - - name: Assert built JS is in the zip - if: steps.meta.outputs.skip == 'false' - run: scripts/ci/assert-built-assets.sh ".build/${{ steps.meta.outputs.zip }}" + with: + filename: ${{ steps.meta.outputs.zip }} + build: ${{ steps.prebuilt.outputs.cache-hit != 'true' }} - name: Extract changelog section if: steps.meta.outputs.skip == 'false' diff --git a/scripts/protect-main.sh b/scripts/protect-main.sh index d33ebe6..33af5df 100755 --- a/scripts/protect-main.sh +++ b/scripts/protect-main.sh @@ -9,7 +9,7 @@ REPO="${1:-$(git config --get remote.origin.url | sed -E 's#^.*[:/]([^/]+/[^/]+) tea api -X PATCH "repos/${REPO}/branch_protections/main" -d '{ "enable_status_check": true, "status_check_contexts": [ - "version-changelog / version-changelog (pull_request)", + "plugin-checks / version-changelog (pull_request)", "plugin-checks / package (pull_request)", "plugin-checks / phpunit (pull_request)" ]