The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/build/cmd/verifydrone.go

125 lines
2.6 KiB

package main
import (
"errors"
"flag"
"fmt"
"io"
"log"
"os"
"github.com/drone/drone-cli/drone/lint"
"github.com/drone/drone-cli/drone/starlark"
"github.com/google/go-cmp/cmp"
cliv1 "github.com/urfave/cli"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
"github.com/grafana/grafana/pkg/build/fsutil"
)
func VerifyDrone(c *cli.Context) error {
const yml = ".drone.yml"
const backup = ".drone.yml.bak"
if err := fsutil.CopyFile(yml, backup); err != nil {
return cli.Exit(fmt.Sprintf("failed to copy %s to %s: %s", yml, backup, err), 1)
}
defer func() {
if err := os.Remove(yml); err != nil {
log.Printf("Failed to rename %s to %s", backup, yml)
}
if err := os.Rename(backup, yml); err != nil {
log.Printf("Failed to rename %s to %s", backup, yml)
}
}()
flags := &flag.FlagSet{}
for _, flag := range starlark.Command.Flags {
flag.Apply(flags)
}
if err := flags.Set("format", "true"); err != nil {
return err
}
cStarlark := cliv1.NewContext(cliv1.NewApp(), flags, nil)
action := starlark.Command.Action.(func(*cliv1.Context))
action(cStarlark)
if err := verifyYAML(yml, backup); err != nil {
return err
}
flags = &flag.FlagSet{}
for _, flag := range lint.Command.Flags {
flag.Apply(flags)
}
err := flags.Set("trusted", "true")
if err != nil {
return err
}
cLint := cliv1.NewContext(cliv1.NewApp(), flags, nil)
actionE := lint.Command.Action.(func(*cliv1.Context) error)
if err := actionE(cLint); err != nil {
return err
}
log.Printf("%s is valid", yml)
return nil
}
func readConfig(fpath string) ([]map[string]any, error) {
//nolint:gosec
f, err := os.Open(fpath)
if err != nil {
return nil, cli.Exit(fmt.Sprintf("failed to read %s: %s", fpath, err), 1)
}
defer func() {
if err := f.Close(); err != nil {
log.Println("error closing file", err)
}
}()
// The YAML stream may contain multiple pipeline configurations, read them all
dec := yaml.NewDecoder(f)
var c []map[string]any
for {
var m map[string]any
if err := dec.Decode(&m); err != nil {
if errors.Is(err, io.EOF) {
break
}
return nil, cli.Exit(fmt.Sprintf("Failed to decode %s: %s", fpath, err), 1)
}
if m["kind"] == "signature" {
log.Printf("Ignoring a signature")
continue
}
c = append(c, m)
}
return c, nil
}
func verifyYAML(yml, backup string) error {
log.Printf("Comparing %s and %s", yml, backup)
c1, err := readConfig(yml)
if err != nil {
return err
}
c2, err := readConfig(backup)
if err != nil {
return err
}
if !cmp.Equal(c1, c2) {
return cli.Exit(fmt.Sprintf("%s is out of sync with .drone.star - regenerate it with drone starlark convert",
yml), 1)
}
return nil
}