woodpecker/make.go
2015-09-02 16:52:59 -07:00

299 lines
6.2 KiB
Go

// +build ignore
// This program builds Drone.
// $ go run make.go build test
//
// The output binaries go into the ./bin/ directory (under the
// project root, where make.go is)
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/jteeuwen/go-bindata"
)
var (
version = "0.4"
sha = rev()
)
// list of all posible steps that can be executed
// as part of the build process.
var steps = map[string]step{
"scripts": scripts,
"styles": styles,
"json": json,
"embed": embed,
"vet": vet,
"bindata": bindat,
"build": build,
"test": test,
"image": image,
"clean": clean,
}
func main() {
for _, arg := range os.Args[1:] {
step, ok := steps[arg]
if !ok {
fmt.Println("error: invalid step", arg)
os.Exit(1)
}
err := step()
if err != nil {
fmt.Println("error: failed step", arg)
os.Exit(1)
}
}
}
type step func() error
// embed step embeds static files in .go files.
func embed() error {
// embed drone.{revision}.css
// embed drone.{revision}.js
return nil
}
// scripts step concatinates all javascript files.
func scripts() error {
files := []string{
"cmd/drone-server/static/scripts/term.js",
"cmd/drone-server/static/scripts/drone.js",
"cmd/drone-server/static/scripts/controllers/repos.js",
"cmd/drone-server/static/scripts/controllers/builds.js",
"cmd/drone-server/static/scripts/controllers/users.js",
"cmd/drone-server/static/scripts/services/repos.js",
"cmd/drone-server/static/scripts/services/builds.js",
"cmd/drone-server/static/scripts/services/users.js",
"cmd/drone-server/static/scripts/services/logs.js",
"cmd/drone-server/static/scripts/services/tokens.js",
"cmd/drone-server/static/scripts/services/feed.js",
"cmd/drone-server/static/scripts/filters/filter.js",
"cmd/drone-server/static/scripts/filters/gravatar.js",
"cmd/drone-server/static/scripts/filters/time.js",
}
f, err := os.OpenFile(
"cmd/drone-server/static/scripts/drone.min.js",
os.O_CREATE|os.O_RDWR|os.O_TRUNC,
0660)
defer f.Close()
if err != nil {
fmt.Println("Failed to open output file")
return err
}
for _, input := range files {
content, err := ioutil.ReadFile(input)
if err != nil {
return err
}
f.Write(content)
}
return nil
}
// styles step concatinates the stylesheet files.
func styles() error {
files := []string{
"cmd/drone-server/static/styles/reset.css",
"cmd/drone-server/static/styles/fonts.css",
"cmd/drone-server/static/styles/alert.css",
"cmd/drone-server/static/styles/blankslate.css",
"cmd/drone-server/static/styles/list.css",
"cmd/drone-server/static/styles/label.css",
"cmd/drone-server/static/styles/range.css",
"cmd/drone-server/static/styles/switch.css",
"cmd/drone-server/static/styles/main.css",
}
f, err := os.OpenFile(
"cmd/drone-server/static/styles/drone.min.css",
os.O_CREATE|os.O_RDWR|os.O_TRUNC,
0660)
defer f.Close()
if err != nil {
fmt.Println("Failed to open output file")
return err
}
for _, input := range files {
content, err := ioutil.ReadFile(input)
if err != nil {
return err
}
f.Write(content)
}
return nil
}
// json step generates optimized json marshal and
// unmarshal functions to override defaults.
func json() error {
return nil
}
// bindata step generates go-bindata package.
func bindat() error {
var paths = []struct {
input string
recursive bool
}{
{"cmd/drone-server/static", true},
}
c := bindata.NewConfig()
c.Output = "cmd/drone-server/drone_bindata.go"
c.Input = make([]bindata.InputConfig, len(paths))
for i, path := range paths {
c.Input[i] = bindata.InputConfig{
Path: path.input,
Recursive: path.recursive,
}
}
return bindata.Translate(c)
}
// build step creates the application binaries.
func build() error {
var bins = []struct {
input string
output string
}{
{"github.com/drone/drone/cmd/drone-server", "bin/drone"},
{"github.com/drone/drone/cmd/drone-agent", "bin/drone-agent"},
}
for _, bin := range bins {
ldf := fmt.Sprintf("-X main.revision=%s -X main.version=%s", sha, version)
cmd := exec.Command("go", "build", "-o", bin.output, "-ldflags", ldf, bin.input)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
trace(cmd.Args)
err := cmd.Run()
if err != nil {
return err
}
}
return nil
}
// vet step executes the `go vet` command
func vet() error {
cmd := exec.Command("go", "vet",
"github.com/drone/drone/pkg/...",
"github.com/drone/drone/cmd/...")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
trace(cmd.Args)
return cmd.Run()
}
// test step executes unit tests and coverage.
func test() error {
cmd := exec.Command("go", "test", "-cover", "./pkg/...")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
trace(cmd.Args)
return cmd.Run()
}
// image step builds Docker images.
func image() error {
var images = []struct {
dir string
name string
}{
{"./bin/drone-agent", "drone/drone-agent"},
{"./bin/drone-server", "drone/drone"},
}
for _, image := range images {
path := filepath.Join(image.dir, "Dockerfile")
name := image.name + ":" + version
cmd := exec.Command("docker", "build", "-rm", path, name)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
trace(cmd.Args)
err := cmd.Run()
if err != nil {
return err
}
}
return nil
}
func clean() error {
err := filepath.Walk(".", func(path string, f os.FileInfo, err error) error {
suffixes := []string{
".out",
"_bindata.go",
}
for _, suffix := range suffixes {
if strings.HasSuffix(path, suffix) {
if err := os.Remove(path); err != nil {
return err
}
}
}
return nil
})
if err != nil {
return err
}
files := []string{
"bin/drone",
"bin/drone-agent",
}
for _, file := range files {
if _, err := os.Stat(file); err != nil {
continue
}
if err := os.Remove(file); err != nil {
return err
}
}
return nil
}
// trace is a helper fucntion that writes a command
// to stdout similar to bash +x
func trace(args []string) {
print("+ ")
println(strings.Join(args, " "))
}
// helper function to parse the git revision
func rev() string {
cmd := exec.Command("git", "rev-parse", "--short", "HEAD")
raw, err := cmd.CombinedOutput()
if err != nil {
return "HEAD"
}
return strings.Trim(string(raw), "\n")
}