Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
94939c4
feat(grpc): create grpcprotoc package structure
spencercjh Mar 7, 2026
3b9841f
feat(grpc): implement grpcprotoc detector
spencercjh Mar 7, 2026
d9de38e
feat(grpc): implement grpcprotoc patcher
spencercjh Mar 7, 2026
f3bea6d
feat(grpc): implement grpcprotoc generator
spencercjh Mar 7, 2026
cc24f47
feat(grpc): register grpcprotoc extractor in builtin registry
spencercjh Mar 7, 2026
b279d78
feat(grpc): add --proto-import-path CLI flag
spencercjh Mar 7, 2026
9460eea
docs: add gRPC-protoc support to README
spencercjh Mar 7, 2026
dc2f101
feat(grpcprotoc): improve proto file handling and add demo project
spencercjh Mar 7, 2026
cb4846b
feat(grpcprotoc): add HTTP annotations support for REST endpoints
spencercjh Mar 7, 2026
af98829
test(e2e): add gRPC-protoc integration test
spencercjh Mar 7, 2026
d600d36
docs: update grpc-protoc documentation and tests
spencercjh Mar 8, 2026
020e18a
docs(grpc): update design and implementation plan to reflect actual i…
spencercjh Mar 8, 2026
baea31a
ci: add Protoc installation step in CI configuration
spencercjh Mar 8, 2026
12df44e
ci: add setup step for protoc-gen-connect-openapi
spencercjh Mar 8, 2026
1df9dd1
fix(grpcprotoc): remove duplicate google/api/annotations.proto check
spencercjh Mar 8, 2026
8fe6591
refactor(grpcprotoc): simplify findOutputFile logic
spencercjh Mar 8, 2026
8f0b5ce
refactor(grpcprotoc): remove duplicate FrameworkName constant
spencercjh Mar 8, 2026
694925d
refactor(grpcprotoc): use strings.Contains instead of custom helper
spencercjh Mar 8, 2026
2684732
fix(grpcprotoc): add service definition requirement in detector
spencercjh Mar 8, 2026
2e1955c
fix(grpcprotoc): pass OutputFile to protoc plugin and simplify findOu…
spencercjh Mar 8, 2026
b625708
fix(e2e): update grpc_protoc_test to use ExtractorName
spencercjh Mar 8, 2026
d76ba8e
fix(grpcprotoc): handle comments in hasServiceDefinition and avoid re…
spencercjh Mar 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,11 @@ jobs:
java-version: "25"
distribution: "temurin"

- name: Set up Protoc
uses: arduino/setup-protoc@v3

- name: Set up protoc-gen-connect-openapi
run: go install github.com/sudorandom/protoc-gen-connect-openapi@latest

- name: Run E2E tests
run: make test-e2e
46 changes: 30 additions & 16 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ make verify

## Architecture Overview

Spec Forge is a CLI tool that generates enriched OpenAPI specifications from Spring Boot projects.
Spec Forge is a CLI tool that generates enriched OpenAPI specifications from various frameworks (Spring Boot, go-zero, gRPC-protoc).

**Core workflow:**
```
Source Code → Detect → Patch → Generate → Validate → Enrich → Restore
Source Code → Detect → Patch → Generate → Validate → Enrich → Publish
```

### Package Structure
Expand All @@ -43,27 +43,41 @@ cmd/ # Cobra CLI commands
├── root.go # Entry point, config initialization
├── generate.go # `spec-forge generate` - full pipeline
├── enrich.go # `spec-forge enrich` - standalone enrichment
├── spring.go # `spec-forge spring` - patch/detect subcommands
├── publish.go # `spec-forge publish` - publish to platforms

internal/
├── config/ # Viper configuration loading
├── executor/ # Shell command execution with timeout
├── extractor/ # OpenAPI spec extraction
│ ├── types.go # GenerateOptions, GenerateResult, etc.
│ └── spring/ # Spring Boot specific implementation
│ ├── detector.go # Project type detection (Maven/Gradle)
│ ├── patcher.go # springdoc dependency injection
│ ├── generator.go # Maven/Gradle command execution
│ ├── maven.go # POM parsing, spring-boot plugin config
│ └── gradle.go # build.gradle parsing
│ ├── builtin/ # Built-in extractor registry
│ ├── spring/ # Spring Boot implementation
│ │ ├── detector.go # Project type detection (Maven/Gradle)
│ │ ├── patcher.go # springdoc dependency injection
│ │ ├── generator.go # Maven/Gradle command execution
│ │ ├── maven.go # POM parsing, spring-boot plugin config
│ │ └── gradle.go # build.gradle parsing
│ ├── gozero/ # go-zero implementation
│ │ ├── detector.go # go.mod parsing, dependency detection
│ │ ├── patcher.go # go-swagger installation check
│ │ └── generator.go # goctl command execution
│ └── grpcprotoc/ # gRPC-protoc implementation
│ ├── detector.go # .proto file detection, buf.yaml rejection
│ ├── patcher.go # protoc tools check
│ ├── generator.go # protoc command execution
│ └── grpcprotoc.go # Info struct with ProtoFiles, ServiceProtoFiles
├── validator/ # kin-openapi validation
└── enricher/ # LLM-based description enrichment
├── enricher.go # Main enricher interface
├── config.go # Enricher configuration
├── prompt/ # Prompt templates
├── processor/ # Batching and concurrent processing
└── provider/ # LLM providers (factory pattern)
└── factory.go # Use NewProvider(cfg Config) to create providers
├── enricher/ # LLM-based description enrichment
│ ├── enricher.go # Main enricher interface
│ ├── config.go # Enricher configuration
│ ├── prompt/ # Prompt templates
│ ├── processor/ # Batching and concurrent processing
│ ├── specctx/ # Spec context extraction (reserved for future)
│ └── provider/ # LLM providers (factory pattern)
│ └── factory.go # Use NewProvider(cfg Config) to create providers
└── publisher/ # OpenAPI spec publishing
├── local.go # Local file publishing
└── readme.go # ReadMe.com publishing via rdme CLI
```

### Data Flow
Expand Down
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,33 @@ LLM_API_KEY="sk-xxx" spec-forge enrich ./openapi.json \
|----------------------------------------------------------------------------------------------------------------------------------------------|----------------|----------------|
| [Spring Boot](https://springdoc.org/#plugins) | Java | ✅ Supported |
| [go-zero](https://go-zero.dev/reference/cli-guide/swagger/) | Go | ✅ Supported |
| [gRPC (protoc)](https://github.com/sudorandom/protoc-gen-connect-openapi) | Multi-language | ✅ Supported |
| [Hertz](https://github.com/hertz-contrib/swagger-generate/tree/main/protoc-gen-http-swagger) | Go | 🚧 Coming soon |
| [Kitex](https://github.com/hertz-contrib/swagger-generate/tree/main/protoc-gen-rpc-swagger) | Go | 🚧 Coming soon |
| [gRPC](https://github.com/grpc-ecosystem/grpc-gateway?tab=readme-ov-file#6-optional-generate-openapi-definitions-using-protoc-gen-openapiv2) | Multi-language | 🚧 Coming soon |

### gRPC Projects (Native protoc)

For gRPC projects using native protoc (not buf-managed):

```bash
# Generate OpenAPI spec from proto files
spec-forge generate ./my-grpc-project

# With additional import paths
spec-forge generate ./my-grpc-project --proto-import-path ./third_party --proto-import-path ./vendor

# Generate with AI enrichment
LLM_API_KEY="your-key" spec-forge generate ./my-grpc-project --enrich --language zh
```

**Requirements:**
- `protoc` installed ([install guide](https://github.com/protocolbuffers/protobuf/releases))
- `protoc-gen-connect-openapi` installed:
```bash
go install github.com/sudorandom/protoc-gen-connect-openapi@latest
```

**Note:** buf-managed projects are not supported in this mode. Use `buf generate` with the plugin, then use `spec-forge enrich` on the generated OpenAPI spec.

## Supported Publishers

Expand Down
13 changes: 9 additions & 4 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ var (
generatePublishTarget string
// generatePublishOverwrite controls whether to overwrite existing remote spec
generatePublishOverwrite bool
// generateProtoImportPaths are additional import paths for protoc (-I flags)
generateProtoImportPaths []string
)

// generateCmd represents the generate command
Expand Down Expand Up @@ -123,10 +125,11 @@ func runGenerate(cmd *cobra.Command, args []string) error { //nolint:gocyclo //
}

genOpts := &extractor.GenerateOptions{
OutputDir: outputDir,
Format: config.Get().Output.Format,
Timeout: generateTimeout,
SkipTests: true,
OutputDir: outputDir,
Format: config.Get().Output.Format,
Timeout: generateTimeout,
SkipTests: true,
ProtoImportPaths: generateProtoImportPaths,
}

genResult, err := extractorImpl.Generate(ctx, path, info, genOpts)
Expand Down Expand Up @@ -262,6 +265,8 @@ func init() {
"publish target (local, readme)")
generateCmd.Flags().BoolVar(&generatePublishOverwrite, "publish-overwrite", false,
"overwrite existing spec (applies to both local and remote publishers)")
generateCmd.Flags().StringSliceVar(&generateProtoImportPaths, "proto-import-path", nil,
"additional import paths for protoc (-I flags), can be specified multiple times")
}

// enrichGeneratedSpec enriches the generated spec with AI-generated descriptions
Expand Down
Loading