From 4680f5c69666368ec68e8fd7dfdc992ff7ce9768 Mon Sep 17 00:00:00 2001 From: Sertii <36940685+Sreini@users.noreply.github.com> Date: Mon, 16 Feb 2026 07:34:38 +0100 Subject: [PATCH 1/9] release: 3.6.10 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 565e7c67..aa6e9ea1 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://tinypng.com/ Tags: compress images, compression, image size, page speed, performance Requires at least: 4.0 Tested up to: 6.9 -Stable tag: 3.6.9 +Stable tag: 3.6.10 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From d23e81589a6d51997a7b33d28ad57eb9d427cc11 Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:11:53 +0100 Subject: [PATCH 2/9] wait for docker compose to boot --- bin/run-mocks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/run-mocks b/bin/run-mocks index cf2fbc87..7f591b90 100755 --- a/bin/run-mocks +++ b/bin/run-mocks @@ -2,7 +2,7 @@ port="$1" -docker compose -f config/mocks.docker-compose.yml up -d +docker compose -f config/mocks.docker-compose.yml up -d --wait mv src/vendor/tinify/Tinify/Client.php src/vendor/tinify/Tinify/Client.php.bak cp test/fixtures/Client.php src/vendor/tinify/Tinify/Client.php From 91f1cd664d0986bd6eb9050b715116dba54676f9 Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:21:08 +0100 Subject: [PATCH 3/9] add cache for mock api image --- .github/workflows/integration-tests.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 132cc1b4..a7b73833 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -32,6 +32,19 @@ jobs: node-version: 18 cache: 'npm' + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build Mock Image + uses: docker/build-push-action@v7 + with: + context: . + file: ./config/Dockerfile-mock-webservice + tags: tinify-mock-api:latest + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Cache node_modules uses: actions/cache@v4 with: @@ -57,7 +70,6 @@ jobs: - run: npx playwright install --with-deps if: steps.playwright-cache.outputs.cache-hit != 'true' - - name: Start WordPress uses: nick-fields/retry@v3 with: From 6ea063973ccdfa5eaae80b917bbb7f7fe888041b Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:28:33 +0100 Subject: [PATCH 4/9] fix(ci): cache localstack Docker image in GitHub Actions --- .github/workflows/integration-tests.yml | 10 ++++++++++ config/Dockerfile-localstack | 1 + 2 files changed, 11 insertions(+) create mode 100644 config/Dockerfile-localstack diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a7b73833..3250650b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -45,6 +45,16 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Cache Localstack Image + uses: docker/build-push-action@v7 + with: + context: . + file: ./config/Dockerfile-localstack + tags: localstack/localstack:latest + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Cache node_modules uses: actions/cache@v4 with: diff --git a/config/Dockerfile-localstack b/config/Dockerfile-localstack new file mode 100644 index 00000000..485c03a7 --- /dev/null +++ b/config/Dockerfile-localstack @@ -0,0 +1 @@ +FROM localstack/localstack From 7d3d0b5bdc770eb4ff3e9f74dce25fdc0aae80cd Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:35:38 +0100 Subject: [PATCH 5/9] remove e2e for s3 offload and dependencies --- .github/workflows/integration-tests.yml | 11 -- config/Dockerfile-localstack | 1 - config/docker-compose.yml | 6 - config/localstack-init.sh | 3 - config/mocks.docker-compose.yml | 9 -- test/fixtures/class-tiny-config.php | 21 ---- test/integration/compatibility.spec.ts | 156 ------------------------ test/integration/utils.ts | 12 -- 8 files changed, 219 deletions(-) delete mode 100644 config/Dockerfile-localstack delete mode 100755 config/localstack-init.sh delete mode 100644 test/integration/compatibility.spec.ts diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 3250650b..59c8dc0c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -45,16 +45,6 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - - name: Cache Localstack Image - uses: docker/build-push-action@v7 - with: - context: . - file: ./config/Dockerfile-localstack - tags: localstack/localstack:latest - load: true - cache-from: type=gha - cache-to: type=gha,mode=max - - name: Cache node_modules uses: actions/cache@v4 with: @@ -95,7 +85,6 @@ jobs: run: npm run test:playwright env: WORDPRESS_PORT: 80${{ matrix.wp }} - PHP_VERSION: ${{ matrix.php }} - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} diff --git a/config/Dockerfile-localstack b/config/Dockerfile-localstack deleted file mode 100644 index 485c03a7..00000000 --- a/config/Dockerfile-localstack +++ /dev/null @@ -1 +0,0 @@ -FROM localstack/localstack diff --git a/config/docker-compose.yml b/config/docker-compose.yml index 69233cba..775f9238 100755 --- a/config/docker-compose.yml +++ b/config/docker-compose.yml @@ -29,12 +29,6 @@ services: WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress WORDPRESS_DEBUG: '1' - AWS_ENDPOINT: http://localstack:4566 - AWS_USE_PATH_STYLE_ENDPOINT: true - AWS_ACCESS_KEY_ID: test_key_id - AWS_SECRET_ACCESS_KEY: test_secret_access_key - AWS_REGION: eu-central-1 - AWS_DEFAULT_REGION: eu-central-1 volumes: - wordpress_data:/var/www/html - ../:/var/www/html/wp-content/plugins/tiny-compress-images diff --git a/config/localstack-init.sh b/config/localstack-init.sh deleted file mode 100755 index d2a53e73..00000000 --- a/config/localstack-init.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -awslocal s3 mb s3://tinytest - diff --git a/config/mocks.docker-compose.yml b/config/mocks.docker-compose.yml index f09e150f..ee094854 100755 --- a/config/mocks.docker-compose.yml +++ b/config/mocks.docker-compose.yml @@ -1,13 +1,4 @@ services: - localstack: - image: localstack/localstack - volumes: - - './localstack-init.sh:/etc/localstack/init/ready.d/init-aws.sh' - ports: - - 4566:4566 - networks: - - tinify - tinify-mock-api: image: tinify-mock-api build: diff --git a/test/fixtures/class-tiny-config.php b/test/fixtures/class-tiny-config.php index a28419f7..4c748efb 100644 --- a/test/fixtures/class-tiny-config.php +++ b/test/fixtures/class-tiny-config.php @@ -3,10 +3,6 @@ if (! defined('TINY_DEBUG')) { define('TINY_DEBUG', null); } -define('AWS_REGION', getenv('AWS_REGION')); -define('AWS_ENDPOINT', getenv('AWS_ENDPOINT')); -define('AWS_ACCESS_KEY_ID', getenv('AWS_ACCESS_KEY_ID')); -define('AWS_SECRET_ACCESS_KEY', getenv('AWS_SECRET_ACCESS_KEY')); class Tiny_Config { @@ -17,23 +13,6 @@ class Tiny_Config const META_KEY = 'tiny_compress_images'; } -/** - * Filter for adding arguments to the AS3CF AWS client. - * Required to point the client to the LocalStack instance. - */ -add_filter('as3cf_aws_init_client_args', function ($args) { - $args['endpoint'] = AWS_ENDPOINT; - $args['use_path_style_endpoint'] = true; - $args['region'] = AWS_REGION; - return $args; -}); - -// Force all S3 URLs to use LocalStack instead of s3.amazonaws.com -add_filter('as3cf_aws_s3_url_domain', function ($domain, $bucket, $region, $expires, $args) { - // Replace any AWS domain with LocalStack - return AWS_ENDPOINT . '/' . $bucket; -}, 10, 5); - // ajax hook to delete all attachments as doing it via UI is flaky add_action( 'wp_ajax_clear_media_library', 'clear_media_library' ); function clear_media_library() { diff --git a/test/integration/compatibility.spec.ts b/test/integration/compatibility.spec.ts deleted file mode 100644 index 17f015c0..00000000 --- a/test/integration/compatibility.spec.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Page, expect, test } from '@playwright/test'; -import { activatePlugin, clearMediaLibrary, deactivatePlugin, enableCompressionSizes, getPHPVersion, getWPVersion, setAPIKey, setCompressionTiming, uploadMedia } from './utils'; - -test.describe.configure({ mode: 'serial' }); - -const TEST_BUCKETNAME = 'tinytest'; -let WPVersion = 0; - -async function setRemoveLocalMedia(page: Page, enabled: boolean) { - await page.goto('/wp-admin/options-general.php?page=amazon-s3-and-cloudfront'); - - const cfgRemoveLocal = await page.getByLabel('Remove Local Media').isChecked(); - if (cfgRemoveLocal && enabled) { - // should enable but is already enabled - return; - } - if (!cfgRemoveLocal && !enabled) { - // should disable but is already disabled - return; - } - - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/state/') && resp.status() === 200), - page.locator('label[for="remove-local-file"]').click(), - ]); - - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/settings/') && resp.status() === 200), - page.getByRole('button', { name: 'Save Changes' }).click() - ]); -} - -test.describe('as3cf', () => { - let page: Page; - - test.beforeAll(async ({ browser }) => { - page = await browser.newPage(); - WPVersion = await getWPVersion(page); - const phpVersion = getPHPVersion(); - - if (WPVersion < 5.9) { - // Skipping test as it WP Offload does not support WordPress < 5.9 - test.skip(); - return; - } - - if (phpVersion < 81) { - // Skipping test as WP Offload Media requires PHP 8.1+ - test.skip(); - return; - } - - await activatePlugin(page, 'amazon-s3-and-cloudfront'); - - await page.goto('/wp-admin/options-general.php?page=amazon-s3-and-cloudfront'); - - const isConfigured = await page.getByText('Storage provider is successfully connected and ready to offload new media.').isVisible(); - if (!isConfigured) { - await page.getByText('Enter bucket name').click(); - await page.getByPlaceholder('Enter bucket name…').fill(TEST_BUCKETNAME); - await Promise.all([ - page.waitForResponse((resp) => resp.url().includes('/wp-offload-media/v1/settings/') && resp.status() === 200), - page.getByRole('button', { name: 'Save Bucket Settings' }).click(), - ]); - } - - await setRemoveLocalMedia(page, false); - - await setAPIKey(page, 'JPG123'); - await enableCompressionSizes(page, [], true); - await setCompressionTiming(page, 'auto'); - }); - - test.afterAll(async () => { - await deactivatePlugin(page, 'amazon-s3-and-cloudfront'); - await page.close(); - }); - - test('does not show notification when local media is preserved', async () => { - await setRemoveLocalMedia(page, false); - - await page.goto('/wp-admin/options-general.php?page=tinify'); - - await expect(page.getByText(' configure WP Offload')).not.toBeVisible(); - }); - - test('shows notification when local media is not preserved', async () => { - await setCompressionTiming(page, 'background'); - await setRemoveLocalMedia(page, true); - - await page.goto('/wp-admin/options-general.php?page=tinify'); - - await expect(page.getByText(' configure WP Offload')).toBeVisible(); - }); - - test('compress image before offloading', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'auto'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size compressed')).toBeVisible(); - }); - - test('compress image asynchronously', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'background'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size compressed')).toBeVisible(); - }); - - test('compress images manually', async ({ page }) => { - await setRemoveLocalMedia(page, false); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'manual'); - await enableCompressionSizes(page, ['0'], false); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - await page.getByLabel('“input-example” (Edit)').click(); - - const imageURL = await page.locator('#attachment_url').inputValue(); - await expect(imageURL).toContain(TEST_BUCKETNAME); - await expect(page.getByText('1 size to be compressed')).toBeVisible(); - }); - - test('does not show compression button if image is not available locally', async ({ page }) => { - // Currently, we cannot support compression of images that are not available locally. - await setRemoveLocalMedia(page, true); - await clearMediaLibrary(page); - await setCompressionTiming(page, 'manual'); - - await uploadMedia(page, 'input-example.jpg'); - - await page.goto('/wp-admin/upload.php?mode=list'); - - await expect(page.getByRole('button', { name: 'Compress', exact: true })).not.toBeVisible(); - }); -}); diff --git a/test/integration/utils.ts b/test/integration/utils.ts index 01640e24..25ca8fd3 100644 --- a/test/integration/utils.ts +++ b/test/integration/utils.ts @@ -160,18 +160,6 @@ export async function getWPVersion(page: Page): Promise { return parsedText; } -/** - * @returns {number} retrieves the current PHP version from environment variable - */ -export function getPHPVersion(): number { - const { PHP_VERSION } = process.env; - if (!PHP_VERSION) { - throw Error('PHP_VERSION is not set'); - } - - return +PHP_VERSION; -} - /** * @param {Page} page context * @param {string} pluginSlug slug of the plugin, ex 'tiny-compress-images' From baf51054ca3c80f5b8c1247db3a982670b42ca11 Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:56:24 +0100 Subject: [PATCH 6/9] exit on error when running mocks --- bin/run-mocks | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/run-mocks b/bin/run-mocks index 7f591b90..3aef15fe 100755 --- a/bin/run-mocks +++ b/bin/run-mocks @@ -1,4 +1,5 @@ #!/bin/bash +set -e port="$1" From ae68386a1d63be02e95e9aa6cfb0660e03ab9098 Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 09:56:57 +0100 Subject: [PATCH 7/9] add healthcheck to mock api --- config/mocks.docker-compose.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/mocks.docker-compose.yml b/config/mocks.docker-compose.yml index ee094854..7c5b4e3c 100755 --- a/config/mocks.docker-compose.yml +++ b/config/mocks.docker-compose.yml @@ -8,6 +8,11 @@ services: - '8100:80' volumes: - ../test/mock-tinypng-webservice:/var/www/html + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/"] + interval: 5s + timeout: 3s + retries: 3 networks: - tinify From 414a247698583afba4e8b030ac5995d299fff78e Mon Sep 17 00:00:00 2001 From: tijmen Date: Fri, 27 Mar 2026 10:15:48 +0100 Subject: [PATCH 8/9] add plain index --- test/mock-tinypng-webservice/index.php | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/mock-tinypng-webservice/index.php diff --git a/test/mock-tinypng-webservice/index.php b/test/mock-tinypng-webservice/index.php new file mode 100644 index 00000000..b3d9bbc7 --- /dev/null +++ b/test/mock-tinypng-webservice/index.php @@ -0,0 +1 @@ + Date: Fri, 27 Mar 2026 10:27:25 +0100 Subject: [PATCH 9/9] Remove plugins from wp boot --- bin/run-wordpress | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bin/run-wordpress b/bin/run-wordpress index 770592cd..30a7186d 100755 --- a/bin/run-wordpress +++ b/bin/run-wordpress @@ -93,11 +93,6 @@ EOF echo "Activating tinify.." docker compose -f config/docker-compose.yml run --rm wpcli wp plugin activate tiny-compress-images --allow-root -if [ "$WORDPRESS_VERSION_ENV" -ge 55 ]; then - echo "Installing compatible plugins for WordPress ${WORDPRESS_PORT}.." - docker compose -f config/docker-compose.yml run --rm --user 33 wpcli wp plugin install amazon-s3-and-cloudfront --activate --allow-root || exit 1 -fi - MAX_ATTEMPTS=10 ATTEMPT=0 until curl -s --head --fail "http://localhost:${WORDPRESS_PORT}" >/dev/null; do