diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2e12e3..3daa446 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,14 @@ on: branches: [main, develop] pull_request: branches: [main, develop] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: test: @@ -29,11 +37,11 @@ jobs: - name: Lint JavaScript run: npm run lint:js - continue-on-error: true # Don't fail on lint warnings initially + continue-on-error: true # Existing product lint debt remains non-blocking. - name: Lint CSS run: npm run lint:css - continue-on-error: true # Don't fail on lint warnings initially + continue-on-error: true # Existing product lint debt remains non-blocking. - name: Run tests run: npm test @@ -50,3 +58,36 @@ jobs: test -f build/integration-features-group/view.js test -f build/section-heading/index.js echo "✅ All build artifacts verified" + + composer-install: + name: Composer install and Strauss + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 + - uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + tools: composer:v2 + - name: Install Composer dependencies + run: composer install --prefer-dist --no-progress + + ci-summary: + name: CI summary + runs-on: ubuntu-latest + needs: [test, composer-install] + if: always() + steps: + - name: Require every CI job to run and pass + env: + TEST: ${{ needs.test.result }} + COMPOSER_INSTALL: ${{ needs.composer-install.result }} + run: | + set -euo pipefail + { + echo '## CI summary' + echo "- Frontend tests and build: $TEST" + echo "- Composer install and Strauss: $COMPOSER_INSTALL" + } >> "$GITHUB_STEP_SUMMARY" + test "$TEST" = success + test "$COMPOSER_INSTALL" = success diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 154eabe..463bf68 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,21 @@ name: Release +run-name: Release (${{ github.event_name == 'push' && github.ref_name || format('dry run {0}', inputs.version) }}) + on: push: tags: - - '[0-9]+.[0-9]+.[0-9]+*' + - '[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+-*' + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-*' + workflow_dispatch: + inputs: + version: + description: Version to package in a release-free dry run (with or without a v prefix). + required: true + default: '0.4.2' + type: string permissions: contents: write @@ -34,7 +46,25 @@ jobs: - name: Get version from tag id: get_version - run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + env: + DISPATCH_VERSION: ${{ inputs.version }} + run: | + set -euo pipefail + git_tag="$GITHUB_REF_NAME" + if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]]; then + git_tag="$DISPATCH_VERSION" + fi + version="${git_tag#v}" + if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "::error::Version/tag must be N.N.N or vN.N.N, optionally with a prerelease suffix." + exit 1 + fi + header_version="$(awk -F: '/^[[:space:]]*\*?[[:space:]]*Version:/ { gsub(/[[:space:]]/, "", $2); print $2; exit }' integration-features.php)" + test "$header_version" = "$version" + { + echo "VERSION=$version" + echo "GIT_TAG=$git_tag" + } >> "$GITHUB_OUTPUT" - name: Create plugin zip run: | @@ -55,8 +85,30 @@ jobs: zip -r ../integration-features-${{ steps.get_version.outputs.VERSION }}.zip integration-features cd .. + - name: Smoke-test and inspect the shipped archive + run: | + set -euo pipefail + archive="integration-features-${{ steps.get_version.outputs.VERSION }}.zip" + smoke="$(mktemp -d)" + trap 'rm -rf "$smoke"' EXIT + unzip -q "$archive" -d "$smoke" + test -f "$smoke/integration-features/integration-features.php" + while IFS= read -r -d '' file; do php -l "$file" >/dev/null; done < <(find "$smoke/integration-features" -name '*.php' -print0) + if unzip -Z1 "$archive" | grep -E '(^|/)(node_modules|tests|\.github)/|\.map$|\.DS_Store$'; then + echo '::error::Release archive contains development-only content.' + exit 1 + fi + + - name: Upload release-free proof artifact + uses: actions/upload-artifact@v6 + with: + name: release-zip + path: integration-features-${{ steps.get_version.outputs.VERSION }}.zip + retention-days: 5 + - name: Extract changelog for this version id: changelog + if: github.event_name == 'push' run: | # Extract changelog section for this version VERSION="${{ steps.get_version.outputs.VERSION }}" @@ -71,6 +123,7 @@ jobs: echo "$CHANGELOG" > changelog_extract.txt - name: Create GitHub Release + if: github.event_name == 'push' uses: softprops/action-gh-release@v2 with: files: integration-features-${{ steps.get_version.outputs.VERSION }}.zip diff --git a/.gitignore b/.gitignore index 8936404..55c9c98 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Dependencies node_modules/ vendor/ +strauss.phar # Build output build/ diff --git a/composer.json b/composer.json index 72dbdda..8b3c18e 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ }, "scripts": { "install-strauss": [ - "test -f strauss.phar || curl -o strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/download/0.22.4/strauss.phar" + "(test -f strauss.phar && echo '2141bf2cf5179bfceabf14dd647920abdfc7c3f1dfc702534d87e5994e5a3b48 strauss.phar' | shasum -a 256 -c - >/dev/null 2>&1) || curl -o strauss.phar -L https://github.com/BrianHenryIE/strauss/releases/download/0.29.1/strauss.phar", + "echo '2141bf2cf5179bfceabf14dd647920abdfc7c3f1dfc702534d87e5994e5a3b48 strauss.phar' | shasum -a 256 -c -" ], "clean-vendor-prefix-folder": [ "rm -rf vendor-prefixed/**/*" diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..241ded6 --- /dev/null +++ b/composer.lock @@ -0,0 +1,20 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f31a2e1394b349ed8c14ddd6646304e9", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": {}, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=7.4" + }, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +} diff --git a/vendor-prefixed/.gitkeep b/vendor-prefixed/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/vendor-prefixed/.gitkeep @@ -0,0 +1 @@ +