From 114765690a1d785fe8728369f8403c69f38bace9 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Sun, 15 Sep 2024 17:57:25 -0700 Subject: [PATCH] fix(lint): use buf plugins for lint and fixes for AEP compliance. Using buf plugins for linting is a more ergonomic approach, avoiding the need to manually clone googleapis. Fixes to reach AEP compliance: - removing apply method as it is not an official AEP at the moment. --- .github/workflows/test.yml | 8 +- buf.lock | 8 +- buf.yaml | 6 +- example/bookstore/v1/bookstore.yaml | 2 +- schema/resourcedefinition.pb.go | 116 ++++++++++++++++++---------- schema/resourcedefinition.proto | 64 +++++++++++---- scripts/run-api-linter.sh | 15 ++-- 7 files changed, 141 insertions(+), 78 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1aa5c8..2204c33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,13 +21,13 @@ jobs: - name: "test: no change to generated files." run: | - go install github.com/bufbuild/buf/cmd/buf@v1.38.0 + go install github.com/bufbuild/buf/cmd/buf@v1.42.0 ./scripts/verify-goldens.sh - name: "test: example server function" run: | ./scripts/test_http_api.sh - # - name: Run script - # run: | - # ./scripts/run-api-linter.sh + - name: run api-linter + run: | + ./scripts/run-api-linter.sh diff --git a/buf.lock b/buf.lock index 6c4355d..c83a0ee 100644 --- a/buf.lock +++ b/buf.lock @@ -1,8 +1,6 @@ # Generated by buf. DO NOT EDIT. -version: v1 +version: v2 deps: - - remote: buf.build - owner: googleapis - repository: googleapis + - name: buf.build/googleapis/googleapis commit: 28151c0d0a1641bf938a7672c500e01d - digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de + digest: b5:93b70089baa4fc05a92d3e52db91a4b7812db3b57b9664f6cb301733938cb630e377a938e8a56779388171c749c1d42a2e9a6c6230f2ff45f127a8102a6a27d0 diff --git a/buf.yaml b/buf.yaml index 204dbaa..ea81f26 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,9 +1,11 @@ -version: v1 +version: v2 breaking: use: - FILE lint: use: - - DEFAULT + - AEP +plugins: + - plugin: buf-plugin-aep deps: - buf.build/googleapis/googleapis:28151c0d0a1641bf938a7672c500e01d diff --git a/example/bookstore/v1/bookstore.yaml b/example/bookstore/v1/bookstore.yaml index f9a36d8..287f4e9 100644 --- a/example/bookstore/v1/bookstore.yaml +++ b/example/bookstore/v1/bookstore.yaml @@ -29,7 +29,7 @@ resources: update: {} delete: {} list: {} - apply: {} + apply: {} # do not uncomment until there is an AEP on apply. # - kind: "Publisher" # plural: "publishers" # methods: diff --git a/schema/resourcedefinition.pb.go b/schema/resourcedefinition.pb.go index afc9485..d64dc52 100644 --- a/schema/resourcedefinition.pb.go +++ b/schema/resourcedefinition.pb.go @@ -1,8 +1,7 @@ // resourcedefinition contains the // schema of the resource definition. -// regenerate with -// -// protoc ./aepc/schema/resourcedefinition.proto --go_opt paths=source_relative\ +// regenerate with: +// protoc ./aepc/schema/resourcedefinition.proto --go_opt paths=source_relative\ // --go_out=. // Code generated by protoc-gen-go. DO NOT EDIT. @@ -27,22 +26,30 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// The pritimive types supported by the schema. type Type int32 const ( - Type_UNSPECIFIED Type = 0 - Type_STRING Type = 1 - Type_INT32 Type = 2 - Type_INT64 Type = 3 - Type_DOUBLE Type = 4 - Type_FLOAT Type = 5 - Type_BOOLEAN Type = 6 + // The type is unspecified. + Type_TYPE_UNSPECIFIED Type = 0 + // The type is a string. + Type_STRING Type = 1 + // The type is an int32. + Type_INT32 Type = 2 + // The type is an int64. + Type_INT64 Type = 3 + // The type is a double. + Type_DOUBLE Type = 4 + // The type is a float. + Type_FLOAT Type = 5 + // The type is a boolean. + Type_BOOLEAN Type = 6 ) // Enum value maps for Type. var ( Type_name = map[int32]string{ - 0: "UNSPECIFIED", + 0: "TYPE_UNSPECIFIED", 1: "STRING", 2: "INT32", 3: "INT64", @@ -51,13 +58,13 @@ var ( 6: "BOOLEAN", } Type_value = map[string]int32{ - "UNSPECIFIED": 0, - "STRING": 1, - "INT32": 2, - "INT64": 3, - "DOUBLE": 4, - "FLOAT": 5, - "BOOLEAN": 6, + "TYPE_UNSPECIFIED": 0, + "STRING": 1, + "INT32": 2, + "INT64": 3, + "DOUBLE": 4, + "FLOAT": 5, + "BOOLEAN": 6, } ) @@ -88,12 +95,15 @@ func (Type) EnumDescriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{0} } +// An API service. type Service struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The name of the API service. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The resources that the API service exposes. Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` // These are additional objects (list of properties) that may be referenced from another property. Objects []*Object `protobuf:"bytes,3,rep,name=objects,proto3" json:"objects,omitempty"` @@ -152,6 +162,7 @@ func (x *Service) GetObjects() []*Object { return nil } +// A resource. type Resource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -164,9 +175,9 @@ type Resource struct { Plural string `protobuf:"bytes,2,opt,name=plural,proto3" json:"plural,omitempty"` // The list of parent resources, referred to via the kind. Parents []string `protobuf:"bytes,3,rep,name=parents,proto3" json:"parents,omitempty"` - // Properties + // Properties of the resource. Also often referred to as it's schema. Properties map[string]*Property `protobuf:"bytes,4,rep,name=properties,proto3" json:"properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // method support + // methods support by the resource. Methods *Methods `protobuf:"bytes,5,opt,name=methods,proto3" json:"methods,omitempty"` } @@ -237,12 +248,16 @@ func (x *Resource) GetMethods() *Methods { return nil } +// An object is a collection of properties, that does not have methods of it's +// on in the API. It is currently only used as a property of a resource. type Object struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` + // The name of the object. + Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` + // The properties of the object. Properties map[string]*Property `protobuf:"bytes,2,rep,name=properties,proto3" json:"properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -292,18 +307,26 @@ func (x *Object) GetProperties() map[string]*Property { return nil } +// Methods supported by a resource. type Methods struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Create *Methods_CreateMethod `protobuf:"bytes,1,opt,name=create,proto3" json:"create,omitempty"` - Read *Methods_ReadMethod `protobuf:"bytes,2,opt,name=read,proto3" json:"read,omitempty"` - Update *Methods_UpdateMethod `protobuf:"bytes,3,opt,name=update,proto3" json:"update,omitempty"` - Delete *Methods_DeleteMethod `protobuf:"bytes,4,opt,name=delete,proto3" json:"delete,omitempty"` - List *Methods_ListMethod `protobuf:"bytes,5,opt,name=list,proto3" json:"list,omitempty"` + // Specific properties of the create method for the resource. + Create *Methods_CreateMethod `protobuf:"bytes,1,opt,name=create,proto3" json:"create,omitempty"` + // Specific properties of the read method for the resource. + Read *Methods_ReadMethod `protobuf:"bytes,2,opt,name=read,proto3" json:"read,omitempty"` + // Specific properties of the update method for the resource. + Update *Methods_UpdateMethod `protobuf:"bytes,3,opt,name=update,proto3" json:"update,omitempty"` + // Specific properties of the delete emethod for the resource. + Delete *Methods_DeleteMethod `protobuf:"bytes,4,opt,name=delete,proto3" json:"delete,omitempty"` + // Specific properties of the list for the resource. + List *Methods_ListMethod `protobuf:"bytes,5,opt,name=list,proto3" json:"list,omitempty"` + // Specific properties of the global_list for the resource. GlobalList *Methods_GlobalListMethod `protobuf:"bytes,6,opt,name=global_list,json=globalList,proto3" json:"global_list,omitempty"` - Apply *Methods_ApplyMethod `protobuf:"bytes,7,opt,name=apply,proto3" json:"apply,omitempty"` + // Specific properties of the apply for the resource. + Apply *Methods_ApplyMethod `protobuf:"bytes,7,opt,name=apply,proto3" json:"apply,omitempty"` } func (x *Methods) Reset() { @@ -387,6 +410,7 @@ func (x *Methods) GetApply() *Methods_ApplyMethod { return nil } +// A property represents a field in a resource or object. type Property struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -400,9 +424,11 @@ type Property struct { Types isProperty_Types `protobuf_oneof:"types"` // field number used for protobuf or other systems where fields must // be explicitly enumerated. - Number int32 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"` - ReadOnly bool `protobuf:"varint,3,opt,name=readOnly,proto3" json:"readOnly,omitempty"` - Required bool `protobuf:"varint,4,opt,name=required,proto3" json:"required,omitempty"` + Number int32 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"` + // true if the property is read only. + ReadOnly bool `protobuf:"varint,3,opt,name=readOnly,proto3" json:"readOnly,omitempty"` + // true if the property is required. + Required bool `protobuf:"varint,4,opt,name=required,proto3" json:"required,omitempty"` } func (x *Property) Reset() { @@ -448,7 +474,7 @@ func (x *Property) GetType() Type { if x, ok := x.GetTypes().(*Property_Type); ok { return x.Type } - return Type_UNSPECIFIED + return Type_TYPE_UNSPECIFIED } func (x *Property) GetObjectType() *ObjectType { @@ -630,7 +656,7 @@ func (x *ArrayType) GetType() Type { if x, ok := x.GetArrayDetails().(*ArrayType_Type); ok { return x.Type } - return Type_UNSPECIFIED + return Type_TYPE_UNSPECIFIED } func (x *ArrayType) GetObjectType() *ObjectType { @@ -656,6 +682,7 @@ func (*ArrayType_Type) isArrayType_ArrayDetails() {} func (*ArrayType_ObjectType) isArrayType_ArrayDetails() {} +// The properties of the create method. type Methods_CreateMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -694,6 +721,7 @@ func (*Methods_CreateMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 0} } +// The properties of the read method. type Methods_ReadMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -732,6 +760,7 @@ func (*Methods_ReadMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 1} } +// The properties of the update method. type Methods_UpdateMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -770,6 +799,7 @@ func (*Methods_UpdateMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 2} } +// The properties of the delete method. type Methods_DeleteMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -808,6 +838,7 @@ func (*Methods_DeleteMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 3} } +// The properties of the list method. type Methods_ListMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -846,6 +877,7 @@ func (*Methods_ListMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 4} } +// THe properties of the global list method. type Methods_GlobalListMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -884,6 +916,7 @@ func (*Methods_GlobalListMethod) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{3, 5} } +// THe properties of the apply method. type Methods_ApplyMethod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1012,14 +1045,15 @@ var file_schema_resourcedefinition_proto_rawDesc = []byte{ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2a, 0x5d, 0x0a, 0x04, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, - 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x4f, 0x55, 0x42, 0x4c, - 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x05, 0x12, 0x0b, - 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x06, 0x42, 0x09, 0x5a, 0x07, 0x2f, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2a, 0x62, 0x0a, 0x04, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, + 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, + 0x02, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, + 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, + 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x06, + 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/schema/resourcedefinition.proto b/schema/resourcedefinition.proto index c02d1b2..65b77ac 100644 --- a/schema/resourcedefinition.proto +++ b/schema/resourcedefinition.proto @@ -1,20 +1,24 @@ // resourcedefinition contains the // schema of the resource definition. -// regenerate with -// -// protoc ./aepc/schema/resourcedefinition.proto --go_opt paths=source_relative\ +// regenerate with: +// protoc ./aepc/schema/resourcedefinition.proto --go_opt paths=source_relative\ // --go_out=. syntax = "proto3"; option go_package = "/schema"; +// An API service. message Service { + // The name of the API service. string name = 1; + + // The resources that the API service exposes. repeated Resource resources = 2; // These are additional objects (list of properties) that may be referenced from another property. repeated Object objects = 3; } +// A resource. message Resource { // The type of the resource. Used to programmatically // refer to and identify the resource. @@ -23,45 +27,55 @@ message Resource { string plural = 2; // The list of parent resources, referred to via the kind. repeated string parents = 3; - // Properties + // Properties of the resource. Also often referred to as it's schema. map properties = 4; - // method support + // methods support by the resource. Methods methods = 5; } +// An object is a collection of properties, that does not have methods of it's +// on in the API. It is currently only used as a property of a resource. message Object { + // The name of the object. string kind = 1; + // The properties of the object. map properties = 2; } +// Methods supported by a resource. message Methods { + // The properties of the create method. message CreateMethod {} + // The properties of the read method. message ReadMethod {} + // The properties of the update method. message UpdateMethod {} + // The properties of the delete method. message DeleteMethod {} + // The properties of the list method. message ListMethod {} + // THe properties of the global list method. message GlobalListMethod {} + // THe properties of the apply method. message ApplyMethod {} + // Specific properties of the create method for the resource. CreateMethod create = 1; + // Specific properties of the read method for the resource. ReadMethod read = 2; + // Specific properties of the update method for the resource. UpdateMethod update = 3; + // Specific properties of the delete emethod for the resource. DeleteMethod delete = 4; + // Specific properties of the list for the resource. ListMethod list = 5; + // Specific properties of the global_list for the resource. GlobalListMethod global_list = 6; + // Specific properties of the apply for the resource. ApplyMethod apply = 7; } -enum Type { - UNSPECIFIED = 0; - STRING = 1; - INT32 = 2; - INT64 = 3; - DOUBLE = 4; - FLOAT = 5; - BOOLEAN = 6; -} - +// A property represents a field in a resource or object. message Property { oneof types { Type type = 1; @@ -71,7 +85,9 @@ message Property { // field number used for protobuf or other systems where fields must // be explicitly enumerated. int32 number = 2; + // true if the property is read only. bool readOnly = 3; + // true if the property is required. bool required = 4; } @@ -87,3 +103,21 @@ message ArrayType { ObjectType object_type = 2; } } + +// The pritimive types supported by the schema. +enum Type { + // The type is unspecified. + TYPE_UNSPECIFIED = 0; + // The type is a string. + STRING = 1; + // The type is an int32. + INT32 = 2; + // The type is an int64. + INT64 = 3; + // The type is a double. + DOUBLE = 4; + // The type is a float. + FLOAT = 5; + // The type is a boolean. + BOOLEAN = 6; +} \ No newline at end of file diff --git a/scripts/run-api-linter.sh b/scripts/run-api-linter.sh index 2741cf1..8fd0635 100755 --- a/scripts/run-api-linter.sh +++ b/scripts/run-api-linter.sh @@ -1,15 +1,10 @@ #!/usr/bin/env bash set -e -if ! which api-linter ; then - go install github.com/aep-dev/api-linter/cmd/api-linter@latest +if ! which buf-plugin-aep > /dev/null; then + go install github.com/aep-dev/api-linter/cmd/buf-plugin-aep@latest fi -if [ ! -d /tmp/googleapis ]; then - git clone https://github.com/googleapis/googleapis.git --depth=1 /tmp/googleapis -fi - -api-linter \ - ./example/bookstore/v1/bookstore.proto \ - -I /tmp/googleapis \ - --set-exit-status \ No newline at end of file +echo "Running API linter..." +buf lint --path example/bookstore/v1/bookstore.proto +echo "passed!" \ No newline at end of file