From 495e53e52508e161713888827473f46b53a16b56 Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Mon, 12 Feb 2024 15:32:27 +0100 Subject: [PATCH] feat!: Rework config Rename `xpackages` to `builds` and `dockers` to `pushes`. Fix bug that output directory was not created before calling crank. --- cmd/crossplanereleaser/build.go | 18 ++++++++++------ cmd/crossplanereleaser/release.go | 31 ++++++++++++++++++++------- config/v1/config.go | 14 ++++++------ internal/build/build_crank.go | 3 ++- internal/config/parse.go | 18 ++++++++-------- internal/config/project_properties.go | 2 -- internal/config/template.go | 10 ++++----- 7 files changed, 57 insertions(+), 39 deletions(-) diff --git a/cmd/crossplanereleaser/build.go b/cmd/crossplanereleaser/build.go index 13dc1c9..297aca5 100644 --- a/cmd/crossplanereleaser/build.go +++ b/cmd/crossplanereleaser/build.go @@ -34,20 +34,24 @@ func (c *buildCmd) Run(fsys afero.Fs) error { } func (c *buildCmd) buildPackages(ctx context.Context, fsys afero.Fs, cfg *v1.Config) error { - for _, pkgCfg := range cfg.XPackages { + for _, b := range cfg.Builds { buildCfg := &build.PackageBuildConfig{ - PackageDir: pkgCfg.Dir, - ExamplesDir: pkgCfg.Examples, - OutputPath: getPackageOutputPath(cfg, &pkgCfg), + PackageDir: b.Dir, + ExamplesDir: b.Examples, + OutputPath: getPackageOutputPath(cfg, &b), + } + // We need to call mkdir here because crank doesn't do it for us + if err := fsys.MkdirAll(filepath.Dir(buildCfg.OutputPath), 0755); err != nil { + return err } err := c.builder.BuildPackage(ctx, buildCfg) if err != nil { - return errors.Wrapf(err, "cannot build package %q", pkgCfg.ID) + return errors.Wrapf(err, "cannot build package %q", b.ID) } } return nil } -func getPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { - return filepath.Join(cfg.Dist, pkgCfg.ID, pkgCfg.NameTemplate) +func getPackageOutputPath(cfg *v1.Config, build *v1.BuildConfig) string { + return filepath.Join(cfg.Dist, build.ID, build.NameTemplate) } diff --git a/cmd/crossplanereleaser/release.go b/cmd/crossplanereleaser/release.go index b158d0f..00fa558 100644 --- a/cmd/crossplanereleaser/release.go +++ b/cmd/crossplanereleaser/release.go @@ -50,18 +50,33 @@ func (c *releaseCmd) Run(fsys afero.Fs) error { return errors.Wrap(err, "build failed") } } - return c.publishPackages(ctx, cfg) + return errors.Wrap(c.publishPackages(ctx, cfg), "cannot push images") } func (c *releaseCmd) publishPackages(ctx context.Context, cfg *v1.Config) error { - for _, pkgCfg := range cfg.XPackages { - filename := getPackageOutputPath(cfg, &pkgCfg) - ref, err := name.ParseReference(pkgCfg.NameTemplate) - if err != nil { - return errors.Wrap(err, "cannot parse image name") + for _, push := range cfg.Pushes { + build := getBuildConfigByID(cfg, push.Build) + if build == nil { + return errors.Errorf("no build with ID %q", push.Build) } - if err := c.publisher.PublishPackage(ctx, filename, ref); err != nil { - return errors.Wrapf(err, "cannot publish package %q", pkgCfg.ID) + filename := getPackageOutputPath(cfg, build) + for _, img := range push.ImageTemplates { + ref, err := name.ParseReference(img) + if err != nil { + return errors.Wrap(err, "cannot parse image name") + } + if err := c.publisher.PublishPackage(ctx, filename, ref); err != nil { + return errors.Wrapf(err, "cannot publish package %q", build.ID) + } + } + } + return nil +} + +func getBuildConfigByID(cfg *v1.Config, buildID string) *v1.BuildConfig { + for _, b := range cfg.Builds { + if b.ID == buildID { + return &b } } return nil diff --git a/config/v1/config.go b/config/v1/config.go index 180e6b9..4e7e767 100644 --- a/config/v1/config.go +++ b/config/v1/config.go @@ -1,20 +1,20 @@ package v1 type Config struct { - ProjectName string `json:"project_name"` - XPackages []XPackageConfig `json:"xpackages"` - Dist string `json:"dist"` - Dockers []DockerConfig `json:"dockers"` + ProjectName string `json:"project_name"` + Dist string `json:"dist"` + Builds []BuildConfig `json:"builds"` + Pushes []PushConfig `json:"pushes"` } -type XPackageConfig struct { +type BuildConfig struct { ID string `json:"id"` Dir string `json:"dir"` Examples string `json:"examples"` NameTemplate string `json:"name_template"` } -type DockerConfig struct { - IDs []string `json:"ids"` +type PushConfig struct { + Build string `json:"build"` ImageTemplates []string `json:"image_templates"` } diff --git a/internal/build/build_crank.go b/internal/build/build_crank.go index 71cd511..a3020bb 100644 --- a/internal/build/build_crank.go +++ b/internal/build/build_crank.go @@ -28,8 +28,9 @@ func (c CrankCLIBackend) exec(ctx context.Context, args ...string) error { func (c *CrankCLIBackend) BuildPackage(ctx context.Context, cfg *PackageBuildConfig) error { args := []string{ + "xpkg", "build", fmt.Sprintf("--package-root=%s", cfg.PackageDir), - fmt.Sprintf("--output=%s", cfg.OutputPath), + fmt.Sprintf("--package-file=%s", cfg.OutputPath), } if cfg.ExamplesDir != "" { args = append(args, fmt.Sprintf("--examples-root=%s", cfg.ExamplesDir)) diff --git a/internal/config/parse.go b/internal/config/parse.go index c445b6d..9054ab8 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -33,7 +33,7 @@ func Parse(fsys afero.Fs, filename string) (*v1.Config, error) { return nil, err } cfg := &v1.Config{} - if err := yaml.Unmarshal(raw, cfg); err != nil { + if err := yaml.UnmarshalStrict(raw, cfg, yaml.DisallowUnknownFields); err != nil { return nil, err } err = fillDefaults(filename, cfg) @@ -44,18 +44,18 @@ func fillDefaults(filename string, cfg *v1.Config) error { cfg.ProjectName = valueOrFallback(cfg.ProjectName, filepath.Base(filepath.Dir(filename))) cfg.Dist = valueOrFallback(cfg.Dist, "dist") - for i := range cfg.XPackages { - cfg.XPackages[i].Examples = valueOrFallback(cfg.XPackages[i].Examples, "examples") + for i := range cfg.Builds { + cfg.Builds[i].Examples = valueOrFallback(cfg.Builds[i].Examples, "examples") - if cfg.XPackages[i].ID == "" { - if len(cfg.XPackages) > 1 { - return errors.New("package ID is required if there is more than one package") + if cfg.Builds[i].ID == "" { + if len(cfg.Builds) > 1 { + return errors.New("build ID is required if there is more than one build") } - // If there is only one package use the project name as ID - cfg.XPackages[i].ID = cfg.ProjectName + // If there is only one build use the project name as ID + cfg.Builds[i].ID = cfg.ProjectName } - cfg.XPackages[i].NameTemplate = valueOrFallback(cfg.XPackages[i].NameTemplate, cfg.XPackages[i].ID) + cfg.Builds[i].NameTemplate = valueOrFallback(cfg.Builds[i].NameTemplate, cfg.Builds[i].ID+".xpkg") } return nil } diff --git a/internal/config/project_properties.go b/internal/config/project_properties.go index 06aa086..ea78255 100644 --- a/internal/config/project_properties.go +++ b/internal/config/project_properties.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "os" "strings" @@ -67,7 +66,6 @@ func getEnvMap() map[string]string { m := make(map[string]string, len(environ)) for _, s := range os.Environ() { split := strings.SplitN(s, "=", 2) - fmt.Printf("%v\n", split) m[split[0]] = split[1] } return m diff --git a/internal/config/template.go b/internal/config/template.go index 7b09e4b..69a5904 100644 --- a/internal/config/template.go +++ b/internal/config/template.go @@ -8,18 +8,18 @@ import ( ) func RenderConfigTemplates(cfg *v1.Config, props *ProjectProperties) error { - for di, docker := range cfg.Dockers { - for ii, imgTmpl := range docker.ImageTemplates { + for pi, push := range cfg.Pushes { + for ii, imgTmpl := range push.ImageTemplates { var err error - cfg.Dockers[di].ImageTemplates[ii], err = renderTemplate(imgTmpl, props) + cfg.Pushes[pi].ImageTemplates[ii], err = renderTemplate(imgTmpl, props) if err != nil { return err } } } - for pi, pkgCfg := range cfg.XPackages { + for pi, build := range cfg.Builds { var err error - cfg.XPackages[pi].NameTemplate, err = renderTemplate(pkgCfg.NameTemplate, props) + cfg.Builds[pi].NameTemplate, err = renderTemplate(build.NameTemplate, props) if err != nil { return err }