2022-09-14 00:59:18 -05:00
|
|
|
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"
|
2022-12-14 05:32:45 -06:00
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/build/fsutil"
|
2022-09-14 00:59:18 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func VerifyDrone(c *cli.Context) error {
|
|
|
|
const yml = ".drone.yml"
|
|
|
|
const backup = ".drone.yml.bak"
|
|
|
|
|
|
|
|
if err := fsutil.CopyFile(yml, backup); err != nil {
|
2022-12-14 05:32:45 -06:00
|
|
|
return cli.Exit(fmt.Sprintf("failed to copy %s to %s: %s", yml, backup, err), 1)
|
2022-09-14 00:59:18 -05:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
2022-11-08 09:27:57 -06:00
|
|
|
if err := flags.Set("format", "true"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-09-14 00:59:18 -05:00
|
|
|
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]interface{}, error) {
|
|
|
|
//nolint:gosec
|
|
|
|
f, err := os.Open(fpath)
|
|
|
|
if err != nil {
|
2022-12-14 05:32:45 -06:00
|
|
|
return nil, cli.Exit(fmt.Sprintf("failed to read %s: %s", fpath, err), 1)
|
2022-09-14 00:59:18 -05:00
|
|
|
}
|
|
|
|
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]interface{}
|
|
|
|
for {
|
|
|
|
var m map[string]interface{}
|
|
|
|
if err := dec.Decode(&m); err != nil {
|
|
|
|
if errors.Is(err, io.EOF) {
|
|
|
|
break
|
|
|
|
}
|
2022-12-14 05:32:45 -06:00
|
|
|
return nil, cli.Exit(fmt.Sprintf("Failed to decode %s: %s", fpath, err), 1)
|
2022-09-14 00:59:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2022-12-14 05:32:45 -06:00
|
|
|
return cli.Exit(fmt.Sprintf("%s is out of sync with .drone.star - regenerate it with drone starlark convert",
|
2022-09-14 00:59:18 -05:00
|
|
|
yml), 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|