// 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 }