mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"golang.org/x/xerrors"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type MD struct {
|
|
HelmComponent string `yaml:"helm-component"`
|
|
}
|
|
|
|
func main() {
|
|
produceManifest(os.Stdout, os.DirFS("."))
|
|
}
|
|
|
|
func produceManifest(out io.Writer, dir fs.FS) error {
|
|
mds, err := fs.Glob(dir, "**/metadata.yaml")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
versions := make(map[string]string)
|
|
for _, md := range mds {
|
|
b, err := fs.ReadFile(dir, md)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var mdobj MD
|
|
err = yaml.Unmarshal(b, &mdobj)
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot unmarshal %s: %w", md, err)
|
|
}
|
|
if mdobj.HelmComponent == "" {
|
|
continue
|
|
}
|
|
|
|
imgf, err := fs.ReadFile(dir, filepath.Join(filepath.Dir(md), "imgnames.txt"))
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot read image names for %s: %w", md, err)
|
|
}
|
|
imgs := strings.Split(strings.TrimSpace(string(imgf)), "\n")
|
|
img := imgs[len(imgs)-1]
|
|
segs := strings.Split(img, ":")
|
|
if len(segs) != 2 {
|
|
return xerrors.Errorf("invalid image format: %s", img)
|
|
}
|
|
version := segs[1]
|
|
versions[mdobj.HelmComponent] = version
|
|
}
|
|
|
|
// We need to deduplicate keys in the resulting yaml file. To this end, we first build up
|
|
// a map of maps and later print that map YAML style.
|
|
res := make(map[string]interface{})
|
|
comps := make(map[string]interface{})
|
|
res["components"] = comps
|
|
for k, v := range versions {
|
|
var (
|
|
m = comps
|
|
segs = strings.Split(k+".version", ".")
|
|
)
|
|
for i, seg := range segs {
|
|
if i == len(segs)-1 {
|
|
m[seg] = v
|
|
continue
|
|
}
|
|
|
|
if _, ok := m[seg]; !ok {
|
|
m[seg] = make(map[string]interface{})
|
|
}
|
|
m = m[seg].(map[string]interface{})
|
|
}
|
|
}
|
|
|
|
// It's not clear how to maintain a stable order of keys using the YAML serializer.
|
|
// If it were, we could just through this map at the YAML serializer and call it a day.
|
|
// Right now, we have to produce the YAML ourselves.
|
|
var print func(m map[string]interface{}, indent int) error
|
|
print = func(m map[string]interface{}, indent int) error {
|
|
keys := make([]string, 0, len(m))
|
|
for v := range m {
|
|
keys = append(keys, v)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
for _, k := range keys {
|
|
v := m[k]
|
|
fmt.Fprintf(out, "%s%s:", strings.Repeat(" ", indent), k)
|
|
if c, ok := v.(map[string]interface{}); ok {
|
|
fmt.Fprintln(out)
|
|
err := print(c, indent+1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
if c, ok := v.(string); ok {
|
|
fmt.Fprintf(out, " %s\n", c)
|
|
fmt.Fprintln(out)
|
|
continue
|
|
}
|
|
|
|
return xerrors.Errorf("unknown value type - this should never happen")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
return print(res, 0)
|
|
}
|