diff --git a/build.go b/build.go index 8ac7fada898..a706842dfec 100644 --- a/build.go +++ b/build.go @@ -351,7 +351,7 @@ func grunt(params ...string) { func gruntBuildArg(task string) []string { args := []string{task} if includeBuildNumber { - args = append(args, fmt.Sprintf("--pkgVer=%v-%v", version, linuxPackageIteration)) + args = append(args, fmt.Sprintf("--pkgVer=%v-%v", linuxPackageVersion, linuxPackageIteration)) } else { args = append(args, fmt.Sprintf("--pkgVer=%v", version)) } diff --git a/circle.yml b/circle.yml index 9c5f0f1ccbd..8ae37162490 100644 --- a/circle.yml +++ b/circle.yml @@ -45,6 +45,7 @@ deployment: - aws s3 sync ./dist s3://$BUCKET_NAME/master - ./scripts/trigger_windows_build.sh ${APPVEYOR_TOKEN} ${CIRCLE_SHA1} master - ./scripts/trigger_docker_build.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN} + - go run ./scripts/build/publish.go -apiKey "${GRAFANA_COM_API_KEY}" gh_tag: tag: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/ commands: diff --git a/scripts/build/publish.go b/scripts/build/publish.go new file mode 100644 index 00000000000..447d38068bd --- /dev/null +++ b/scripts/build/publish.go @@ -0,0 +1,150 @@ +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" +) + +var apiUrl = flag.String("apiUrl", "https://grafana.com/api", "api url") +var apiKey = flag.String("apiKey", "", "api key") +var version = "" +var versionRe = regexp.MustCompile(`grafana-(.*)\.(linux|windows)`) +var builds = []build{} + +func main() { + flag.Parse() + if *apiKey == "" { + log.Fatalf("Require apiKey command line parameters") + } + + err := filepath.Walk("dist", packageWalker) + if err != nil { + log.Fatalf("Cannot find any packages to publish, %v", err) + } + + if version == "" { + log.Fatalf("No version found") + } + + if len(builds) == 0 { + log.Fatalf("No builds found") + } + + nightly := release{ + Version: version, + ReleaseDate: time.Now(), + Stable: false, + Nightly: true, + Beta: false, + WhatsNewUrl: "", + ReleaseNotesUrl: "", + Builds: builds, + } + + postRequest("/grafana/versions", nightly, fmt.Sprintf("Create Release %s", nightly.Version)) + postRequest("/grafana/versions/"+nightly.Version, nightly, fmt.Sprintf("Update Release %s", nightly.Version)) + + for _, b := range nightly.Builds { + postRequest(fmt.Sprintf("/grafana/versions/%s/packages", nightly.Version), b, fmt.Sprintf("Create Build %s %s", b.Os, b.Arch)) + postRequest(fmt.Sprintf("/grafana/versions/%s/packages/%s/%s", nightly.Version, b.Arch, b.Os), b, fmt.Sprintf("Update Build %s %s", b.Os, b.Arch)) + } +} + +func packageWalker(path string, f os.FileInfo, err error) error { + if f.Name() == "dist" || strings.Contains(f.Name(), "sha256") { + return nil + } + + log.Printf("Finding package file %s", f.Name()) + result := versionRe.FindSubmatch([]byte(f.Name())) + + if len(result) > 0 { + version = string(result[1]) + log.Printf("Version detected: %v", version) + } + + shaBytes, err := ioutil.ReadFile(path + ".sha256") + if err != nil { + log.Fatalf("Failed to read sha256 file", err) + } + + os := "" + if strings.Contains(f.Name(), "linux-x64.tar.gz") { + os = "linux" + } + if strings.HasSuffix(f.Name(), "windows-x64.zip") { + os = "win" + } + if strings.HasSuffix(f.Name(), ".rpm") { + os = "rhel" + } + if strings.HasSuffix(f.Name(), ".deb") { + os = "deb" + } + + builds = append(builds, build{ + Os: os, + Arch: "amd64", + Url: "https://s3-us-west-2.amazonaws.com/grafana-releases/master/" + f.Name(), + Sha256: string(shaBytes), + }) + + return nil +} + +func postRequest(url string, obj interface{}, desc string) { + jsonBytes, _ := json.Marshal(obj) + req, _ := http.NewRequest(http.MethodPost, (*apiUrl)+url, bytes.NewReader(jsonBytes)) + req.Header.Add("Authorization", "Bearer "+(*apiKey)) + req.Header.Add("Content-Type", "application/json") + + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Fatalf("error: %v", err) + } + + if res.StatusCode == http.StatusOK { + log.Printf("Action: %s \t OK", desc) + } else { + + if res.Body != nil { + defer res.Body.Close() + body, _ := ioutil.ReadAll(res.Body) + if strings.Contains(string(body), "already exists") || strings.Contains(string(body), "Nothing to update") { + log.Printf("Action: %s \t Already exists", desc) + } else { + log.Printf("Action: %s \t Failed - Status: %v", desc, res.Status) + log.Printf("Resp: %s", body) + log.Fatalf("Quiting") + } + } + } +} + +type release struct { + Version string `json:"version"` + ReleaseDate time.Time `json:"releaseDate"` + Stable bool `json:"stable"` + Beta bool `json:"beta"` + Nightly bool `json:"nightly"` + WhatsNewUrl string `json:"whatsNewUrl"` + ReleaseNotesUrl string `json:"releaseNotesUrl"` + Builds []build `json:"-"` +} + +type build struct { + Os string `json:"os"` + Url string `json:"url"` + Sha256 string `json:"sha256"` + Arch string `json:"arch"` +} diff --git a/tasks/build_task.js b/tasks/build_task.js index 7956c66fc23..e6751aa399d 100644 --- a/tasks/build_task.js +++ b/tasks/build_task.js @@ -1,3 +1,5 @@ +var path = require('path'); + module.exports = function(grunt) { "use strict"; @@ -67,6 +69,8 @@ module.exports = function(grunt) { grunt.task.run('copy:public_gen_to_temp'); grunt.task.run('copy:backend_bin'); grunt.task.run('copy:backend_files'); + + grunt.file.write(path.join(grunt.config('tempDir'), 'VERSION'), grunt.config('pkg.version')); }); };