// GetBuildPage accepts a request to retrieve the build // output page for the package version, channel and SDK // from the datastore in JSON format. // // If the SDK is not provided, the system will lookup // the latest SDK version for this package. // // GET /:name/:number/:channel/:sdk // func GetBuildPage(c web.C, w http.ResponseWriter, r *http.Request) { ctx := context.FromC(c) name := c.URLParams["name"] number := c.URLParams["number"] channel := c.URLParams["channel"] sdk := c.URLParams["sdk"] // If no SDK is provided we should use the most recent // SDK number associated with the Package version. var build *resource.Build var err error if len(sdk) == 0 { build, err = datastore.GetBuildLatest(ctx, name, number, channel) } else { build, err = datastore.GetBuild(ctx, name, number, channel, sdk) } // If the error is not nil then we can // display some sort of NotFound page. if err != nil { http.Error(w, "Not Found", http.StatusNotFound) return } BuildTempl.Execute(w, struct { Build *resource.Build Error error }{build, err}) }
// GetBuild accepts a request to retrieve the build // details for the package version, channel and SDK // from the datastore in JSON format. // // GET /api/packages/:name/:number/channel/:channel/sdk/:sdk // func GetBuild(c web.C, w http.ResponseWriter, r *http.Request) { ctx := context.FromC(c) name := c.URLParams["name"] number := c.URLParams["number"] channel := c.URLParams["channel"] sdk := c.URLParams["sdk"] build, err := datastore.GetBuild(ctx, name, number, channel, sdk) if err != nil { w.WriteHeader(http.StatusNotFound) return } json.NewEncoder(w).Encode(build) }
// PostBuild accepts a request to execute a build // for the named package, version, channel and SDK. // // POST /sudo/api/build // func PostBuild(c web.C, w http.ResponseWriter, r *http.Request) { ctx := context.FromC(c) name := r.FormValue("package") number := r.FormValue("version") channel := r.FormValue("channel") rev := r.FormValue("revision") sdk := r.FormValue("sdk") force := r.FormValue("force") // parse the revision number from string to int64 // format so that we can run version comparisons. revision, err := strconv.ParseInt(rev, 10, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) return } // get the build from the datastore. If it does not // yet exist, populate fields required upon creation. build, err := datastore.GetBuild(ctx, name, number, channel, sdk) if err == nil && len(force) == 0 { w.WriteHeader(http.StatusConflict) return } else if err != nil { build.Name = name build.Version = number build.Channel = channel build.SDK = sdk build.Created = time.Now().UTC().Unix() } build.Revision = revision build.Status = resource.StatusPending build.Updated = time.Now().UTC().Unix() if err := datastore.PutBuild(ctx, build); err != nil { w.WriteHeader(http.StatusInternalServerError) return } work := worker.Work{build} go worker.Do(ctx, &work) w.WriteHeader(http.StatusNoContent) }
// GetBadge accepts a request to retrieve the named // package and version build details from the datastore // and return an SVG badges representing the build results. // // GET /api/badges/:name/:number/channel/:channel/status.svg // GET /api/badges/:name/:number/channel/:channel/sdk/:sdk/status.svg // func GetBadge(c web.C, w http.ResponseWriter, r *http.Request) { ctx := context.FromC(c) name := c.URLParams["name"] number := c.URLParams["number"] channel := c.URLParams["channel"] sdk := c.URLParams["sdk"] // Ensure we set the correct content-type // for the badge to ensure it displays // correctly on GitHub. w.Header().Set("Content-Type", "image/svg+xml") // If no SDK is provided we should use the most recent // SDK number associated with the Package version. var build *resource.Build var err error if len(sdk) == 0 { build, err = datastore.GetBuildLatest(ctx, name, number, channel) } else { build, err = datastore.GetBuild(ctx, name, number, channel, sdk) } // If there was an error default to a build status None if err != nil { build.Status = resource.StatusNone } var badgeStr string var badgeMsg string = build.SDK switch build.Status { case resource.StatusSuccess: badgeStr = badgeSuccess case resource.StatusFailure: badgeStr = badgeFailure case resource.StatusWarning: badgeStr = badgeWarning case resource.StatusStarted, resource.StatusPending: badgeStr = badgeStarted case resource.StatusKilled, resource.StatusError: badgeStr = badgeError default: badgeStr = badgeNone badgeMsg = channel } // replace any - with -- for compatibility with // the shields.io service. badgeMsg = strings.Replace(badgeMsg, "-", "--", -1) // generate the badge url and check to see if the // badge already exists in the cache var badgeUrl = fmt.Sprintf(badgeStr, badgeMsg) if badgeRaw, ok := badgeCache.Get(badgeUrl); ok { w.Write(badgeRaw.([]byte)) return } // retrieve the badge from shields.io res, err := http.Get(badgeUrl) if err != nil { http.Error(w, err.Error(), res.StatusCode) return } defer res.Body.Close() // read the svg data from the request body, // write to the response + the local lru cache. badgeRaw, err := ioutil.ReadAll(res.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } badgeCache.Add(badgeUrl, badgeRaw) w.Write(badgeRaw) }