support message reference #42

Merged
vtolstov merged 2 commits from messageref into v3 2022-03-19 15:17:56 +03:00
11 changed files with 154 additions and 105 deletions

20
.github/workflows/autoapprove.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: "autoapprove"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
autoapprove:
runs-on: ubuntu-latest
steps:
- name: approve
uses: hmarr/auto-approve-action@v2
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
id: approve
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

21
.github/workflows/automerge.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: "automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'vtolstov'
steps:
- name: merge
id: merge
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@ -3,6 +3,7 @@ on:
push:
branches:
- master
- v3
jobs:
test:
name: test
@ -33,7 +34,7 @@ jobs:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v3.1.0
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.

View File

@ -9,7 +9,7 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
name: "codeql"
on:
workflow_run:
@ -17,16 +17,16 @@ on:
types:
- completed
push:
branches: [ master ]
branches: [ master, v3 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches: [ master, v3 ]
schedule:
- cron: '34 1 * * 0'
jobs:
analyze:
name: Analyze
name: analyze
runs-on: ubuntu-latest
permissions:
actions: read
@ -42,11 +42,14 @@ jobs:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
- name: checkout
uses: actions/checkout@v3
- name: setup
uses: actions/setup-go@v2
with:
go-version: 1.17
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- name: init
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
@ -57,7 +60,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- name: autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
@ -71,5 +74,5 @@ jobs:
# make bootstrap
# make release
- name: Perform CodeQL Analysis
- name: analyze
uses: github/codeql-action/analyze@v1

View File

@ -1,66 +1,27 @@
name: "prautomerge"
name: "dependabot-automerge"
on:
workflow_run:
workflows: ["prbuild"]
types:
- completed
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
contents: write
pull-requests: write
contents: write
jobs:
Dependabot-Automerge:
automerge:
runs-on: ubuntu-latest
# Contains workaround to execute if dependabot updates the PR by checking for the base branch in the linked PR
# The the github.event.workflow_run.event value is 'push' and not 'pull_request'
# dont work with multiple workflows when last returns success
if: >-
github.event.workflow_run.conclusion == 'success'
&& github.actor == 'dependabot[bot]'
&& github.event.sender.login == 'dependabot[bot]'
&& github.event.sender.type == 'Bot'
&& (github.event.workflow_run.event == 'pull_request'
|| (github.event.workflow_run.event == 'push' && github.event.workflow_run.pull_requests[0].base.ref == github.event.repository.default_branch ))
if: github.actor == 'dependabot[bot]'
steps:
- name: Approve Changes and Merge changes if label 'dependencies' is set
uses: actions/github-script@v6
- name: metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
console.log(context.payload.workflow_run);
var labelNames = await github.paginate(
github.issues.listLabelsOnIssue,
{
repo: context.repo.repo,
owner: context.repo.owner,
issue_number: context.payload.workflow_run.pull_requests[0].number,
},
(response) => response.data.map(
(label) => label.name
)
);
console.log(labelNames);
if (labelNames.includes('dependencies')) {
console.log('Found label');
await github.pulls.createReview({
repo: context.repo.repo,
owner: context.repo.owner,
pull_number: context.payload.workflow_run.pull_requests[0].number,
event: 'APPROVE'
});
console.log('Approved PR');
await github.pulls.merge({
repo: context.repo.repo,
owner: context.repo.owner,
pull_number: context.payload.workflow_run.pull_requests[0].number,
});
console.log('Merged PR');
}
github-token: "${{ secrets.TOKEN }}"
- name: merge
id: merge
if: ${{contains(steps.metadata.outputs.dependency-names, 'go.unistack.org')}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@ -3,6 +3,7 @@ on:
pull_request:
branches:
- master
- v3
jobs:
test:
name: test
@ -33,7 +34,7 @@ jobs:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v3.1.0
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.

View File

@ -40,13 +40,13 @@ func (g *Generator) httpGenerate(component string, plugin *protogen.Plugin, genC
for _, service := range file.Services {
if genClient {
generateServiceClient(gfile, service)
generateServiceClientMethods(gfile, service, true)
g.generateServiceClient(gfile, service)
g.generateServiceClientMethods(gfile, service, true)
}
if genServer {
generateServiceServer(gfile, service)
generateServiceServerMethods(gfile, service)
generateServiceRegister(gfile, service)
g.generateServiceServerMethods(gfile, service)
g.generateServiceRegister(gfile, service)
}
}
}

View File

@ -45,11 +45,13 @@ type Generator struct {
fieldaligment bool
tagPath string
openapiFile string
plugin *protogen.Plugin
}
func (g *Generator) Generate(plugin *protogen.Plugin) error {
var err error
g.plugin = plugin
g.standalone = *flagStandalone
g.debug = *flagDebug
g.components = *flagComponents

View File

@ -35,14 +35,14 @@ func (g *Generator) microGenerate(component string, plugin *protogen.Plugin, gen
}
// generate services
for _, service := range file.Services {
generateServiceEndpoints(gfile, service)
g.generateServiceEndpoints(gfile, service)
if genClient {
generateServiceClientInterface(gfile, service)
generateServiceClientStreamInterface(gfile, service)
g.generateServiceClientInterface(gfile, service)
g.generateServiceClientStreamInterface(gfile, service)
}
if genServer {
generateServiceServerInterface(gfile, service)
generateServiceServerStreamInterface(gfile, service)
g.generateServiceServerInterface(gfile, service)
g.generateServiceServerStreamInterface(gfile, service)
}
}

8
rpc.go
View File

@ -37,13 +37,13 @@ func (g *Generator) rpcGenerate(component string, plugin *protogen.Plugin, genCl
}
for _, service := range file.Services {
if genClient {
generateServiceClient(gfile, service)
generateServiceClientMethods(gfile, service, false)
g.generateServiceClient(gfile, service)
g.generateServiceClientMethods(gfile, service, false)
}
if genServer {
generateServiceServer(gfile, service)
generateServiceServerMethods(gfile, service)
generateServiceRegister(gfile, service)
g.generateServiceServerMethods(gfile, service)
g.generateServiceRegister(gfile, service)
}
}
}

90
util.go
View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"log"
"net/http"
"strings"
@ -28,7 +29,7 @@ func unexport(s string) string {
return strings.ToLower(s[:1]) + s[1:]
}
func generateServiceClient(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceClient(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
// if rule, ok := getMicroApiService(service); ok {
// gfile.P("// client wrappers ", strings.Join(rule.ClientWrappers, ", "))
@ -44,11 +45,11 @@ func generateServiceClient(gfile *protogen.GeneratedFile, service *protogen.Serv
gfile.P()
}
func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protogen.Service, http bool) {
func (g *Generator) generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protogen.Service, http bool) {
serviceName := service.GoName
for _, method := range service.Methods {
methodName := fmt.Sprintf("%s.%s", serviceName, method.GoName)
generateClientFuncSignature(gfile, serviceName, method)
g.generateClientFuncSignature(gfile, serviceName, method)
if http && method.Desc.Options() != nil {
if proto.HasExtension(method.Desc.Options(), v2.E_Openapiv2Operation) {
@ -61,20 +62,25 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog
gfile.P("errmap := make(map[string]interface{}, ", len(r.Responses.ResponseCode), ")")
for _, rsp := range r.Responses.ResponseCode {
if schema := rsp.Value.GetJsonReference(); schema != nil {
ref := schema.XRef
if strings.HasPrefix(ref, "."+string(service.Desc.ParentFile().Package())+".") {
ref = strings.TrimPrefix(ref, "."+string(service.Desc.ParentFile().Package())+".")
xref := schema.XRef
if strings.HasPrefix(xref, "."+string(service.Desc.ParentFile().Package())+".") {
xref = strings.TrimPrefix(xref, "."+string(service.Desc.ParentFile().Package())+".")
}
if ref[0] == '.' {
ref = ref[1:]
if xref[0] == '.' {
xref = xref[1:]
}
switch ref {
switch xref {
case "micro.codec.Frame":
gfile.P(`errmap["`, rsp.Name, `"] = &`, microCodecPackage.Ident("Frame"), "{}")
case "micro.errors.Error":
gfile.P(`errmap["`, rsp.Name, `"] = &`, microErrorsPackage.Ident("Error"), "{}")
default:
gfile.P(`errmap["`, rsp.Name, `"] = &`, ref, "{}")
ident, err := g.getGoIdentByXref(strings.TrimPrefix(schema.XRef, "."))
if err != nil {
log.Printf("cant find message by ref %s\n", schema.XRef)
continue
}
gfile.P(`errmap["`, rsp.Name, `"] = &`, gfile.QualifiedGoIdent(ident), "{}")
}
}
}
@ -97,20 +103,25 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog
gfile.P("errmap := make(map[string]interface{}, ", len(resps), ")")
for _, rsp := range resps {
if schema := rsp.Value.GetReference(); schema != nil {
ref := schema.XRef
if strings.HasPrefix(ref, "."+string(service.Desc.ParentFile().Package())+".") {
ref = strings.TrimPrefix(ref, "."+string(service.Desc.ParentFile().Package())+".")
xref := schema.XRef
if strings.HasPrefix(xref, "."+string(service.Desc.ParentFile().Package())+".") {
xref = strings.TrimPrefix(xref, "."+string(service.Desc.ParentFile().Package())+".")
}
if ref[0] == '.' {
ref = ref[1:]
if xref[0] == '.' {
xref = xref[1:]
}
switch ref {
switch xref {
case "micro.codec.Frame":
gfile.P(`errmap["`, rsp.Name, `"] = &`, microCodecPackage.Ident("Frame"), "{}")
case "micro.errors.Error":
gfile.P(`errmap["`, rsp.Name, `"] = &`, microErrorsPackage.Ident("Error"), "{}")
default:
gfile.P(`errmap["`, rsp.Name, `"] = &`, ref, "{}")
ident, err := g.getGoIdentByXref(strings.TrimPrefix(schema.XRef, "."))
if err != nil {
log.Printf("cant find message by ref %s\n", schema.XRef)
continue
}
gfile.P(`errmap["`, rsp.Name, `"] = &`, gfile.QualifiedGoIdent(ident), "{}")
}
}
}
@ -300,7 +311,7 @@ func generateServiceServer(gfile *protogen.GeneratedFile, service *protogen.Serv
gfile.P()
}
func generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
for _, method := range service.Methods {
generateServerFuncSignature(gfile, serviceName, method, true)
@ -444,7 +455,7 @@ func generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protog
}
}
func generateServiceRegister(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceRegister(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
gfile.P("func Register", serviceName, "Server(s ", microServerPackage.Ident("Server"), ", sh ", serviceName, "Server, opts ...", microServerPackage.Ident("HandlerOption"), ") error {")
gfile.P("type ", unexport(serviceName), " interface {")
@ -508,7 +519,7 @@ func generateServerSignature(gfile *protogen.GeneratedFile, serviceName string,
gfile.P(args...)
}
func generateClientFuncSignature(gfile *protogen.GeneratedFile, serviceName string, method *protogen.Method) {
func (g *Generator) generateClientFuncSignature(gfile *protogen.GeneratedFile, serviceName string, method *protogen.Method) {
args := append([]interface{}{},
"func (c *",
unexport(serviceName),
@ -547,7 +558,7 @@ func generateClientSignature(gfile *protogen.GeneratedFile, serviceName string,
gfile.P(args...)
}
func generateServiceClientInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceClientInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
gfile.P("type ", serviceName, "Client interface {")
for _, method := range service.Methods {
@ -557,7 +568,7 @@ func generateServiceClientInterface(gfile *protogen.GeneratedFile, service *prot
gfile.P()
}
func generateServiceServerInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceServerInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
gfile.P("type ", serviceName, "Server interface {")
for _, method := range service.Methods {
@ -567,7 +578,7 @@ func generateServiceServerInterface(gfile *protogen.GeneratedFile, service *prot
gfile.P()
}
func generateServiceClientStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceClientStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
for _, method := range service.Methods {
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
@ -594,7 +605,7 @@ func generateServiceClientStreamInterface(gfile *protogen.GeneratedFile, service
}
}
func generateServiceServerStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceServerStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
for _, method := range service.Methods {
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
@ -621,7 +632,7 @@ func generateServiceServerStreamInterface(gfile *protogen.GeneratedFile, service
}
}
func generateServiceEndpoints(gfile *protogen.GeneratedFile, service *protogen.Service) {
func (g *Generator) generateServiceEndpoints(gfile *protogen.GeneratedFile, service *protogen.Service) {
serviceName := service.GoName
gfile.P("var (")
gfile.P(serviceName, "Name", "=", `"`, serviceName, `"`)
@ -755,3 +766,32 @@ func generateEndpoint(gfile *protogen.GeneratedFile, serviceName string, methodN
}
gfile.P(`Handler: "rpc",`)
}
func (g *Generator) getGoIdentByXref(xref string) (protogen.GoIdent, error) {
idx := strings.LastIndex(xref, ".")
pkg := xref[:idx]
msg := xref[idx+1:]
for _, file := range g.plugin.Files {
if strings.Compare(pkg, *(file.Proto.Package)) != 0 {
continue
}
if ident, err := getGoIdentByMessage(file.Messages, msg); err == nil {
return ident, nil
}
}
return protogen.GoIdent{}, fmt.Errorf("not found")
}
func getGoIdentByMessage(messages []*protogen.Message, msg string) (protogen.GoIdent, error) {
for _, message := range messages {
if strings.Compare(msg, message.GoIdent.GoName) == 0 {
return message.GoIdent, nil
}
if len(message.Messages) > 0 {
if ident, err := getGoIdentByMessage(message.Messages, msg); err == nil {
return ident, nil
}
}
}
return protogen.GoIdent{}, fmt.Errorf("not found")
}