databricks-cli/lib/flavor/mvn/mvn.go

99 lines
2.5 KiB
Go

package mvn
import (
"context"
"encoding/xml"
"fmt"
"io"
"os"
"path/filepath"
"github.com/databricks/bricks/lib/flavor"
"github.com/databricks/bricks/lib/spawn"
"github.com/databricks/databricks-sdk-go/service/libraries"
)
type Pom struct {
Name string `xml:"name"`
GroupID string `xml:"groupId"`
ArtifactID string `xml:"artifactId"`
Version string `xml:"version"`
}
func (pom *Pom) Jar() string {
return fmt.Sprintf("%s-%s.jar", pom.ArtifactID, pom.Version)
}
type Maven struct {
SkipTests bool `json:"skip_tests,omitempty"`
}
func (mvn *Maven) RequiresCluster() bool {
return true
}
// Java libraries always require cluster restart
func (mvn *Maven) RequiresRestart() bool {
return true
}
func (mvn *Maven) Detected(prj flavor.Project) bool {
_, err := os.Stat(filepath.Join(prj.Root(), "pom.xml"))
return err == nil
}
func (mvn *Maven) LocalArtifacts(ctx context.Context, prj flavor.Project) (flavor.Artifacts, error) {
pom, err := mvn.Pom(prj.Root())
if err != nil {
return nil, err
}
return flavor.Artifacts{
{
Flavor: mvn,
Library: libraries.Library{
Jar: fmt.Sprintf("%s/target/%s", prj.Root(), pom.Jar()),
},
},
}, nil
}
func (mvn *Maven) Pom(root string) (*Pom, error) {
// TODO: perhaps we should call effective-pom, specially once
// we start comparing local spark version and the one on DBR
pomFile := fmt.Sprintf("%s/pom.xml", root)
pomHandle, err := os.Open(pomFile)
if err != nil {
return nil, fmt.Errorf("open %s: %w", pomFile, err)
}
pomBytes, err := io.ReadAll(pomHandle)
if err != nil {
return nil, fmt.Errorf("read %s: %w", pomFile, err)
}
var pom Pom
err = xml.Unmarshal(pomBytes, &pom)
if err != nil {
return nil, fmt.Errorf("parse %s: %w", pomFile, err)
}
return &pom, nil
}
func (mvn *Maven) Build(ctx context.Context, prj flavor.Project, status func(string)) error {
mavenPath, err := spawn.DetectExecutable(ctx, "mvn")
if err != nil {
return fmt.Errorf("no Maven installed: %w", err)
}
// report back the name of the JAR to the user
pom, _ := mvn.Pom(prj.Root())
status(fmt.Sprintf("Buidling %s", pom.Jar()))
args := []string{fmt.Sprintf("--file=%s/pom.xml", prj.Root())}
args = append(args, "-DskipTests=true")
args = append(args, "clean", "package")
_, err = spawn.ExecAndPassErr(ctx, mavenPath, args...)
if err != nil {
// TODO: figure out error reporting in a generic way
// one of the options is to re-run the same command with stdout forwarding
return fmt.Errorf("mvn package: %w", err)
}
return nil
}