diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 145dfb2..17edbc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,12 +15,15 @@ concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true -permissions: {} +permissions: + contents: read jobs: detect: name: Detect Changes - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: ubuntu:24.04 if: github.event_name != 'pull_request' || github.event.pull_request.draft == false permissions: contents: read @@ -36,10 +39,16 @@ jobs: jest: ${{ steps.filter.outputs.jest }} steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Detect file changes uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -138,6 +147,7 @@ jobs: contents: read strategy: fail-fast: false + max-parallel: 1 matrix: php: ['8.4', '8.3', '8.2'] wp: ['latest'] @@ -153,8 +163,8 @@ jobs: e2e: name: E2E Tests - needs: detect - if: needs.detect.outputs.php == 'true' || needs.detect.outputs.e2e == 'true' || needs.detect.outputs.js == 'true' || needs.detect.outputs.css == 'true' + needs: [detect, phpunit] + if: needs.detect.result == 'success' && (needs.phpunit.result == 'success' || needs.phpunit.result == 'skipped') && (needs.detect.outputs.php == 'true' || needs.detect.outputs.e2e == 'true' || needs.detect.outputs.js == 'true' || needs.detect.outputs.css == 'true') uses: ./.github/workflows/reusable-e2e.yml permissions: contents: read @@ -163,6 +173,8 @@ jobs: build-plugin-zip: name: Build Plugin Zip + needs: [e2e] + if: needs.e2e.result == 'success' || needs.e2e.result == 'skipped' permissions: contents: read uses: ./.github/workflows/reusable-build.yml diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 66658f5..3978c24 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -12,15 +12,47 @@ on: jobs: build: - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: ubuntu:24.04 + options: --user root -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/wp-env:/tmp/wp-env permissions: contents: read + + env: + WP_ENV_PORT: 8889 + WP_ENV_TESTS_PORT: 8891 + WP_ENV_HOME: /tmp/wp-env + + timeout-minutes: 30 + steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git curl sudo unzip jq + + - name: setup Docker + run: | + curl -fsSL https://get.docker.com -o get-docker.sh + sh get-docker.sh + + - name: Configure Docker group permissions + run: | + useradd -m wpuser + SOCK_GID=$(stat -c '%g' /var/run/docker.sock) + groupmod -g $SOCK_GID -o docker + usermod -aG docker wpuser + mkdir -p /tmp/wp-env + chown -R wpuser:wpuser /tmp/wp-env + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Set up PHP uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0 @@ -45,15 +77,39 @@ jobs: - name: Build plugin for release run: npm run build:prod + - name: Fix wp-env host mapping + run: | + # Get the host path for the workspace by inspecting the container's own mounts + HOST_WORKSPACE_PATH=$(docker inspect $(hostname) --format '{{ range .Mounts }}{{ if eq .Destination "/__w" }}{{ .Source }}{{ end }}{{ end }}') + + # Construct the full host path for the current plugin directory + RELATIVE_PATH=$(pwd | sed 's|^/__w||') + PLUGIN_HOST_PATH="${HOST_WORKSPACE_PATH}${RELATIVE_PATH}" + + echo "Host Workspace: $HOST_WORKSPACE_PATH" + echo "Plugin Host Path: $PLUGIN_HOST_PATH" + + # Update .wp-env.json (default env) + jq --arg path "$PLUGIN_HOST_PATH" \ + 'del(.plugins) | .mappings["wp-content/plugins/plugin-skeleton-d"] = $path' \ + .wp-env.json > .wp-env.json.tmp && mv .wp-env.json.tmp .wp-env.json + + cat .wp-env.json + + - name: Fix workspace permissions + run: chown -R wpuser:wpuser . + - name: Start the Docker testing environment uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: timeout_minutes: 10 max_attempts: 3 - command: npm run wp-env start + command: | + sudo -u wpuser git config --global --add safe.directory '/tmp/wp-env/*' + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" "WP_ENV_PORT=$WP_ENV_PORT" "WP_ENV_TESTS_PORT=$WP_ENV_TESTS_PORT" npm run wp-env start -- --update - name: Generate Translation files - run: npm run i18n:make-pot + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run i18n:make-pot - name: Create plugin zip run: npm run plugin-zip @@ -64,3 +120,7 @@ jobs: name: ${{ inputs.artifact-name }} path: plugin-skeleton-d.zip if-no-files-found: error + + - name: Stop the Docker testing environment + if: always() + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env destroy -- --force diff --git a/.github/workflows/reusable-e2e.yml b/.github/workflows/reusable-e2e.yml index e5dce7d..e8afc75 100644 --- a/.github/workflows/reusable-e2e.yml +++ b/.github/workflows/reusable-e2e.yml @@ -8,20 +8,51 @@ on: required: true type: string -permissions: {} +permissions: + contents: read jobs: e2e: name: Playwright E2E Tests - runs-on: ubuntu-24.04 - timeout-minutes: 20 + runs-on: [public-repo] + container: + image: ubuntu:24.04 + options: --user root -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/wp-env:/tmp/wp-env + + timeout-minutes: 30 + + env: + WP_ENV_PORT: 8889 + WP_ENV_TESTS_PORT: 8891 + WP_ENV_HOME: /tmp/wp-env steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git curl sudo unzip jq + + - name: setup Docker + run: | + curl -fsSL https://get.docker.com -o get-docker.sh + sh get-docker.sh + + - name: Configure Docker group permissions + run: | + useradd -m wpuser + SOCK_GID=$(stat -c '%g' /var/run/docker.sock) + groupmod -g $SOCK_GID -o docker + usermod -aG docker wpuser + mkdir -p /tmp/wp-env + chown -R wpuser:wpuser /tmp/wp-env + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Set up PHP uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0 @@ -44,15 +75,43 @@ jobs: - name: Build development assets run: npm run build:dev + - name: Fix wp-env host mapping + run: | + # Get the host path for the workspace by inspecting the container's own mounts + HOST_WORKSPACE_PATH=$(docker inspect $(hostname) --format '{{ range .Mounts }}{{ if eq .Destination "/__w" }}{{ .Source }}{{ end }}{{ end }}') + + # Construct the full host path for the current plugin directory + RELATIVE_PATH=$(pwd | sed 's|^/__w||') + PLUGIN_HOST_PATH="${HOST_WORKSPACE_PATH}${RELATIVE_PATH}" + + echo "Host Workspace: $HOST_WORKSPACE_PATH" + echo "Plugin Host Path: $PLUGIN_HOST_PATH" + + # Update .wp-env.test.json + jq --arg path "$PLUGIN_HOST_PATH" \ + 'del(.plugins) | .mappings["wp-content/plugins/plugin-skeleton-d"] = $path' \ + .wp-env.test.json > .wp-env.test.json.tmp && mv .wp-env.test.json.tmp .wp-env.test.json + + cat .wp-env.test.json + + - name: Fix workspace permissions + run: chown -R wpuser:wpuser . + - name: Start the Docker testing environment uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: - timeout_minutes: 10 + timeout_minutes: 15 max_attempts: 3 - command: WP_ENV_PORT=8889 WP_ENV_TESTS_PORT=8891 npm run wp-env:test start + command: | + sudo -u wpuser git config --global --add safe.directory '/tmp/wp-env/*' + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" "WP_ENV_PORT=$WP_ENV_PORT" "WP_ENV_TESTS_PORT=$WP_ENV_TESTS_PORT" npm run wp-env:test start -- --update + + - name: Activate plugin + run: | + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test run cli -- wp plugin activate plugin-skeleton-d - name: Run E2E tests - run: npm run test:e2e + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run test:e2e -- --debug - name: Upload E2E test results as artifact uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 @@ -62,3 +121,7 @@ jobs: path: tests/_output retention-days: 2 if-no-files-found: ignore + + - name: Stop the Docker testing environment + if: always() + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test destroy -- --force diff --git a/.github/workflows/reusable-jest.yml b/.github/workflows/reusable-jest.yml index 719dc08..e514a9c 100644 --- a/.github/workflows/reusable-jest.yml +++ b/.github/workflows/reusable-jest.yml @@ -9,12 +9,15 @@ on: type: boolean default: true -permissions: {} +permissions: + contents: read jobs: jest: name: Jest Unit Tests${{ inputs.coverage && ' with coverage' || '' }} - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: node:22 timeout-minutes: 10 steps: @@ -22,7 +25,9 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 diff --git a/.github/workflows/reusable-lint-css-js.yml b/.github/workflows/reusable-lint-css-js.yml index c855250..c64166b 100644 --- a/.github/workflows/reusable-lint-css-js.yml +++ b/.github/workflows/reusable-lint-css-js.yml @@ -3,12 +3,15 @@ name: Run JS Lint on: workflow_call: -permissions: {} +permissions: + contents: read jobs: lint-js: name: JS Lint & TypeScript - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: node:22 timeout-minutes: 20 steps: @@ -16,7 +19,9 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 diff --git a/.github/workflows/reusable-phpcs.yml b/.github/workflows/reusable-phpcs.yml index d2a6bc5..2b7b0c1 100644 --- a/.github/workflows/reusable-phpcs.yml +++ b/.github/workflows/reusable-phpcs.yml @@ -8,20 +8,30 @@ on: required: true type: string -permissions: {} +permissions: + contents: read jobs: phpcs: name: PHPCS Coding Standards - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: ubuntu:24.04 timeout-minutes: 20 steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git curl sudo unzip + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Set up PHP uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0 diff --git a/.github/workflows/reusable-phpstan.yml b/.github/workflows/reusable-phpstan.yml index 6701091..9e81f3a 100644 --- a/.github/workflows/reusable-phpstan.yml +++ b/.github/workflows/reusable-phpstan.yml @@ -8,20 +8,30 @@ on: required: true type: string -permissions: {} +permissions: + contents: read jobs: phpstan: name: PHPStan Static Analysis - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: ubuntu:24.04 timeout-minutes: 20 steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git curl sudo unzip + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Set up PHP uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0 diff --git a/.github/workflows/reusable-phpunit.yml b/.github/workflows/reusable-phpunit.yml index 2a990ba..0a6d6c2 100644 --- a/.github/workflows/reusable-phpunit.yml +++ b/.github/workflows/reusable-phpunit.yml @@ -23,18 +23,45 @@ on: type: boolean default: false -permissions: {} +permissions: + contents: read jobs: phpunit: name: PHPUnit (PHP ${{ inputs.php-version }}, WP ${{ inputs.wp-version }})${{ inputs.coverage && ' with coverage' || '' }}${{ inputs.multisite && ' multisite' || '' }} - runs-on: ubuntu-24.04 - timeout-minutes: 20 + runs-on: [public-repo] + container: + image: ubuntu:24.04 + options: --user root -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/wp-env:/tmp/wp-env + + timeout-minutes: 30 + env: WP_ENV_PHP_VERSION: ${{ inputs.php-version }} WP_ENV_CORE: ${{ inputs.wp-version == 'trunk' && 'WordPress/WordPress' || format('https://wordpress.org/wordpress-{0}.zip', inputs.wp-version) }} + WP_ENV_PORT: 8889 + WP_ENV_TESTS_PORT: 8891 + WP_ENV_HOME: /tmp/wp-env steps: + - name: Install system dependencies + run: | + apt update + apt-get install -y git curl sudo unzip jq + + - name: setup Docker + run: | + curl -fsSL https://get.docker.com -o get-docker.sh + sh get-docker.sh + + - name: Configure Docker group permissions + run: | + useradd -m wpuser -s /bin/bash + SOCK_GID=$(stat -c '%g' /var/run/docker.sock) + groupmod -g $SOCK_GID -o docker + usermod -aG docker wpuser + chown -R wpuser:wpuser /tmp/wp-env + - name: Configure environment variables run: | echo "PHP_FPM_UID=$(id -u)" >> "$GITHUB_ENV" @@ -44,7 +71,9 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - persist-credentials: false + + - name: Configure Git for Safe Directory + run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Set up PHP uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0 @@ -67,25 +96,55 @@ jobs: - name: Build development assets run: npm run build:dev + - name: Fix wp-env host mapping + run: | + # Get the host path for the workspace by inspecting the container's own mounts + HOST_WORKSPACE_PATH=$(docker inspect $(hostname) --format '{{ range .Mounts }}{{ if eq .Destination "/__w" }}{{ .Source }}{{ end }}{{ end }}') + + # Construct the full host path for the current plugin directory + # We strip the internal /__w prefix and append it to the host workspace path + RELATIVE_PATH=$(pwd | sed 's|^/__w||') + PLUGIN_HOST_PATH="${HOST_WORKSPACE_PATH}${RELATIVE_PATH}" + + echo "Host Workspace: $HOST_WORKSPACE_PATH" + echo "Plugin Host Path: $PLUGIN_HOST_PATH" + + # 1. Remove the "plugins" field to prevent broken automatic mounts + # 2. Add the host mapping + jq --arg path "$PLUGIN_HOST_PATH" \ + 'del(.plugins) | .mappings["wp-content/plugins/plugin-skeleton-d"] = $path' \ + .wp-env.test.json > .wp-env.test.json.tmp && mv .wp-env.test.json.tmp .wp-env.test.json + + cat .wp-env.test.json + + - name: Fix workspace permissions + run: chown -R wpuser:wpuser . + - name: Start the Docker testing environment uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 with: - timeout_minutes: 10 + timeout_minutes: 15 max_attempts: 3 command: | + sudo -u wpuser git config --global --add safe.directory '/tmp/wp-env/*' if [ "${{ inputs.coverage }}" == "true" ]; then - npm run wp-env:test start -- --xdebug=coverage + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" "WP_ENV_PORT=$WP_ENV_PORT" "WP_ENV_TESTS_PORT=$WP_ENV_TESTS_PORT" npm run wp-env:test start -- --xdebug=coverage --update --debug else - npm run wp-env:test start + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" "WP_ENV_PORT=$WP_ENV_PORT" "WP_ENV_TESTS_PORT=$WP_ENV_TESTS_PORT" npm run wp-env:test start -- --update fi + - name: Activate plugin + run: | + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test run cli -- wp plugin activate plugin-skeleton-d + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test run tests-cli -- wp plugin activate plugin-skeleton-d + - name: Log versions run: | - npm run wp-env:test -- run cli php -- -v - npm run wp-env:test -- run cli wp core version + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test -- run tests-cli php -- -v + sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test -- run tests-cli wp core version - name: Run PHPUnit tests${{ inputs.coverage && ' with coverage report' || '' }} - run: npm run test:php ${{ !inputs.coverage && '-- --no-coverage' || '' }} + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run test:php ${{ !inputs.coverage && '-- --no-coverage' || '' }} - name: Upload code coverage report if: ${{ inputs.coverage }} @@ -103,3 +162,7 @@ jobs: name: wp-code-coverage-${{ inputs.php-version }}-${{ inputs.wp-version }} path: tests/_output/html overwrite: true + + - name: Stop the Docker testing environment + if: always() + run: sudo -u wpuser env "PATH=$PATH" "WP_ENV_HOME=$WP_ENV_HOME" npm run wp-env:test destroy -- --force diff --git a/.github/workflows/reusable-wp-playground-pr-preview.yml b/.github/workflows/reusable-wp-playground-pr-preview.yml index e25a1b1..270166b 100644 --- a/.github/workflows/reusable-wp-playground-pr-preview.yml +++ b/.github/workflows/reusable-wp-playground-pr-preview.yml @@ -23,18 +23,29 @@ on: type: string default: '2' -permissions: {} +permissions: + contents: read jobs: playground-preview: name: Post Playground Preview - runs-on: ubuntu-24.04 + runs-on: [public-repo] + container: + image: ubuntu:24.04 permissions: actions: read contents: write pull-requests: write steps: + - name: Install system dependencies + run: | + apt-get update + apt-get install -y git curl + + # - name: Configure Git for Safe Directory + # run: git config --global --add safe.directory "${GITHUB_WORKSPACE}" + - name: Extract PR metadata and artifact info id: pr-metadata uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 diff --git a/.wp-env.test.json b/.wp-env.test.json index b8f64fd..6297e6e 100644 --- a/.wp-env.test.json +++ b/.wp-env.test.json @@ -2,14 +2,12 @@ "$schema": "https://schemas.wp.org/trunk/wp-env.json", "core": null, "port": 8889, - "testsEnvironment": false, + "testsPort": 8891, + "testsEnvironment": true, "plugins": [ "." ], "config": { "FS_METHOD": "direct", "WP_DEBUG": true, "WP_DEBUG_LOG": "/var/www/html/wp-content/plugins/plugin-skeleton-d/tests/_output/debug-test.log" - }, - "mappings": { - "wp-content/plugins/plugin-skeleton-d": "." } } diff --git a/package.json b/package.json index 65e3422..6411f1b 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "test:js": "wp-scripts test-unit-js", "test:js:watch": "wp-scripts test-unit-js --watch", "test:js:coverage": "wp-scripts test-unit-js --coverage", - "test:php": "npm run wp-env:test -- run cli --env-cwd=wp-content/plugins/$(basename \"$(pwd)\")/ vendor/bin/phpunit -c phpunit.xml.dist", + "test:php": "npm run wp-env:test -- run tests-cli --env-cwd=wp-content/plugins/$(basename \"$(pwd)\")/ vendor/bin/phpunit -c phpunit.xml.dist", "wp-env": "wp-env", "wp-env:cli": "wp-env run cli --env-cwd=wp-content/plugins/$(basename \"$(pwd)\")/", "wp-env:test": "wp-env --config=.wp-env.test.json"