diff --git a/.github/actions/auth-gcp/action.yml b/.github/actions/auth-gcp/action.yml new file mode 100644 index 000000000..f5ecb6776 --- /dev/null +++ b/.github/actions/auth-gcp/action.yml @@ -0,0 +1,68 @@ +name: 'Auth GCP' +description: 'Auth gcp, can login to docker artifact registry or install the sdk' +inputs: + registry-login: + required: false + type: bool + default: false + setup-gcloud: + required: false + type: bool + default: false + service-account: + required: true + description: Service account email + type: string + provider: + required: true + description: gcp workload identity provider + type: string + gcp-registry-region: + required: false + description: docker registry gcp + default: "europe-west1-docker.pkg.dev" + type: string + sdk-version: + required: false + description: which version of google dsl you want to suer + default: '>=457.0.0' + type: string + gke-cluster-name: + required: false + description: 'If you put the cluster name in this variable it will activate auth to make kubectl' + default: '' + type: string + cluster-region: + required: false + description: 'Cluster region' + type: choice + options: + - europe-west1 + default: 'europe-west1' + +runs: + using: 'composite' + steps: + - name: Authenticate to Google Cloud with Workload Federation 🔐 + uses: google-github-actions/auth@v2 + with: + workload_identity_provider: ${{ inputs.provider }} + service_account: ${{ inputs.service-account }} + + - name: Setting up gcloud SDK 🛠 + if: ${{ inputs.setup-gcloud == 'true' }} + uses: google-github-actions/setup-gcloud@v2 + with: + version: ${{ inputs.sdk-version }} + + - name: Login to Docker artifact registry 🐳 + if: ${{ inputs.registry-login == 'true' }} + shell: bash + run: gcloud auth configure-docker ${{ inputs.gcp-registry-region }} + + - name: Add cluster authentification 🧊 + if: ${{ inputs.gke-cluster-name != '' }} + uses: 'google-github-actions/get-gke-credentials@v2' + with: + cluster_name: '${{ inputs.gke-cluster-name }}' + location: '${{ inputs.cluster-region }}' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..64be4c072 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,135 @@ +name: CI - PHPUnit Tests + +on: + pull_request: + types: [opened, synchronize, reopened, labeled] + branches: + - '**' + +jobs: + tests: + name: Tests - ${{ matrix.module }} (PS ${{ matrix.ps-version }}) + runs-on: ubuntu-latest + if: contains(github.event.pull_request.labels.*.name, 'ready to review') + + strategy: + fail-fast: false + matrix: + include: + - module: ps17 + ps-version: '1.7.7.0' + php-version: '7.2' + - module: ps8 + ps-version: '8.1.5' + php-version: '8.1' + - module: ps9 + ps-version: '9.0.0' + php-version: '8.4' + + services: + mysql: + image: mariadb:10.9.4 + env: + MYSQL_ROOT_PASSWORD: prestashop + MYSQL_DATABASE: prestashop + options: >- + --health-cmd="mysqladmin ping -h127.0.0.1 -uroot -pprestashop --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Pull PrestaShop Docker image + run: docker pull prestashop/prestashop:${{ matrix.ps-version }} + + - name: Start PrestaShop container + run: | + docker run -tid --rm \ + --name prestashop-${{ matrix.module }} \ + --network ${{ job.container.network }} \ + -e DB_SERVER=mysql \ + -e DB_NAME=prestashop \ + -e DB_USER=root \ + -e DB_PASSWD=prestashop \ + -e PS_INSTALL_AUTO=1 \ + prestashop/prestashop:${{ matrix.ps-version }} + + - name: Wait for PrestaShop to be ready + run: | + timeout 60 bash -c 'until docker exec prestashop-${{ matrix.module }} test -f /var/www/html/config/config.inc.php 2>/dev/null || docker exec prestashop-${{ matrix.module }} test -f /var/www/html/app/config/parameters.php 2>/dev/null; do sleep 2; done' || true + sleep 5 + + - name: Copy module to PrestaShop + run: | + docker cp ${{ matrix.module }}/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/ + + - name: Install Composer + run: | + docker exec prestashop-${{ matrix.module }} bash -c "curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer" + + - name: Install Composer dependencies in container + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && composer install --no-interaction --prefer-dist" + + - name: Copy monorepo directories to module vendor + run: | + docker exec prestashop-${{ matrix.module }} bash -c "mkdir -p /var/www/html/modules/ps_checkout/vendor/invertus" + docker cp api/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/vendor/invertus/api/ + docker cp core/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/vendor/invertus/core/ + docker cp infrastructure/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/vendor/invertus/infrastructure/ + docker cp presentation/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/vendor/invertus/presentation/ + docker cp utility/. prestashop-${{ matrix.module }}:/var/www/html/modules/ps_checkout/vendor/invertus/utility/ + + - name: Run Infrastructure Unit Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/infrastructure/tests/phpunit.xml \ + --bootstrap=vendor/invertus/infrastructure/tests/bootstrap.php" + + - name: Run Utility Unit Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/utility/tests/phpunit.xml \ + --bootstrap=vendor/invertus/utility/tests/bootstrap.php" + + - name: Run Core Unit Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/core/tests/phpunit.xml \ + --bootstrap=vendor/invertus/core/tests/bootstrap.php" + + - name: Run Presentation Unit Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/presentation/tests/phpunit.xml \ + --bootstrap=vendor/invertus/presentation/tests/bootstrap.php" + + - name: Install module and Create testing database for Integration tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html && php bin/console prestashop:module install ps_checkout" + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php -d display_errors=1 -d error_reporting=E_ALL tests/create-test-database.php" + + - name: Run Infrastructure Integration Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/infrastructure/tests/phpunit-integration.xml \ + --bootstrap=vendor/invertus/infrastructure/tests/bootstrap-integration.php" + + - name: Run Core Integration Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=vendor/invertus/core/tests/phpunit-integration.xml \ + --bootstrap=vendor/invertus/core/tests/bootstrap-integration.php" + + - name: Run Module Integration Tests + run: | + docker exec prestashop-${{ matrix.module }} bash -c "cd /var/www/html/modules/ps_checkout && php vendor/bin/phpunit \ + --configuration=tests/phpunit-integration.xml \ + --bootstrap=tests/bootstrap-integration.php" + + - name: Cleanup + if: always() + run: docker stop prestashop-${{ matrix.module }} || true \ No newline at end of file diff --git a/.github/workflows/create-testing-zip.yml b/.github/workflows/create-testing-zip.yml new file mode 100644 index 000000000..c40165623 --- /dev/null +++ b/.github/workflows/create-testing-zip.yml @@ -0,0 +1,147 @@ +name: Create module ZIP (INT/PREPROD) + +on: + pull_request: + types: [edited, labeled, synchronize] + +jobs: + generate-shared-date: + name: Generate shared date for all matrix jobs + runs-on: ubuntu-latest + if: | + contains(github.event.pull_request.labels.*.name, 'preproduction deployment') || + contains(github.event.pull_request.labels.*.name, 'integration deployment') + outputs: + shared_date: ${{ steps.date.outputs.date }} + steps: + - name: Generate shared date + id: date + run: | + date=$(date -d '+2 hours' +'%Y-%m-%d_%H-%M-%S') + echo "date=$date" >> $GITHUB_OUTPUT + + prepare-zip: + needs: [generate-shared-date] + name: Prepare module ZIP artifacts + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + pull-requests: write + + strategy: + matrix: + module: + - { dir: ps8, suffix: 8 } + - { dir: ps17, suffix: 7 } + - { dir: ps9, suffix: 9 } + + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.12.0 + with: + access_token: ${{ github.token }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Determine Environment + id: environment + run: | + # Get all labels as a JSON array and extract names + LABELS_JSON='${{ toJSON(github.event.pull_request.labels) }}' + echo "Labels JSON: $LABELS_JSON" + + # Extract label names using jq + LABEL_NAMES=$(echo "$LABELS_JSON" | jq -r '.[].name' | tr '\n' ' ') + + if echo "$LABEL_NAMES" | grep -q "integration deployment"; then + echo "environment=integration" >> $GITHUB_OUTPUT + echo "provider_secret=WI_PROVIDER_V2_INTEGRATION" >> $GITHUB_OUTPUT + echo "sa_secret=WI_SA_V2_INTEGRATION" >> $GITHUB_OUTPUT + echo "gcp_project_secret=GCP_PROJECT_INTEGRATION" >> $GITHUB_OUTPUT + echo "Detected integration environment" + elif echo "$LABEL_NAMES" | grep -q "preproduction deployment"; then + echo "environment=preproduction" >> $GITHUB_OUTPUT + echo "provider_secret=WI_PROVIDER_V2_PREPRODUCTION" >> $GITHUB_OUTPUT + echo "sa_secret=WI_SA_V2_PREPRODUCTION" >> $GITHUB_OUTPUT + echo "gcp_project_secret=GCP_PROJECT_PREPRODUCTION" >> $GITHUB_OUTPUT + echo "Detected preproduction environment" + else + echo "No matching labels found. Available labels: $LABEL_NAMES" + exit 1 + fi + + - name: Auth GCP 🔑 + uses: ./.github/actions/auth-gcp + with: + provider: ${{ secrets[steps.environment.outputs.provider_secret] }} + service-account: ${{ secrets[steps.environment.outputs.sa_secret] }} + registry-login: true + setup-gcloud: true + + - name: Write .env file 🌳 + run: gcloud --quiet beta secrets versions access latest --project=$GCP_PROJECT --secret="module-env" > .env + env: + GCP_PROJECT: ${{ secrets[steps.environment.outputs.gcp_project_secret] }} + + - name: Install Composer + run: | + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + php composer-setup.php + php -r "unlink('composer-setup.php');" + sudo mv composer.phar /usr/local/bin/composer + + - name: Install Composer Dev Dependencies (for monorepo) + run: | + echo "Installing root-level dev dependencies" + composer install --prefer-dist --optimize-autoloader + + - name: Prepare and Package Module + run: | + MODULE_NAME=${{ matrix.module.dir }} + FINAL_NAME=ps_checkout + VERSION_SUFFIX=${{ matrix.module.suffix }} + + echo "Preparing module: $MODULE_NAME (suffix: $VERSION_SUFFIX)" + + cd $MODULE_NAME + composer install --no-dev --prefer-dist --optimize-autoloader + cd .. + + mkdir -p $MODULE_NAME/vendor/invertus + cp -r api core infrastructure presentation utility $MODULE_NAME/vendor/invertus/ + + rm -rf $MODULE_NAME/.php-cs-fixer.dist.php \ + $MODULE_NAME/tests \ + $MODULE_NAME/vendor/tests \ + $MODULE_NAME/.php-cs-fixer.cache + + find $MODULE_NAME -type f -name "monorepo.json" -delete + for dir in api core infrastructure presentation utility; do + rm -rf $MODULE_NAME/vendor/invertus/$dir/tests + done + + mkdir -p tmp_package/$FINAL_NAME + cp -r $MODULE_NAME/* tmp_package/$FINAL_NAME/ + cp -r $MODULE_NAME/.htaccess tmp_package/$FINAL_NAME/ || true + cp -r $MODULE_NAME/.well-known tmp_package/$FINAL_NAME/ || true + cp -r .env tmp_package/$FINAL_NAME/.env || true + + cd tmp_package + zip -r ../${FINAL_NAME}.${VERSION_SUFFIX}.zip $FINAL_NAME + cd .. + rm -rf tmp_package + + - name: Generate GCP bucket filename + id: bucket-filename + run: | + echo "filename=pr${{ github.event.pull_request.number }}/ps_checkout-${{ matrix.module.suffix }}-${{ steps.environment.outputs.environment }}-${{ github.event.pull_request.number }}-${{ needs.generate-shared-date.outputs.shared_date }}.zip" >> $GITHUB_OUTPUT + + - name: Upload directly to GCP bucket storage + run: | + FINAL_NAME=ps_checkout + VERSION_SUFFIX=${{ matrix.module.suffix }} + + # Upload the zip file directly to GCP bucket + gsutil cp ${FINAL_NAME}.${VERSION_SUFFIX}.zip gs://ps-eu-w1-checkout-assets-${{ steps.environment.outputs.environment }}/${{ steps.bucket-filename.outputs.filename }} \ No newline at end of file diff --git a/core/tests/Unit/PayPal/OAuth/OAuthServiceTest.php b/core/tests/Unit/PayPal/OAuth/OAuthServiceTest.php index 31c1303a0..50f326c5a 100644 --- a/core/tests/Unit/PayPal/OAuth/OAuthServiceTest.php +++ b/core/tests/Unit/PayPal/OAuth/OAuthServiceTest.php @@ -39,7 +39,8 @@ class OAuthServiceTest extends TestCase /** @var StreamInterface|MockObject */ private $stream; - private OAuthService $oauthService; + /** @var OAuthService */ + private $oauthService; protected function setUp(): void { diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php index 37bce480e..2d1b709e7 100644 --- a/core/tests/bootstrap.php +++ b/core/tests/bootstrap.php @@ -35,5 +35,9 @@ } if (!defined('_PS_VERSION_')) { - define('_PS_VERSION_', AppKernel::VERSION); + if (class_exists('AppKernel')) { + define('_PS_VERSION_', AppKernel::VERSION); + } else { + define('_PS_VERSION_', '1.7'); + } } diff --git a/core/tests/create-test-database.php b/core/tests/create-test-database.php index 42e5d6f1f..be2dad79f 100644 --- a/core/tests/create-test-database.php +++ b/core/tests/create-test-database.php @@ -1,24 +1,12 @@