From a0def9463b59effbe6bb97c9aaa2ce6821ece47d Mon Sep 17 00:00:00 2001 From: dongmucat <1127093059@qq.com> Date: Mon, 18 May 2026 16:42:06 +0800 Subject: [PATCH] chore(cli): improve dry-run test fixture and 403 error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix test fixture: warnings-only response now uses valid=false to match real backend behavior (warnings make dry-run invalid) - Distinguish 403 from 401 in CLI error messages: 403 now says "access denied — token may lack required scope" with a hint to regenerate the token, rather than the generic "authentication failed" --- cli/src/clients/skillhub-client.ts | 5 ++++- cli/test/integration/publish-dry-run.test.ts | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cli/src/clients/skillhub-client.ts b/cli/src/clients/skillhub-client.ts index c1ff5fe3..14e14ec3 100644 --- a/cli/src/clients/skillhub-client.ts +++ b/cli/src/clients/skillhub-client.ts @@ -151,9 +151,12 @@ export class SkillHubClient { } private async handleJsonResponse(response: Response): Promise { - if (response.status === 401 || response.status === 403) { + if (response.status === 401) { throw new CliError('authentication failed', EXIT.auth, { registry: this.registry, next: 'run `skillhub login`' }) } + if (response.status === 403) { + throw new CliError('access denied — token may lack required scope', EXIT.auth, { registry: this.registry, next: 'regenerate token with required scopes or run `skillhub login`' }) + } if (response.status === 404) { throw new CliError('resource not found', EXIT.generic, { registry: this.registry }) } diff --git a/cli/test/integration/publish-dry-run.test.ts b/cli/test/integration/publish-dry-run.test.ts index bc2deb13..7a44b779 100644 --- a/cli/test/integration/publish-dry-run.test.ts +++ b/cli/test/integration/publish-dry-run.test.ts @@ -50,12 +50,12 @@ describe('publish --dry-run', () => { expect(registry.received.publish).toBeNull() }) - test('--dry-run with --json returns structured response', async () => { + test('--dry-run with --json returns structured response on warnings (valid=false)', async () => { const env = await createTempHome() registry = await startFakeRegistry({ token: 'sk_ok', dryRunResponse: { - valid: true, + valid: false, errors: [], warnings: ['Disallowed file extension: data.bin'], resolvedSlug: 'my-skill', @@ -70,9 +70,9 @@ describe('publish --dry-run', () => { USERPROFILE: env.home }) - expect(result.exitCode).toBe(0) + expect(result.exitCode).toBe(6) const json = JSON.parse(result.stdout) - expect(json.valid).toBe(true) + expect(json.valid).toBe(false) expect(json.resolvedSlug).toBe('my-skill') expect(json.resolvedVersion).toBe('2.0.0') expect(json.warnings).toContain('Disallowed file extension: data.bin')