magefiles/resources.go (79 lines of code) (raw):

//go:build mage package main import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "strconv" "github.com/jedib0t/go-pretty/v6/table" "github.com/magefile/mage/mg" "github.com/samber/lo" "github.com/sourcegraph/conc/iter" "gitlab.com/gitlab-org/gitlab-runner/magefiles/build" ) type Resources mg.Namespace // Verify verifies that the resources exported match the expected blueprint // blueprints are expected to be exported to the `out/release_artifacts/<typ>.json` file func (Resources) Verify(typ string) error { rows, err := verify(build.ReleaseArtifactsPath(typ)) renderTable(rows) return err } func verify(f string) ([]table.Row, error) { if _, err := os.Stat(f); os.IsNotExist(err) { return nil, err } b, err := os.ReadFile(f) if err != nil { return nil, err } var m []map[string]string if err := json.Unmarshal(b, &m); err != nil { return nil, err } c := lo.Map(m, func(m map[string]string, _ int) build.Component { required, _ := strconv.ParseBool(m["Required"]) return build.NewComponent( m["Value"], m["Type"], m["Description"], required, ) }) checked, _ := build.CheckComponents(c) rows := build.RowsFromCheckedComponents(checked) errs := lo.FilterMap(lo.Values(checked), func(t lo.Tuple2[string, error], _ int) (error, bool) { return t.B, t.B != nil }) if len(errs) == 0 { return rows, nil } return rows, errors.New("there were errors in the checked resources") } func renderTable(rows []table.Row) { t := table.NewWriter() t.AppendHeader(table.Row{"Resources status"}) t.AppendSeparator() t.AppendRow(table.Row{"Resource", "Type", "Exists"}) t.AppendSeparator() t.AppendRows(rows) fmt.Println(t.Render()) } // VerifyAll verifies that all resources exported match the expected blueprint // blueprints are expected to be exported to the `out/release_artifacts/*.json` files func (Resources) VerifyAll() error { // TODO: verify that the resources exported match the expected blueprint // Currently, we rely on each job to export its artifacts. This is great, however if a job // doesn't export its artifacts correctly we could miss some resources. // We need to generate blueprints in the verify stage of the pipeline and then export the artifacts // and compare them to the ones actually exported by the jobs. This is not very straightforward // so let's do it in a separate MR, later. dir := filepath.Dir(build.ReleaseArtifactsPath("")) entries, err := os.ReadDir(dir) if err != nil { return err } mapper := iter.Mapper[os.DirEntry, []table.Row]{ MaxGoroutines: config.Concurrency, } rows, err := mapper.MapErr(entries, func(entry *os.DirEntry) ([]table.Row, error) { if (*entry).IsDir() { return nil, nil } f := (*entry).Name() return verify(filepath.Join(dir, f)) }) renderTable(lo.Flatten(rows)) return err }