Skip to content

Commit

Permalink
Merge pull request #54 from snyk/feat/embedding-for-go
Browse files Browse the repository at this point in the history
feat: embed compiled OpenAPI specs in Go applications.
  • Loading branch information
cmars authored Oct 28, 2021
2 parents f7dca42 + 8b1ce92 commit 7bbc0a6
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
46 changes: 46 additions & 0 deletions internal/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package compiler
import (
"context"
"fmt"
"html/template"
"io/fs"
"io/ioutil"
"log"
Expand Down Expand Up @@ -268,6 +269,7 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
return fmt.Errorf("failed to create output directory: %w", err)
}
log.Printf("compiling API %s to output versions", apiName)
var versionSpecFiles []string
for rcIndex, rc := range api.resources {
specVersions, err := vervet.LoadSpecVersionsFileset(rc.matchedFiles)
if err != nil {
Expand Down Expand Up @@ -312,6 +314,11 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
return buildErr(err)
}
jsonSpecPath := versionDir + "/spec.json"
jsonEmbedPath, err := filepath.Rel(api.output.path, jsonSpecPath)
if err != nil {
return buildErr(err)
}
versionSpecFiles = append(versionSpecFiles, jsonEmbedPath)
err = ioutil.WriteFile(jsonSpecPath, jsonBuf, 0644)
if err != nil {
return buildErr(err)
Expand All @@ -326,6 +333,11 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
return buildErr(err)
}
yamlSpecPath := versionDir + "/spec.yaml"
yamlEmbedPath, err := filepath.Rel(api.output.path, yamlSpecPath)
if err != nil {
return buildErr(err)
}
versionSpecFiles = append(versionSpecFiles, yamlEmbedPath)
err = ioutil.WriteFile(yamlSpecPath, yamlBuf, 0644)
if err != nil {
return buildErr(err)
Expand All @@ -334,9 +346,43 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
}
}
}
err = c.writeEmbedGo(filepath.Base(api.output.path), api, versionSpecFiles)
if err != nil {
return fmt.Errorf("failed to create embed.go: %w", err)
}
return nil
}

func (c *Compiler) writeEmbedGo(pkgName string, a *api, versionSpecFiles []string) error {
f, err := os.Create(filepath.Join(a.output.path, "embed.go"))
if err != nil {
return err
}
defer f.Close()
return embedGoTmpl.Execute(f, struct {
Package string
API *api
VersionSpecFiles []string
}{
Package: pkgName,
API: a,
VersionSpecFiles: versionSpecFiles,
})
}

var embedGoTmpl = template.Must(template.New("embed.go").Parse(`
package {{ .Package }}
import "embed"
// Embed compiled OpenAPI specs in Go projects.
{{ range .VersionSpecFiles -}}
//go:embed {{ . }}
{{ end -}}
var Versions embed.FS
`))

// BuildAll builds all APIs in the project.
func (c *Compiler) BuildAll(ctx context.Context) error {
return c.apisEach(ctx, c.Build)
Expand Down
20 changes: 20 additions & 0 deletions testdata/embed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package testdata

import (
"testing"

qt "github.com/frankban/quicktest"
"github.com/getkin/kin-openapi/openapi3"

"github.com/snyk/vervet/testdata/output"
)

func TestEmbedding(t *testing.T) {
c := qt.New(t)

specYAML, err := output.Versions.ReadFile("2021-06-13~experimental/spec.yaml")
c.Assert(err, qt.IsNil)
l := openapi3.NewLoader()
_, err = l.LoadFromData(specYAML)
c.Assert(err, qt.IsNil)
}
32 changes: 32 additions & 0 deletions testdata/output/embed.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7bbc0a6

Please sign in to comment.