Skip to content

Add public API commands#58

Merged
satvik007 merged 37 commits intomainfrom
dev/ram/public-api
Apr 10, 2026
Merged

Add public API commands#58
satvik007 merged 37 commits intomainfrom
dev/ram/public-api

Conversation

@ramilamparo
Copy link
Copy Markdown
Collaborator

@ramilamparo ramilamparo commented Mar 18, 2026

Summary

Adds a new qasphere api command that provides direct CLI access to the full QA Sphere public API. Users can now manage projects, test runs, test cases, results, and other resources programmatically without writing custom API integration code.

What's included

  • 16 resource subcommands: projects, runs, test-cases, results, folders, milestones, tags, requirements, shared-steps, shared-preconditions, custom-fields, audit-logs, settings, test-plans, files, users
  • JSON argument flexibility: Complex args accept inline JSON or file path.
  • Zod validation with path-based errors: Detailed error messages like [0].tcaseIds: not allowed for "live" runs
  • Lazy env loading: QAS_URL/QAS_TOKEN loaded only when the API is called, so CLI validation errors surface first
  • Path parameter validation: Regex-based validation prevents injection via crafted identifiers
  • File upload size limits: File body mode supports optional maxSize enforcement (e.g., 50 MiB for file uploads)
  • Agent Skills: New SKILL.md file allows installing skills via npx skills add Hypersequent/qas-cli

Architecture

The API command uses a manifest-based pattern

src/api/                          # API client layer
├── index.ts                      # createApi() — composes fetch chain and assembles all sub-modules
├── schemas.ts                    # Shared types, RequestValidationError, validateRequest(), common Zod fields
├── utils.ts                      # Fetch decorators, resourceIdSchema, printJson()
└── <resource>.ts                 # One per resource — exports create<Resource>Api(fetcher) factory,
                                  #   defines Zod request schemas for early validation before API calls

src/commands/api/                 # CLI command layer
├── types.ts                      # ApiEndpointSpec discriminated union (bodyMode: 'none' | 'json' | 'file')
├── manifests/                    # Declarative endpoint specs — one file per resource
│   ├── index.ts                  # Aggregates all specs into allSpecs array
│   ├── utils.ts                  # Shared param definitions (projectCodeParam, etc.)
│   └── <resource>.ts             # Array of ApiEndpointSpec objects per resource
├── builder.ts                    # Builds yargs command tree from flat specs array
├── executor.ts                   # Orchestrates validation → body processing → API call → error mapping
├── main.ts                       # Registers the api command
└── utils.ts                      # Shared helpers: validation, body parsing, error formatting

src/tests/api/                    # API command tests
├── test-helper.ts                # Shared infrastructure: useMockServer(), runCli(), test fixture
│                                 #   with project lifecycle (mock or live), helper creators
└── <resource>/
    └── <action>.spec.ts          # One spec per action — mocked tests (MSW), validation error
                                  #   tests, and live tests (tagged, run against real instance)

Each endpoint is a plain declarative object — the builder and executor handle all yargs wiring, validation, and error handling generically

Other changes

  • New API modules: audit-logs, custom-fields, milestones, requirements, results, settings, shared-preconditions, shared-steps, tags, test-plans, users, file — plus expanded runs, tcases, projects, folders
  • CLAUDE.md updated with full architecture docs for the manifest-based API command
  • README.md updated with usage documentation
  • SKILL.md added for AI coding agent support
  • CI workflow updated
  • npm audit fix applied to dependencies

Testing

  • 55+ test files under src/tests/api/ organized by resource, one spec per action
  • Each spec typically contains: mocked tests with MSW handlers, validation error tests, and live tests tagged with { tags: ['live'] }
  • Shared test infrastructure in test-helper.ts with useMockServer(), runCli(), expectValidationError(), and a test fixture with project lifecycle management
  • Global setup (global-setup.ts) handles live API authentication
  • Missing subcommand help tests ensure incomplete commands show help text
  • File upload tests verify max size enforcement

🤖 Generated with Claude Code

@gemini-code-assist

This comment was marked as resolved.

gemini-code-assist[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

@ramilamparo ramilamparo marked this pull request as ready for review March 25, 2026 09:06
claude[bot]

This comment was marked as outdated.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

src/api/run.ts Outdated
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the file to runs.ts to keep it uniform with the others.

skills/SKILL.md Outdated
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New skill can be added with npx skills add Hypersequent/qas-cli

Comment on lines +60 to +67
- name: Run live API tests
env:
QAS_TEST_URL: ${{ secrets.QAS_TEST_URL }}
QAS_TEST_TOKEN: ${{ secrets.QAS_TEST_TOKEN }}
QAS_TEST_USERNAME: ${{ secrets.QAS_TEST_USERNAME }}
QAS_TEST_PASSWORD: ${{ secrets.QAS_TEST_PASSWORD }}
QAS_DEV_AUTH: ${{ secrets.QAS_DEV_AUTH }}
run: npm run test:live
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Live tests are added that allows running automated tests with a real live qasphere instance. QAS_TEST_USERNAME and QAS_TEST_PASSWORD are required because we don't have a public API yet for deleting projects, which is required for clean-ups after the tests. So we use login credentials and call a non-public API instead.

"typescript": "^5.8.3",
"typescript-eslint": "^8.31.1",
"vitest": "^3.1.2"
"vitest": "^4.1.0"
Copy link
Copy Markdown
Collaborator Author

@ramilamparo ramilamparo Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated vitest to allow specifying tags. Which is useful for live tests and excluding them on normal testing.

Copy link
Copy Markdown
Collaborator

@satvik007 satvik007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was testing with claude and found some bugs

⏺ Bugs Found

  1. Trailing slash on QAS_URL breaks all API commands — QAS_URL="https://host.com/" produces double-slash URLs
    (https://host.com//api/...) returning 404 HTML. createApi() doesn't strip trailing slashes like
    ResultUploadCommandHandler does.
  2. folders bulk-create --folders expects wrong JSON format — Help says '[{"path": ["Parent", "Child"]}]'
    (array), but validation requires '{"folders": [{"path": ["Parent", "Child"]}]}' (object wrapper).
  3. test-cases list --include help suggests invalid values — Help example says "tags,requirements" but server
    rejects these with a validation error. Valid values are undocumented in the CLI.
  4. runs tcases list --limit silently ignored — Passing --limit 1 still returns all 20 test cases. The CLI
    accepts the arg but the API endpoint doesn't paginate.
  5. test-cases list --page 0 crashes with raw Go error — Server requires page >= 1 but CLI doesn't validate.
    Error shown: Field validation for 'Page' failed on the 'gt' tag.
  6. settings update-statuses color help/example are wrong — Help says "color": "#FF9800" (hex), but API
    requires named colors: blue, gray, red, orange, yellow, green, teal, indigo, purple, pink.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its possible to also move the api files inside the folders to have code that changes frequently lives together.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean?

claude[bot]

This comment was marked as outdated.

@ramilamparo
Copy link
Copy Markdown
Collaborator Author

ramilamparo commented Mar 27, 2026

@satvik007

I was testing with claude and found some bugs

⏺ Bugs Found

1. Trailing slash on QAS_URL breaks all API commands — QAS_URL="https://host.com/" produces double-slash URLs
   (https://host.com//api/...) returning 404 HTML. createApi() doesn't strip trailing slashes like
   ResultUploadCommandHandler does.

Fixed.

2. folders bulk-create --folders expects wrong JSON format — Help says '[{"path": ["Parent", "Child"]}]'
   (array), but validation requires '{"folders": [{"path": ["Parent", "Child"]}]}' (object wrapper).

Fixed. Argument should now only accept an array.

3. test-cases list --include help suggests invalid values — Help example says "tags,requirements" but server
   rejects these with a validation error. Valid values are undocumented in the CLI.

Updated help text to include possible values.

4. runs tcases list --limit silently ignored — Passing --limit 1 still returns all 20 test cases. The CLI
   accepts the arg but the API endpoint doesn't paginate.

Looks like the API doesn't pagination --limit. I've removed the limit argument.

5. test-cases list --page 0 crashes with raw Go error — Server requires page >= 1 but CLI doesn't validate.
   Error shown: Field validation for 'Page' failed on the 'gt' tag.

Could not reproduce. Possibly you've tested older code?

6. settings update-statuses color help/example are wrong — Help says "color": "#FF9800" (hex), but API
   requires named colors: blue, gray, red, orange, yellow, green, teal, indigo, purple, pink.

Fixed

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

@claude
Copy link
Copy Markdown

claude bot commented Mar 27, 2026

Reviewing PR #58: Add public API commands

  • Gather PR context and diff
  • Launch specialized review subagents (code quality, security, performance, test coverage)
  • Fetch existing comments for deduplication
  • Aggregate findings, deduplicate, and post review
  • Clean up outdated bot comments and progress comments

View job run

claude[bot]

This comment was marked as outdated.

claude[bot]

This comment was marked as outdated.

ramilamparo and others added 24 commits April 10, 2026 21:34
- Add Zod schemas at API level for all request types with validateRequest()
  that throws RequestValidationError, caught by apiHandler for clean error output
- Add handleValidationError() + buildArgumentMap() to map API field names to
  CLI argument names (e.g., title → --title) for user-friendly error messages
- Move validation schemas from command-level to API-level as single source of
  truth; command handlers pass args directly to API functions
- Add customFields, parameterValues, and filledTCaseTitleSuffixParams to
  test-case create/update commands with proper validation (parameterValues
  restricted to template type)
- Fix jsonResponse null crash, expand ResultStatus with custom statuses,
  relax test-cases update check, extract shared superRefine for run schemas
- Add tests for new fields (mocked + live) and batch-create validation errors
@satvik007 satvik007 force-pushed the dev/ram/public-api branch from c372bf3 to 2fa1e06 Compare April 10, 2026 16:11
@claude
Copy link
Copy Markdown

claude bot commented Apr 10, 2026

Claude finished @satvik007's task in 4m 58s —— View job


Re-review complete — Approved

Verified all 6 bugs from @satvik007's report are fixed and the recent commits address prior nits.

  • Gathered PR context and recent diff
  • Verified the 6 bug fixes
  • Submitted approving review
  • Cleaned up old progress comments

Bug fixes confirmed:

  1. Trailing slash on QAS_URLwithBaseUrl strips trailing slashes (src/api/utils.ts:2)
  2. folders bulk-create --folders — accepts bare array; API layer wraps it (src/commands/api/manifests/folders.ts:80-92)
  3. test-cases list --include valid values — help text now lists all valid values (src/commands/api/manifests/test-cases.ts:140-142)
  4. runs tcases list --limit — removed from query options (src/commands/api/manifests/runs.ts:279-292)
  5. test-cases list --page 0pageParam = z.number().int().positive().optional() rejects 0 (src/api/schemas.ts:55)
  6. settings update-statuses color — constrained to STATUS_COLORS enum (src/commands/api/manifests/settings.ts:9)

Other recent improvements:

  • Process exit code on unknown args is 1 with regression test
  • formatApiError receives verbose from handler instead of reading process.argv
  • runCli test helper uses try/finally for spy restore
  • File upload migrated to /file/batch endpoint with async readFile

Non-blocking carry-overs from prior reviews (not introduced by recent changes):

  • withHttpRetry honors unbounded Retry-After
  • File upload Buffer → Blob copy holds ~2x peak memory

LGTM. Full review posted on the PR. AndrianBdn approved on 2026-04-09; merge conflicts are the only remaining blocker.

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review after recent fixes

Verified all 6 bugs reported by @satvik007 are fixed:

  1. Trailing slash on QAS_URL — Fixed in withBaseUrl (src/api/utils.ts:2): baseUrl.replace(/\/+$/, '') strips trailing slashes.
  2. folders bulk-create --folders JSON format — Fixed (src/commands/api/manifests/folders.ts:80-92). --folders now accepts a bare array, the API layer wraps it as {folders: [...]}. --body still accepts the wrapped object form for compatibility.
  3. test-cases list --include valid values — Fixed (src/commands/api/manifests/test-cases.ts:140-142). Help now lists: steps, tags, requirements, customFields, parameterValues, folder, path, project.
  4. runs tcases list --limit silently ignored — Fixed (src/commands/api/manifests/runs.ts:279-292). --limit removed from query options.
  5. test-cases list --page 0pageParam = z.number().int().positive().optional() (src/api/schemas.ts:55) rejects 0 with a clean message before the request goes out. Confirmed correct.
  6. settings update-statuses color — Fixed (src/commands/api/manifests/settings.ts:9). Color is now constrained to the STATUS_COLORS enum (named colors) and the help text reflects this.

Other improvements in the latest commits:

  • Process exit code on unknown args is now 1 (src/commands/main.ts), with a regression test in src/tests/missing-subcommand-help.spec.ts:68-87.
  • formatApiError no longer reads process.argv directly — receives verbose from the handler.
  • runCli test helper now uses try/finally for spy restore.
  • File upload migrated to /api/public/v0/file/batch; uses async readFile.
  • SKILL.md and README updated for the batch endpoint and new options.

Non-blocking carry-overs from prior reviews (not introduced by this PR's recent changes):

  • withHttpRetry honors Retry-After without an upper bound, so a misconfigured server could stall the CLI indefinitely.
  • File upload still does Buffer → Blob copy (~2x peak memory for 50 MiB files); openAsBlob() would avoid this on Node 20+.

LGTM. AndrianBdn approved on 2026-04-09; the only blocker remaining is the merge conflict resolution he mentioned.

@satvik007 satvik007 merged commit 503a755 into main Apr 10, 2026
4 checks passed
@satvik007 satvik007 deleted the dev/ram/public-api branch April 10, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants