From e92dbf23228827dc418f168edb958cc2a53ab87d Mon Sep 17 00:00:00 2001 From: Aryan Kumar Date: Fri, 28 Aug 2026 14:46:56 +0530 Subject: [PATCH 1/2] fix(sdk-utils): drop the CLI major-version gate that blocks 2.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isPercyEnabled() disabled snapshots whenever the CLI's major was not exactly 1: if (percy.enabled && percy.version.major !== 1) { log.info('Unsupported Percy CLI version, disabling snapshots'); Against a 2.x CLI that means capture silently stops. The build still passes, with zero snapshots and a single info log as the only signal — the worst shape a failure can take. The check came in on 2020-10-19 with this package (#63) as `getInfo.version[0] !== 1`, at the CLI 1.0 cutover from the legacy 0.x @percy/agent, whose protocol predates /percy/healthcheck. The retained test pinned 0.1.0, which is the fingerprint of that intent. It was written as a floor when nothing above 1 existed, and only reads as a ceiling because it used !== rather than >=. The 0.x agent is long gone, so it guards nothing and blocks the next major. percy.version stays populated for SDKs that read it. Replaces the old spec with two: a 2.x CLI must stay enabled (the regression guard for exactly this), and 0.x is no longer special-cased. Verified: 170/170 specs, 100% coverage, node and karma suites. Note this only covers the nine JS SDKs, and only once they upgrade. The 16 non-JS SDKs each carry their own hardcoded copy of the same check, so a 2.0.0 CLI is not safe until those are fixed and adopted too. Co-Authored-By: Claude Opus 5 (1M context) --- packages/sdk-utils/src/percy-enabled.js | 13 ++++++++----- packages/sdk-utils/test/index.test.js | 20 +++++++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/sdk-utils/src/percy-enabled.js b/packages/sdk-utils/src/percy-enabled.js index 02218e003..56ae67a6f 100644 --- a/packages/sdk-utils/src/percy-enabled.js +++ b/packages/sdk-utils/src/percy-enabled.js @@ -22,11 +22,14 @@ export async function isPercyEnabled() { error = e; } - if (percy.enabled && percy.version.major !== 1) { - log.info('Unsupported Percy CLI version, disabling snapshots'); - log.debug(`Found version: ${percy.version}`); - percy.enabled = false; - } else if (!percy.enabled) { + // No CLI major-version gate here. The original check (added Oct 2020 with + // this package) was `version[0] !== 1`, written to refuse the legacy 0.x + // @percy/agent whose protocol predates /percy/healthcheck. Nothing above 1 + // existed then, so it was meant as a floor but reads as a ceiling: it + // silently disables snapshots against any CLI 2.x+. The 0.x agent has been + // gone for years, so the guard protects nothing and only blocks the next + // major. `percy.version` stays populated for SDKs that want to read it. + if (!percy.enabled) { log.info('Percy is not running, disabling snapshots'); log.debug(error); } diff --git a/packages/sdk-utils/test/index.test.js b/packages/sdk-utils/test/index.test.js index e3dbf6a13..23317e6b9 100644 --- a/packages/sdk-utils/test/index.test.js +++ b/packages/sdk-utils/test/index.test.js @@ -104,15 +104,25 @@ describe('SDK Utils', () => { ])); }); - it('disables snapshots when the API version is unsupported', async () => { - await helpers.test('version', '0.1.0'); - await expectAsync(isPercyEnabled()).toBeResolvedTo(false); + it('stays enabled against a next-major CLI', async () => { + // Replaces the old `major !== 1` gate, which disabled snapshots against + // any CLI 2.x+. This is the regression guard for that: a future major + // must not silently turn capture off. + await helpers.test('version', '2.0.0'); + await expectAsync(isPercyEnabled()).toBeResolvedTo(true); - expect(helpers.logger.stdout).toEqual(jasmine.arrayContaining([ - '[percy] Unsupported Percy CLI version, disabling snapshots' + expect(helpers.logger.stdout).not.toEqual(jasmine.arrayContaining([ + jasmine.stringMatching(/Unsupported Percy CLI version/) ])); }); + it('stays enabled against a 0.x CLI', async () => { + // The gate was originally aimed at the legacy 0.x @percy/agent. That + // agent is long gone, so 0.x is no longer special-cased either. + await helpers.test('version', '0.1.0'); + await expectAsync(isPercyEnabled()).toBeResolvedTo(true); + }); + it('returns false if the build fails during a snapshot', async () => { await helpers.test('error', '/percy/snapshot'); await helpers.test('build-failure'); From d53abed89965428bd04d92812827ba192bf309df Mon Sep 17 00:00:00 2001 From: Aryan Kumar Date: Fri, 28 Aug 2026 17:39:29 +0530 Subject: [PATCH 2/2] style: drop the explanatory comments; rationale lives in the PR --- packages/sdk-utils/src/percy-enabled.js | 7 ------- packages/sdk-utils/test/index.test.js | 5 ----- 2 files changed, 12 deletions(-) diff --git a/packages/sdk-utils/src/percy-enabled.js b/packages/sdk-utils/src/percy-enabled.js index 56ae67a6f..5e015986a 100644 --- a/packages/sdk-utils/src/percy-enabled.js +++ b/packages/sdk-utils/src/percy-enabled.js @@ -22,13 +22,6 @@ export async function isPercyEnabled() { error = e; } - // No CLI major-version gate here. The original check (added Oct 2020 with - // this package) was `version[0] !== 1`, written to refuse the legacy 0.x - // @percy/agent whose protocol predates /percy/healthcheck. Nothing above 1 - // existed then, so it was meant as a floor but reads as a ceiling: it - // silently disables snapshots against any CLI 2.x+. The 0.x agent has been - // gone for years, so the guard protects nothing and only blocks the next - // major. `percy.version` stays populated for SDKs that want to read it. if (!percy.enabled) { log.info('Percy is not running, disabling snapshots'); log.debug(error); diff --git a/packages/sdk-utils/test/index.test.js b/packages/sdk-utils/test/index.test.js index 23317e6b9..11ad23782 100644 --- a/packages/sdk-utils/test/index.test.js +++ b/packages/sdk-utils/test/index.test.js @@ -105,9 +105,6 @@ describe('SDK Utils', () => { }); it('stays enabled against a next-major CLI', async () => { - // Replaces the old `major !== 1` gate, which disabled snapshots against - // any CLI 2.x+. This is the regression guard for that: a future major - // must not silently turn capture off. await helpers.test('version', '2.0.0'); await expectAsync(isPercyEnabled()).toBeResolvedTo(true); @@ -117,8 +114,6 @@ describe('SDK Utils', () => { }); it('stays enabled against a 0.x CLI', async () => { - // The gate was originally aimed at the legacy 0.x @percy/agent. That - // agent is long gone, so 0.x is no longer special-cased either. await helpers.test('version', '0.1.0'); await expectAsync(isPercyEnabled()).toBeResolvedTo(true); });