Skip to content

Commit 8b1ce92

Browse files
committed
feat: embed compiled OpenAPI specs in Go applications.
1 parent f7dca42 commit 8b1ce92

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

internal/compiler/compiler.go

+46
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package compiler
33
import (
44
"context"
55
"fmt"
6+
"html/template"
67
"io/fs"
78
"io/ioutil"
89
"log"
@@ -268,6 +269,7 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
268269
return fmt.Errorf("failed to create output directory: %w", err)
269270
}
270271
log.Printf("compiling API %s to output versions", apiName)
272+
var versionSpecFiles []string
271273
for rcIndex, rc := range api.resources {
272274
specVersions, err := vervet.LoadSpecVersionsFileset(rc.matchedFiles)
273275
if err != nil {
@@ -312,6 +314,11 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
312314
return buildErr(err)
313315
}
314316
jsonSpecPath := versionDir + "/spec.json"
317+
jsonEmbedPath, err := filepath.Rel(api.output.path, jsonSpecPath)
318+
if err != nil {
319+
return buildErr(err)
320+
}
321+
versionSpecFiles = append(versionSpecFiles, jsonEmbedPath)
315322
err = ioutil.WriteFile(jsonSpecPath, jsonBuf, 0644)
316323
if err != nil {
317324
return buildErr(err)
@@ -326,6 +333,11 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
326333
return buildErr(err)
327334
}
328335
yamlSpecPath := versionDir + "/spec.yaml"
336+
yamlEmbedPath, err := filepath.Rel(api.output.path, yamlSpecPath)
337+
if err != nil {
338+
return buildErr(err)
339+
}
340+
versionSpecFiles = append(versionSpecFiles, yamlEmbedPath)
329341
err = ioutil.WriteFile(yamlSpecPath, yamlBuf, 0644)
330342
if err != nil {
331343
return buildErr(err)
@@ -334,9 +346,43 @@ func (c *Compiler) Build(ctx context.Context, apiName string) error {
334346
}
335347
}
336348
}
349+
err = c.writeEmbedGo(filepath.Base(api.output.path), api, versionSpecFiles)
350+
if err != nil {
351+
return fmt.Errorf("failed to create embed.go: %w", err)
352+
}
337353
return nil
338354
}
339355

356+
func (c *Compiler) writeEmbedGo(pkgName string, a *api, versionSpecFiles []string) error {
357+
f, err := os.Create(filepath.Join(a.output.path, "embed.go"))
358+
if err != nil {
359+
return err
360+
}
361+
defer f.Close()
362+
return embedGoTmpl.Execute(f, struct {
363+
Package string
364+
API *api
365+
VersionSpecFiles []string
366+
}{
367+
Package: pkgName,
368+
API: a,
369+
VersionSpecFiles: versionSpecFiles,
370+
})
371+
}
372+
373+
var embedGoTmpl = template.Must(template.New("embed.go").Parse(`
374+
package {{ .Package }}
375+
376+
import "embed"
377+
378+
// Embed compiled OpenAPI specs in Go projects.
379+
380+
{{ range .VersionSpecFiles -}}
381+
//go:embed {{ . }}
382+
{{ end -}}
383+
var Versions embed.FS
384+
`))
385+
340386
// BuildAll builds all APIs in the project.
341387
func (c *Compiler) BuildAll(ctx context.Context) error {
342388
return c.apisEach(ctx, c.Build)

testdata/embed_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package testdata
2+
3+
import (
4+
"testing"
5+
6+
qt "github.com/frankban/quicktest"
7+
"github.com/getkin/kin-openapi/openapi3"
8+
9+
"github.com/snyk/vervet/testdata/output"
10+
)
11+
12+
func TestEmbedding(t *testing.T) {
13+
c := qt.New(t)
14+
15+
specYAML, err := output.Versions.ReadFile("2021-06-13~experimental/spec.yaml")
16+
c.Assert(err, qt.IsNil)
17+
l := openapi3.NewLoader()
18+
_, err = l.LoadFromData(specYAML)
19+
c.Assert(err, qt.IsNil)
20+
}

testdata/output/embed.go

+32
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)