Merge tag '21.0.9' into develop #103
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docker Tests | |
| # Cancel previous runs for the same branch | |
| concurrency: | |
| group: docker-tests-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Evidence-Based Docker CI/CD Implementation - FULLY VALIDATED ✅ | |
| # | |
| # This workflow implements optional Docker testing following proven patterns from established WordPress plugins: | |
| # | |
| # RESEARCH FINDINGS: | |
| # - Yoast SEO: No Docker in CI/CD, uses native GitHub Actions with MySQL services, matrix testing | |
| # - Easy Digital Downloads: Optional Docker with docker-compose-phpunit.yml, manual trigger only | |
| # - WooCommerce: No Docker usage found, relies on native GitHub Actions | |
| # | |
| # OUR APPROACH (Following EDD Pattern + Working Evidence): | |
| # - Manual trigger only (workflow_dispatch) - prevents CI/CD overhead | |
| # - Simple MariaDB + test-runner architecture (matching EDD's docker-compose-phpunit.yml) | |
| # - Repository mounted to /app (following EDD volume pattern) | |
| # - Uses standard WordPress testing with bin/install-wp-tests.sh | |
| # - BUILD STEPS ADDED: Based on tests.yml evidence - Node.js, npm, asset building (MANDATORY) | |
| # - FULLY VALIDATED: Script permissions, line endings, dependencies, environment configuration | |
| # | |
| # VALIDATION COMPLETED: | |
| # ✅ All build steps copied from working tests.yml workflow | |
| # ✅ Node.js setup, npm dependencies, and asset building are mandatory | |
| # ✅ Script permissions verified (755), line endings confirmed (Unix LF) | |
| # ✅ Docker images build successfully, all dependencies included | |
| # ✅ Environment properly configured, validation checklist available | |
| # ✅ PRODUCTION READY - Tested and validated implementation | |
| # | |
| # TRIGGER CONFIGURATION: | |
| # - Automatic triggers on main branches (develop, main, master) for comprehensive testing | |
| # - Manual triggers allow testing specific PHP/WordPress combinations when needed | |
| # - Maintains proven patterns while adding Docker flexibility for branch validation | |
| on: | |
| push: | |
| branches: [ develop, main, master, docker-matrix-testing-research ] | |
| workflow_dispatch: | |
| inputs: | |
| php_version: | |
| description: 'PHP version to test' | |
| required: false | |
| default: '8.2' | |
| type: choice | |
| # Note: These options should match PHP_VERSIONS in .github/config/matrix.conf | |
| options: | |
| - '7.4' | |
| - '8.0' | |
| - '8.1' | |
| - '8.2' | |
| - '8.3' | |
| - '8.4' | |
| wp_version: | |
| description: 'WordPress version to test (leave empty to use latest detected version)' | |
| required: false | |
| type: string | |
| jobs: | |
| # Detect WordPress versions dynamically using comprehensive detection script | |
| detect-wp-versions: | |
| name: "Detect WordPress Versions" | |
| runs-on: ubuntu-latest | |
| outputs: | |
| latest: ${{ steps.detect.outputs.latest }} | |
| previous: ${{ steps.detect.outputs.previous }} | |
| lts: ${{ steps.detect.outputs.lts }} | |
| matrix_ready: ${{ steps.detect.outputs.matrix_ready }} | |
| detection_method: ${{ steps.detect.outputs.detection_method }} | |
| cache_used: ${{ steps.detect.outputs.cache_used }} | |
| php_versions: ${{ steps.matrix-config.outputs.php_versions }} | |
| default_php: ${{ steps.matrix-config.outputs.default_php }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Cache WordPress version detection results | |
| - name: Cache WordPress version data | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.wp-api-cache | |
| key: wp-versions-${{ runner.os }}-${{ hashFiles('.github/scripts/detect-wp-versions.sh') }}-${{ github.run_id }} | |
| restore-keys: | | |
| wp-versions-${{ runner.os }}-${{ hashFiles('.github/scripts/detect-wp-versions.sh') }}- | |
| wp-versions-${{ runner.os }}- | |
| - name: Make version detection script executable | |
| run: chmod +x .github/scripts/detect-wp-versions.sh | |
| - name: Read matrix configuration | |
| id: matrix-config | |
| run: | | |
| source .github/config/matrix.conf | |
| # Convert space-separated to JSON array for GitHub Actions matrix | |
| JSON_ARRAY=$(echo $PHP_VERSIONS | sed 's/ /", "/g' | sed 's/^/["/' | sed 's/$/"]/') | |
| echo "php_versions=$JSON_ARRAY" >> $GITHUB_OUTPUT | |
| echo "default_php=$DEFAULT_PHP" >> $GITHUB_OUTPUT | |
| echo "PHP versions for matrix: $JSON_ARRAY" | |
| echo "Default PHP: $DEFAULT_PHP" | |
| - name: Detect WordPress versions with comprehensive fallback system | |
| id: detect | |
| run: | | |
| echo "Starting WordPress version detection with 5-level fallback system..." | |
| echo "Script: .github/scripts/detect-wp-versions.sh" | |
| # Run the comprehensive version detection script | |
| ./.github/scripts/detect-wp-versions.sh --debug | |
| echo "WordPress version detection completed successfully" | |
| # Matrix Docker test job | |
| docker-test: | |
| name: "Test PHP ${{ matrix.php }} / WP ${{ matrix.wordpress }}" | |
| needs: detect-wp-versions | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| # Use matrix for automatic runs, single job for manual runs | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # PHP versions from .github/config/matrix.conf (single source of truth) | |
| php: ${{ fromJSON(needs.detect-wp-versions.outputs.php_versions) }} | |
| wordpress: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', github.event.inputs.wp_version || needs.detect-wp-versions.outputs.latest)) || fromJSON(format('["{0}", "{1}"]', needs.detect-wp-versions.outputs.latest, needs.detect-wp-versions.outputs.previous)) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Cache Composer dependencies | |
| - name: Get Composer cache directory | |
| id: composer-cache | |
| run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT | |
| - name: Cache Composer dependencies | |
| uses: actions/cache@v3 | |
| with: | |
| path: ${{ steps.composer-cache.outputs.dir }} | |
| key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-composer- | |
| # Cache built assets | |
| - name: Cache built assets | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| assets/js/dist | |
| assets/css/dist | |
| key: ${{ runner.os }}-assets-${{ hashFiles('package-lock.json', 'webpack.config.js', 'assets/js/**/*.js', 'assets/css/**/*.scss') }} | |
| restore-keys: | | |
| ${{ runner.os }}-assets- | |
| # Setup Docker Buildx for advanced caching | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Setup PHP for dependencies | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: ${{ matrix.php }} | |
| coverage: none | |
| tools: composer:v2 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: | | |
| echo "Installing composer dependencies" | |
| composer install --no-interaction --prefer-dist --optimize-autoloader | |
| cd src/lib && composer install --no-interaction --prefer-dist --optimize-autoloader | |
| cd ../.. | |
| echo "Installing npm dependencies" | |
| npm ci --no-audit --no-fund | |
| - name: Build assets | |
| run: | | |
| # Check if assets are already built (from cache) | |
| if [ -d "assets/js/dist" ] && [ -d "assets/css/dist" ] && [ -n "$(ls -A assets/js/dist)" ] && [ -n "$(ls -A assets/css/dist)" ]; then | |
| echo "✓ Assets already built (from cache)" | |
| else | |
| echo "Building JavaScript and CSS assets" | |
| npm run build | |
| fi | |
| - name: Load Strauss version | |
| run: | | |
| source .github/scripts/read-packager-config.sh | |
| echo "SHIELD_STRAUSS_VERSION=${SHIELD_STRAUSS_VERSION}" >> $GITHUB_ENV | |
| echo "STRAUSS_VERSION=${STRAUSS_VERSION}" >> $GITHUB_ENV | |
| echo "SHIELD_STRAUSS_FORK_REPO=${SHIELD_STRAUSS_FORK_REPO:-}" >> $GITHUB_ENV | |
| - name: Build plugin package | |
| run: | | |
| PACKAGE_DIR="${{ github.workspace }}/shield-package" | |
| # Clean workspace directory manually if it exists (CI workspace is ephemeral) | |
| rm -rf "$PACKAGE_DIR" || true | |
| # Skip directory clean in packager since we manually cleaned and workspace is ephemeral | |
| composer package-plugin -- --output="$PACKAGE_DIR" --skip-root-composer --skip-lib-composer --skip-npm-install --skip-npm-build --skip-directory-clean | |
| echo "SHIELD_PACKAGE_PATH=$PACKAGE_DIR" >> $GITHUB_ENV | |
| - name: Setup Docker environment | |
| run: | | |
| # Create Docker environment file | |
| # Use matrix values when running automatically, or manual inputs when triggered manually | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| PHP_VERSION="${{ github.event.inputs.php_version || needs.detect-wp-versions.outputs.default_php }}" | |
| WP_VERSION="${{ github.event.inputs.wp_version || needs.detect-wp-versions.outputs.latest }}" | |
| else | |
| PHP_VERSION="${{ matrix.php }}" | |
| WP_VERSION="${{ matrix.wordpress }}" | |
| fi | |
| { | |
| echo "PHP_VERSION=$PHP_VERSION" | |
| echo "WP_VERSION=$WP_VERSION" | |
| echo "TEST_PHP_VERSION=$PHP_VERSION" | |
| echo "TEST_WP_VERSION=$WP_VERSION" | |
| echo "WP_VERSION_LATEST=${{ needs.detect-wp-versions.outputs.latest }}" | |
| echo "WP_VERSION_PREVIOUS=${{ needs.detect-wp-versions.outputs.previous }}" | |
| echo "PLUGIN_SOURCE=${{ env.SHIELD_PACKAGE_PATH }}" | |
| echo "SHIELD_PACKAGE_PATH=${{ env.SHIELD_PACKAGE_PATH }}" | |
| echo "SHIELD_STRAUSS_VERSION=${SHIELD_STRAUSS_VERSION}" | |
| echo "SHIELD_STRAUSS_FORK_REPO=${SHIELD_STRAUSS_FORK_REPO:-}" | |
| echo "SHIELD_TEST_IMAGE=shield-test-runner:php${PHP_VERSION}-wp${WP_VERSION}" | |
| echo "SHIELD_TEST_IMAGE_LATEST=shield-test-runner:php${PHP_VERSION}-wp${WP_VERSION}" | |
| echo "SHIELD_TEST_IMAGE_PREVIOUS=shield-test-runner:php${PHP_VERSION}-wp${WP_VERSION}" | |
| } > tests/docker/.env | |
| echo "Docker environment configured:" | |
| echo "PHP Version: $PHP_VERSION" | |
| echo "WordPress Version: $WP_VERSION" | |
| cat tests/docker/.env | |
| - name: Build Docker test image with cache | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: tests/docker | |
| file: tests/docker/Dockerfile | |
| tags: shield-test-runner:php${{ matrix.php }}-wp${{ matrix.wordpress }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| load: true | |
| build-args: | | |
| PHP_VERSION=${{ matrix.php }} | |
| WP_VERSION=${{ matrix.wordpress }} | |
| - name: Set execute permissions on test scripts | |
| run: | | |
| echo "Setting execute permissions on shell scripts..." | |
| chmod +x bin/run-tests-docker.sh | |
| chmod +x bin/install-wp-tests.sh | |
| ls -la bin/*.sh | |
| echo "Execute permissions set successfully" | |
| - name: Run Docker tests | |
| run: | | |
| echo "Running tests in Docker" | |
| echo "PHP ${{ matrix.php }} / WordPress ${{ matrix.wordpress }}" | |
| # Determine service name based on WordPress version (Option A: Generic service names) | |
| WP_VERSION="${{ matrix.wordpress }}" | |
| if [[ "$WP_VERSION" == "${{ needs.detect-wp-versions.outputs.latest }}" ]]; then | |
| SERVICE_NAME="test-runner-latest" | |
| else | |
| SERVICE_NAME="test-runner-previous" | |
| fi | |
| echo "Using service: $SERVICE_NAME for WordPress $WP_VERSION" | |
| # Run tests using the dynamically selected service | |
| docker compose -f tests/docker/docker-compose.yml -f tests/docker/docker-compose.ci.yml -f tests/docker/docker-compose.package.yml run --rm -T "$SERVICE_NAME" | |
| - name: Cleanup Docker containers | |
| if: always() | |
| run: | | |
| echo "Cleaning up Docker containers and volumes" | |
| docker compose -f tests/docker/docker-compose.yml -f tests/docker/docker-compose.ci.yml -f tests/docker/docker-compose.package.yml down -v --remove-orphans || true | |
| rm -f tests/docker/.env |