| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // A stand-alone Go module that generates ../schema.go using the upstream |
| // x509-limbo JSON schema document. |
| // |
| // We maintain this in a separate Go module and vendor the resulting generated |
| // .go code to avoid the standard library taking a direct dependency on the |
| // C2SP/x509-limbo or atombender/go-jsonschema modules. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "log" |
| "os" |
| "os/exec" |
| "path/filepath" |
| |
| "github.com/atombender/go-jsonschema/pkg/generator" |
| ) |
| |
| // x509LimboVersion is the github.com/C2SP/x509-limbo module version used to |
| // generate ../schema.go. Update this to retarget a different upstream revision. |
| // |
| // x509-limbo publishes no Go packages, so we can't pin the version via a |
| // `require` directive (any `go mod tidy` would drop it) or a `tool` directive |
| // (no main package). Instead we fetch the module on demand via `go mod |
| // download` below, and propagate this constant to ../schemaversion.go so the |
| // runtime test fetches a matching revision. |
| const x509LimboVersion = "v0.0.0-20260522003327-feb7caccc1af" |
| |
| const x509LimboModule = "github.com/C2SP/x509-limbo" |
| |
| func main() { |
| limboDir, err := downloadModuleDir(x509LimboModule, x509LimboVersion) |
| if err != nil { |
| log.Fatalf("failed to fetch %s@%s: %v", x509LimboModule, x509LimboVersion, err) |
| } |
| |
| outputName := "schema.go" |
| gen, err := generator.New(generator.Config{ |
| DefaultPackageName: "x509limbo", |
| DefaultOutputName: outputName, |
| Tags: []string{"json"}, |
| Warner: func(message string) { |
| log.Printf("go-jsonschema: %s", message) |
| }, |
| }) |
| if err != nil { |
| log.Fatal(err) |
| } |
| |
| schemaFile := filepath.Join(limboDir, "limbo-schema.json") |
| if err := gen.DoFile(schemaFile); err != nil { |
| log.Fatalf("error processing limbo-schema.json: %v\n", err) |
| } |
| |
| sources, err := gen.Sources() |
| if err != nil { |
| log.Fatalf("error generating sources: %v\n", err) |
| } |
| if sourceCount := len(sources); sourceCount != 1 { |
| log.Fatalf("expected to generate 1 source file, got %d\n", sourceCount) |
| } |
| content, ok := sources[outputName] |
| if !ok { |
| log.Fatalf("missing generated %q output file source", outputName) |
| } |
| outFile := filepath.Join("../", outputName) |
| if err := os.WriteFile(outFile, content, 0644); err != nil { |
| log.Fatalf("error writing file %s: %v\n", outFile, err) |
| } |
| |
| // Write a sibling file recording the x509-limbo module version that the |
| // generated schema.go was produced against. The x509limbo package uses |
| // this constant to fetch matching test vectors at runtime. We avoid reading |
| // go.sum at test time because it might not be available (e.g. if the test |
| // binary was copied to a remote machine). |
| const versionFile = "../schemaversion.go" |
| versionSrc := fmt.Sprintf(`// Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Code generated by _schema/schema_gen.go, DO NOT EDIT. |
| |
| package x509limbo |
| |
| // X509LimboModule is the module path of the upstream x509-limbo project. |
| const X509LimboModule = %q |
| |
| // X509LimboVersion is the X509LimboModule version that schema.go was |
| // generated against. |
| const X509LimboVersion = %q |
| `, x509LimboModule, x509LimboVersion) |
| if err := os.WriteFile(versionFile, []byte(versionSrc), 0644); err != nil { |
| log.Fatalf("writing %s: %v", versionFile, err) |
| } |
| } |
| |
| // downloadModuleDir runs `go mod download` to ensure module@version is present |
| // in the module cache and returns the directory containing its source tree. |
| func downloadModuleDir(module, version string) (string, error) { |
| cmd := exec.Command("go", "mod", "download", "-json", module+"@"+version) |
| var stderr bytes.Buffer |
| cmd.Stderr = &stderr |
| out, err := cmd.Output() |
| if err != nil { |
| return "", fmt.Errorf("%w\n%s", err, stderr.String()) |
| } |
| var info struct { |
| Dir string |
| Error string |
| } |
| if err := json.Unmarshal(out, &info); err != nil { |
| return "", fmt.Errorf("parsing go mod download output: %w", err) |
| } |
| if info.Error != "" { |
| return "", fmt.Errorf("%s", info.Error) |
| } |
| return info.Dir, nil |
| } |