Skip to content

Add content-api benchmark project with multi-style API specs - #3

Merged
viqueen merged 1 commit into
mainfrom
feature/content-api-benchmark
Mar 6, 2026
Merged

Add content-api benchmark project with multi-style API specs#3
viqueen merged 1 commit into
mainfrom
feature/content-api-benchmark

Conversation

@viqueen

@viqueen viqueen commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds projects/content-api/_shared/ with API specs and k6 load test scripts for three API styles: OpenAPI (REST), GraphQL, and Protobuf (gRPC)
  • Creates .claude/commands/scaffold-implementation.md — an interactive Claude command that guides users through scaffolding new implementations against these specs
  • Fixes toolkit/src/report/json.js to sanitize slashes in target names for result filenames (supports content-api/spring-boot style target names)
  • Clears the placeholder example-api target from benchmark.config.json

Test plan

  • npm run benchmark -- list parses config without errors
  • npm run lint passes
  • Run /scaffold-implementation to scaffold a first implementation and verify the full benchmark pipeline

🤖 Generated with Claude Code

Establish the canonical project structure under projects/ for benchmark
targets, starting with content-api. Shared API contracts and k6 load test
scripts are provided for three API styles: OpenAPI (REST), GraphQL, and
Protobuf (gRPC). An interactive Claude command is added to scaffold new
implementations against these specs.

Also fixes result filename generation to sanitize slashes in target names
and removes the example-api placeholder from the config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 6, 2026 05:09
@viqueen
viqueen merged commit d464143 into main Mar 6, 2026
3 checks passed
@viqueen
viqueen deleted the feature/content-api-benchmark branch March 6, 2026 05:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new content-api benchmark “shared contract” area (OpenAPI/GraphQL/Protobuf) plus k6 scripts to drive each style, and improves result file naming to support hierarchical target names (e.g., content-api/spring-boot).

Changes:

  • Introduce projects/content-api/_shared/ with OpenAPI, GraphQL, and Protobuf API specs and corresponding k6 load-test scripts.
  • Add a .claude interactive command to scaffold new benchmark implementations against these shared specs.
  • Sanitize / in result filenames and remove the placeholder example-api target from benchmark.config.json.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
toolkit/src/report/json.js Sanitizes target name in output filenames to avoid path separators.
projects/content-api/_shared/protobuf/k6/content-api.js Adds a gRPC-based k6 scenario for CRUD-style content operations.
projects/content-api/_shared/protobuf/content.proto Defines the gRPC service + messages for the protobuf benchmark contract.
projects/content-api/_shared/openapi/k6/content-api.js Adds a REST/OpenAPI-based k6 scenario for CRUD-style content operations.
projects/content-api/_shared/openapi/api-spec.yaml Adds an OpenAPI 3.1 contract for the REST content API.
projects/content-api/_shared/graphql/schema.graphql Adds a GraphQL schema for the content API benchmark contract.
projects/content-api/_shared/graphql/k6/content-api.js Adds a GraphQL-based k6 scenario for CRUD-style content operations.
benchmark.config.json Removes placeholder target; leaves an empty targets map with defaults/grafana/output intact.
.claude/commands/scaffold-implementation.md Adds scaffolding guidance for generating implementations and registering targets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


const timestamp = results.timestamp.replace(/[:.]/g, '-');
const filename = `${results.target}-${timestamp}.json`;
const safeName = results.target.replace(/\//g, '-');

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

safeName only replaces forward slashes. On Windows, a target name containing backslashes (or sequences like ..\) can be interpreted by path.join() as a path segment and potentially escape outputDir / create nested paths. Consider normalizing to a safe filename by stripping/replacing both / and \\ (and ideally other filesystem-invalid characters) or by using path.basename() on a sanitized string before joining.

Suggested change
const safeName = results.target.replace(/\//g, '-');
const safeName = results.target.replace(/[\/\\]/g, '-');

Copilot uses AI. Check for mistakes.

put:
operationId: updateContent
summary: Update a content item

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

The PUT /api/v1/content/{id} operation is defined as a partial update (per the k6 script and UpdateContentRequest), but HTTP PUT typically implies full replacement. To avoid ambiguity across implementations, consider switching this operation to PATCH or explicitly documenting that PUT performs a partial update.

Suggested change
summary: Update a content item
summary: Partially update a content item
description: >
Partially updates the specified content item using the fields provided
in the request body. Any fields omitted from the request body are left
unchanged on the existing resource. Although this operation uses HTTP
PUT, it is intentionally defined as a partial update rather than a full
replacement.

Copilot uses AI. Check for mistakes.
Comment on lines +189 to +200
UpdateContentRequest:
type: object
properties:
title:
type: string
minLength: 1
maxLength: 255
body:
type: string
status:
type: string
enum: [draft, published, archived]

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

UpdateContentRequest allows an empty object, which makes it unclear how servers should respond to a no-op update (and can hide client bugs). Consider requiring at least one field (e.g., minProperties: 1 in OAS 3.1 / JSON Schema) or using an anyOf to enforce that title, body, or status is present.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +36
### Dockerfile
- Use an appropriate base image for the language/framework
- Multi-stage build where applicable (build stage + runtime stage)
- The final image should be as small as practical
- Expose port 8080

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

The Dockerfile guidance says to "Expose port 8080", but later the protobuf style section states the gRPC server should listen on port 50051 in addition to the HTTP health check on 8080. To keep the scaffold instructions consistent, update the Dockerfile/compose guidance to include exposing/mapping port 50051 for protobuf implementations (or clarify that EXPOSE is optional but the service must listen on both ports).

Copilot uses AI. Check for mistakes.
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.

2 participants