From b25200536583d43e0f097b56ada3c2e2e7ff5c30 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 4 May 2026 15:51:31 -0700 Subject: [PATCH] feat(schemas): add initial CUE schema module --- .moon/proto/cue.toml | 24 +++++ .prototools | 2 + moon.yml | 59 ++++++++++++ schemas/core/cue_types_gen.go | 101 ++++++++++++++++++++ schemas/core/schema.cue | 89 +++++++++++++++++ schemas/cue.mod/module.cue | 4 + schemas/cue_types_gen.go | 44 +++++++++ schemas/embed.go | 105 +++++++++++++++++++++ schemas/embed_test.go | 60 ++++++++++++ schemas/go.mod | 25 +++++ schemas/go.sum | 54 +++++++++++ schemas/providers/incusos/cue_types_gen.go | 17 ++++ schemas/providers/incusos/schema.cue | 22 +++++ schemas/schema.cue | 40 ++++++++ 14 files changed, 646 insertions(+) create mode 100644 .moon/proto/cue.toml create mode 100644 schemas/core/cue_types_gen.go create mode 100644 schemas/core/schema.cue create mode 100644 schemas/cue.mod/module.cue create mode 100644 schemas/cue_types_gen.go create mode 100644 schemas/embed.go create mode 100644 schemas/embed_test.go create mode 100644 schemas/go.mod create mode 100644 schemas/go.sum create mode 100644 schemas/providers/incusos/cue_types_gen.go create mode 100644 schemas/providers/incusos/schema.cue create mode 100644 schemas/schema.cue diff --git a/.moon/proto/cue.toml b/.moon/proto/cue.toml new file mode 100644 index 0000000..5b6396f --- /dev/null +++ b/.moon/proto/cue.toml @@ -0,0 +1,24 @@ +name = "cue" +type = "cli" + +[platform.macos] +download-file = "cue_v{version}_darwin_{arch}.tar.gz" +exe-path = "cue" + +[platform.linux] +download-file = "cue_v{version}_linux_{arch}.tar.gz" +exe-path = "cue" + +[platform.windows] +download-file = "cue_v{version}_windows_{arch}.zip" +exe-path = "cue.exe" + +[install] +download-url = "https://github.com/cue-lang/cue/releases/download/v{version}/{download_file}" + +[install.arch] +aarch64 = "arm64" +x86_64 = "amd64" + +[resolve] +git-url = "https://github.com/cue-lang/cue" diff --git a/.prototools b/.prototools index ed4dc3f..5878b57 100644 --- a/.prototools +++ b/.prototools @@ -1,4 +1,6 @@ +cue = "=0.16.1" golangci-lint = "=2.11.4" [plugins.tools] +cue = "file://.moon/proto/cue.toml" golangci-lint = "file://.moon/proto/golangci-lint.toml" diff --git a/moon.yml b/moon.yml index 0863c71..e2cec37 100644 --- a/moon.yml +++ b/moon.yml @@ -25,6 +25,16 @@ fileGroups: go-sources: - 'cmd/**/*.go' - 'internal/**/*.go' + schema-config: + - '.prototools' + - '.moon/proto/cue.toml' + - 'schemas/go.mod' + - 'schemas/go.sum' + - 'schemas/cue.mod/**/*.cue' + schema-go-sources: + - 'schemas/**/*.go' + schema-sources: + - 'schemas/**/*.cue' lint-config: - '.golangci.yml' - '.prototools' @@ -67,12 +77,61 @@ tasks: - '@group(go-config)' - '@group(go-sources)' + schemas-mod-check: + script: 'cd schemas && proto run cue -- mod tidy --check' + inputs: + - '@group(schema-config)' + - '@group(schema-sources)' + options: + cache: false + + schemas-vet: + script: 'cd schemas && proto run cue -- vet -c=false ./...' + inputs: + - '@group(schema-config)' + - '@group(schema-sources)' + options: + cache: false + + schemas-generate: + script: 'cd schemas && proto run cue -- exp gengotypes ./... && gofmt -w $(find . -name "*.go" -type f)' + inputs: + - '@group(schema-config)' + - '@group(schema-sources)' + outputs: + - 'schemas/**/*.go' + options: + cache: false + + schemas-generate-check: + script: 'cd schemas && proto run cue -- exp gengotypes ./... && gofmt -w $(find . -name "*.go" -type f) && git -C .. diff --exit-code -- "schemas/**/*.go"' + inputs: + - '@group(schema-config)' + - '@group(schema-sources)' + - '@group(schema-go-sources)' + options: + cache: false + + schemas-test: + deps: + - 'root:schemas-generate-check' + script: 'cd schemas && go test ./...' + toolchains: ['go'] + inputs: + - '@group(schema-config)' + - '@group(schema-go-sources)' + options: + cache: false + check: deps: - 'root:format' - 'root:lint' - 'root:build' - 'root:test' + - 'root:schemas-mod-check' + - 'root:schemas-vet' + - 'root:schemas-test' options: cache: false runInCI: true diff --git a/schemas/core/cue_types_gen.go b/schemas/core/cue_types_gen.go new file mode 100644 index 0000000..c55f3e3 --- /dev/null +++ b/schemas/core/cue_types_gen.go @@ -0,0 +1,101 @@ +// Code generated by "cue exp gengotypes"; DO NOT EDIT. + +package core + +type Name string + +type VariantName string + +type ArtifactKey string + +type Architecture string + +type ArtifactFormat string + +type ProviderName string + +type Image struct { + Name Name `json:"name"` + + Description string `json:"description,omitempty"` + + Labels map[string]string `json:"labels,omitempty"` + + Annotations map[string]string `json:"annotations,omitempty"` +} + +type OutputDefaults struct { + // Defaults to ./dist unless overridden by CLI flag or config. + Dir string `json:"dir,omitempty"` +} + +type PublishIntent struct { + // Optional override if imgsrv image identity should differ from image.name. + ImageName Name `json:"imageName,omitempty"` + + Labels map[string]string `json:"labels,omitempty"` + + Annotations map[string]string `json:"annotations,omitempty"` +} + +type ArtifactIntent struct { + Variant VariantName `json:"variant"` + + Provider ProviderName `json:"provider"` + + Os string `json:"os"` + + Architecture Architecture `json:"architecture"` + + Format ArtifactFormat `json:"format"` + + MediaType string `json:"mediaType,omitempty"` + + Filename string `json:"filename,omitempty"` + + Labels map[string]string `json:"labels,omitempty"` + + Annotations map[string]string `json:"annotations,omitempty"` +} + +type ResolvedArtifact struct { + ArtifactKey ArtifactKey `json:"artifactKey"` + + ImageName string `json:"imageName"` + + Version string `json:"version,omitempty"` + + Variant VariantName `json:"variant"` + + Provider ProviderName `json:"provider"` + + Os string `json:"os"` + + Architecture Architecture `json:"architecture"` + + Format ArtifactFormat `json:"format"` + + MediaType string `json:"mediaType"` + + Path string `json:"path"` + + Labels map[string]string `json:"labels,omitempty"` + + Annotations map[string]string `json:"annotations,omitempty"` + + // Populated after build. + Digest string `json:"digest,omitempty"` + + Size int64 `json:"size,omitempty"` +} + +type ResolvedPlan struct { + Image Image `json:"image"` + + // Supplied by CLI or release environment. Not required in the config file. + Version string `json:"version,omitempty"` + + OutputDir string `json:"outputDir"` + + Artifacts map[ArtifactKey]ResolvedArtifact `json:"artifacts"` +} diff --git a/schemas/core/schema.cue b/schemas/core/schema.cue new file mode 100644 index 0000000..0eb1a87 --- /dev/null +++ b/schemas/core/schema.cue @@ -0,0 +1,89 @@ +package core + +#Name: =~"^[a-z0-9][a-z0-9._-]*[a-z0-9]$" | error("name must start and end with lowercase alphanumeric characters and contain only lowercase letters, digits, dots, underscores, or hyphens") + +#VariantName: =~"^[A-Za-z0-9][A-Za-z0-9._-]*$" | error("variant name must start with an alphanumeric character and contain only letters, digits, dots, underscores, or hyphens") + +#ArtifactKey: =~"^[A-Za-z0-9][A-Za-z0-9._-]*$" | error("artifact key must start with an alphanumeric character and contain only letters, digits, dots, underscores, or hyphens") + +#Architecture: "amd64" | "arm64" | error("architecture must be one of: amd64, arm64") + +#ArtifactFormat: "raw" | "raw.gz" | "qcow2" | "qcow2.gz" | "iso" | error("artifact format must be one of: raw, raw.gz, qcow2, qcow2.gz, iso") + +#ProviderName: "incusos" | error("provider must be incusos") + +#Image: { + name: #Name + + description?: string + + labels?: [string]: string + annotations?: [string]: string +} + +#OutputDefaults: { + // Defaults to ./dist unless overridden by CLI flag or config. + dir?: string | *"dist" +} + +#PublishIntent: { + // Optional override if imgsrv image identity should differ from image.name. + imageName?: #Name + + labels?: [string]: string + annotations?: [string]: string +} + +#ArtifactIntent: { + variant: #VariantName + + provider: #ProviderName + os: string + + architecture: #Architecture + format: #ArtifactFormat + + mediaType?: string + filename?: string + + labels?: [string]: string + annotations?: [string]: string +} + +#ResolvedArtifact: { + artifactKey: #ArtifactKey + + imageName: string + version?: string + + variant: #VariantName + provider: #ProviderName + os: string + architecture: #Architecture + format: #ArtifactFormat + + mediaType: string + path: string + + labels?: [string]: string + annotations?: [string]: string + + // Populated after build. + digest?: string + size?: int +} + +#ResolvedPlan: { + image: #Image + + // Supplied by CLI or release environment. Not required in the config file. + version?: string + + outputDir: string + + artifacts: { + [ArtifactKey=#ArtifactKey]: #ResolvedArtifact & { + artifactKey: ArtifactKey + } + } @go(,type=map[ArtifactKey]ResolvedArtifact) +} diff --git a/schemas/cue.mod/module.cue b/schemas/cue.mod/module.cue new file mode 100644 index 0000000..4cc588d --- /dev/null +++ b/schemas/cue.mod/module.cue @@ -0,0 +1,4 @@ +module: "github.com/meigma/imgcli/schemas@v0" +language: { + version: "v0.16.1" +} diff --git a/schemas/cue_types_gen.go b/schemas/cue_types_gen.go new file mode 100644 index 0000000..7d057f2 --- /dev/null +++ b/schemas/cue_types_gen.go @@ -0,0 +1,44 @@ +// Code generated by "cue exp gengotypes"; DO NOT EDIT. + +package schemas + +import ( + "github.com/meigma/imgcli/schemas/core" + incusosprovider "github.com/meigma/imgcli/schemas/providers/incusos" +) + +type Config struct { + ApiVersion string `json:"apiVersion"` + + Kind string `json:"kind"` + + Image core.Image `json:"image"` + + Output *core.OutputDefaults `json:"output,omitempty"` + + Publish *core.PublishIntent `json:"publish,omitempty"` + + Incusos *incusosprovider.Config `json:"incusos,omitempty"` +} + +type Image core.Image + +type OutputDefaults core.OutputDefaults + +type PublishIntent core.PublishIntent + +type ArtifactIntent core.ArtifactIntent + +type ResolvedArtifact core.ResolvedArtifact + +type ResolvedPlan core.ResolvedPlan + +type Name core.Name + +type VariantName core.VariantName + +type ArtifactKey core.ArtifactKey + +type Architecture core.Architecture + +type ArtifactFormat core.ArtifactFormat diff --git a/schemas/embed.go b/schemas/embed.go new file mode 100644 index 0000000..ffcb013 --- /dev/null +++ b/schemas/embed.go @@ -0,0 +1,105 @@ +package schemas + +import ( + "embed" + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" + + "cuelang.org/go/cue" + "cuelang.org/go/cue/load" +) + +const ( + // ModulePath is the CUE module path embedded in this Go package. + ModulePath = "github.com/meigma/imgcli/schemas@v0" + + embeddedModuleDir = "imgcli-schemas-embedded" +) + +//go:embed cue.mod/module.cue *.cue core/*.cue providers/*/*.cue +var embeddedModule embed.FS + +// ModuleFS returns the embedded CUE module files. +func ModuleFS() fs.FS { + return embeddedModule +} + +// LoadSchema loads the embedded CUE module into ctx and returns the root package value. +func LoadSchema(ctx *cue.Context) (cue.Value, error) { + if ctx == nil { + return cue.Value{}, errors.New("schemas: nil CUE context") + } + + overlay, err := embeddedOverlay() + if err != nil { + return cue.Value{}, err + } + + moduleRoot := embeddedModuleRoot() + insts := load.Instances([]string{"."}, &load.Config{ + Dir: moduleRoot, + ModuleRoot: moduleRoot, + Module: ModulePath, + Overlay: overlay, + Env: []string{}, + }) + if len(insts) != 1 { + return cue.Value{}, fmt.Errorf("schemas: expected one CUE instance, got %d", len(insts)) + } + if err := insts[0].Err; err != nil { + return cue.Value{}, fmt.Errorf("schemas: load embedded CUE module: %w", err) + } + + value := ctx.BuildInstance(insts[0]) + if err := value.Err(); err != nil { + return cue.Value{}, fmt.Errorf("schemas: build embedded CUE module: %w", err) + } + return value, nil +} + +// ConfigSchema returns the embedded schemas.#Config definition. +func ConfigSchema(ctx *cue.Context) (cue.Value, error) { + value, err := LoadSchema(ctx) + if err != nil { + return cue.Value{}, err + } + + config := value.LookupPath(cue.ParsePath("#Config")) + if err := config.Err(); err != nil { + return cue.Value{}, fmt.Errorf("schemas: lookup #Config: %w", err) + } + return config, nil +} + +func embeddedOverlay() (map[string]load.Source, error) { + moduleRoot := embeddedModuleRoot() + overlay := map[string]load.Source{} + + err := fs.WalkDir(embeddedModule, ".", func(path string, entry fs.DirEntry, err error) error { + if err != nil { + return err + } + if entry.IsDir() || !strings.HasSuffix(path, ".cue") { + return nil + } + + data, err := fs.ReadFile(embeddedModule, path) + if err != nil { + return err + } + overlay[filepath.Join(moduleRoot, filepath.FromSlash(path))] = load.FromBytes(data) + return nil + }) + if err != nil { + return nil, fmt.Errorf("schemas: read embedded CUE module: %w", err) + } + return overlay, nil +} + +func embeddedModuleRoot() string { + return filepath.Join(os.TempDir(), embeddedModuleDir) +} diff --git a/schemas/embed_test.go b/schemas/embed_test.go new file mode 100644 index 0000000..964a63a --- /dev/null +++ b/schemas/embed_test.go @@ -0,0 +1,60 @@ +package schemas + +import ( + "bytes" + "io/fs" + "testing" + + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" +) + +func TestModuleFS(t *testing.T) { + moduleFile, err := fs.ReadFile(ModuleFS(), "cue.mod/module.cue") + if err != nil { + t.Fatalf("read module file: %v", err) + } + if !bytes.Contains(moduleFile, []byte(ModulePath)) { + t.Fatalf("module file does not contain module path %q", ModulePath) + } +} + +func TestConfigSchema(t *testing.T) { + ctx := cuecontext.New() + + schema, err := ConfigSchema(ctx) + if err != nil { + t.Fatalf("load config schema: %v", err) + } + if got := schema.IncompleteKind(); got != cue.StructKind { + t.Fatalf("#Config kind = %v, want %v", got, cue.StructKind) + } + + input := ctx.CompileString(` +apiVersion: "imgcli.meigma.io/v0alpha1" +kind: "ImagePlan" +image: { + name: "test-image" +} +incusos: variants: default: artifact: { + architecture: "amd64" + format: "raw" +} +`) + if err := input.Err(); err != nil { + t.Fatalf("compile input: %v", err) + } + + value := schema.Unify(input) + if err := value.Validate(cue.Concrete(false)); err != nil { + t.Fatalf("validate config: %v", err) + } + + provider, err := value.LookupPath(cue.ParsePath("incusos.variants.default.artifact.provider")).String() + if err != nil { + t.Fatalf("lookup provider: %v", err) + } + if provider != "incusos" { + t.Fatalf("provider = %q, want %q", provider, "incusos") + } +} diff --git a/schemas/go.mod b/schemas/go.mod new file mode 100644 index 0000000..52dae11 --- /dev/null +++ b/schemas/go.mod @@ -0,0 +1,25 @@ +module github.com/meigma/imgcli/schemas + +go 1.26 + +require cuelang.org/go v0.16.1 + +require ( + cuelabs.dev/go/oci/ociregistry v0.0.0-20251212221603-3adeb8663819 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/emicklei/proto v1.14.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/protocolbuffers/txtpbfmt v0.0.0-20260217160748-a481f6a22f94 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/text v0.35.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect +) diff --git a/schemas/go.sum b/schemas/go.sum new file mode 100644 index 0000000..f72201d --- /dev/null +++ b/schemas/go.sum @@ -0,0 +1,54 @@ +cuelabs.dev/go/oci/ociregistry v0.0.0-20251212221603-3adeb8663819 h1:Zh+Ur3OsoWpvALHPLT45nOekHkgOt+IOfutBbPqM17I= +cuelabs.dev/go/oci/ociregistry v0.0.0-20251212221603-3adeb8663819/go.mod h1:WjmQxb+W6nVNCgj8nXrF24lIz95AHwnSl36tpjDZSU8= +cuelang.org/go v0.16.1 h1:iPN1lHZd2J0hjcr8hfq9PnIGk7VfPkKFfxH4de+m9sE= +cuelang.org/go v0.16.1/go.mod h1:/aW3967FeWC5Hc1cDrN4Z4ICVApdMi83wO5L3uF/1hM= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/emicklei/proto v1.14.3 h1:zEhlzNkpP8kN6utonKMzlPfIvy82t5Kb9mufaJxSe1Q= +github.com/emicklei/proto v1.14.3/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/protocolbuffers/txtpbfmt v0.0.0-20260217160748-a481f6a22f94 h1:2PC6Ql3jipz1KvBlqUHjjk6v4aMwE86mfDu1XMH0LR8= +github.com/protocolbuffers/txtpbfmt v0.0.0-20260217160748-a481f6a22f94/go.mod h1:JSbkp0BviKovYYt9XunS95M3mLPibE9bGg+Y95DsEEY= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= diff --git a/schemas/providers/incusos/cue_types_gen.go b/schemas/providers/incusos/cue_types_gen.go new file mode 100644 index 0000000..5aa5541 --- /dev/null +++ b/schemas/providers/incusos/cue_types_gen.go @@ -0,0 +1,17 @@ +// Code generated by "cue exp gengotypes"; DO NOT EDIT. + +package incusos + +import ( + "github.com/meigma/imgcli/schemas/core" +) + +type Variant struct { + Artifact core.ArtifactIntent `json:"artifact"` +} + +type Config struct { + Defaults any/* CUE top */ `json:"defaults,omitempty"` + + Variants map[core.VariantName]Variant `json:"variants"` +} diff --git a/schemas/providers/incusos/schema.cue b/schemas/providers/incusos/schema.cue new file mode 100644 index 0000000..b26edbd --- /dev/null +++ b/schemas/providers/incusos/schema.cue @@ -0,0 +1,22 @@ +package incusos + +import "github.com/meigma/imgcli/schemas/core" + +#Variant: { + artifact: core.#ArtifactIntent & { + provider: "incusos" + os: "incusos" + } @go(,type="github.com/meigma/imgcli/schemas/core".ArtifactIntent) +} + +#Config: { + defaults?: _ + + variants: { + [VariantName=core.#VariantName]: #Variant & { + artifact: { + variant: VariantName + } + } + } @go(,type=map["github.com/meigma/imgcli/schemas/core".VariantName]Variant) +} diff --git a/schemas/schema.cue b/schemas/schema.cue new file mode 100644 index 0000000..1861d6f --- /dev/null +++ b/schemas/schema.cue @@ -0,0 +1,40 @@ +package schemas + +import ( + "github.com/meigma/imgcli/schemas/core" + incusosprovider "github.com/meigma/imgcli/schemas/providers/incusos" +) + +#Config: { + apiVersion: "imgcli.meigma.io/v0alpha1" + kind: "ImagePlan" + + image: core.#Image + + output?: core.#OutputDefaults @go(,optional=nillable) + publish?: core.#PublishIntent @go(,optional=nillable) + + incusos?: incusosprovider.#Config @go(,optional=nillable) +} + +#Image: core.#Image + +#OutputDefaults: core.#OutputDefaults + +#PublishIntent: core.#PublishIntent + +#ArtifactIntent: core.#ArtifactIntent + +#ResolvedArtifact: core.#ResolvedArtifact + +#ResolvedPlan: core.#ResolvedPlan + +#Name: core.#Name + +#VariantName: core.#VariantName + +#ArtifactKey: core.#ArtifactKey + +#Architecture: core.#Architecture + +#ArtifactFormat: core.#ArtifactFormat