blob: d709a680bf2dafa51f2049252b9ea565662b9e9d [file] [log] [blame]
// capture_skps_on_workers is an application that captures SKPs of the
// specified patchset type on all CT workers and uploads the results to Google
// Storage. The requester is emailed when the task is done.
package main
import (
"flag"
"fmt"
"path/filepath"
"strings"
"time"
"go.skia.org/infra/ct/go/ctfe/capture_skps"
"go.skia.org/infra/ct/go/frontend"
"go.skia.org/infra/ct/go/master_scripts/master_common"
"go.skia.org/infra/ct/go/util"
"go.skia.org/infra/go/common"
"go.skia.org/infra/go/sklog"
skutil "go.skia.org/infra/go/util"
)
const (
MAX_PAGES_PER_SWARMING_BOT_CAPTURE_SKPS = 100
// TODO(rmistry): Change back to 10000 once swarming can handle >10k pending tasks.
MAX_PAGES_PER_SWARMING_BOT_CAPTURE_SKPS_FROM_PDFS = 50000
)
var (
emails = flag.String("emails", "", "The comma separated email addresses to notify when the task is picked up and completes.")
description = flag.String("description", "", "The description of the run as entered by the requester.")
gaeTaskID = flag.Int64("gae_task_id", -1, "The key of the App Engine task. This task will be updated when the task is completed.")
pagesetType = flag.String("pageset_type", "", "The type of pagesets to use. Eg: 10k, Mobile10k, All.")
chromiumBuild = flag.String("chromium_build", "", "The chromium build to use for this capture SKPs run.")
targetPlatform = flag.String("target_platform", util.PLATFORM_LINUX, "The platform the benchmark will run on (Android / Linux).")
runID = flag.String("run_id", "", "The unique run id (typically requester + timestamp).")
taskCompletedSuccessfully = false
)
func sendEmail(recipients []string) {
// Send completion email.
emailSubject := fmt.Sprintf("Capture SKPs cluster telemetry task has completed (%s)", *runID)
failureHtml := ""
if !taskCompletedSuccessfully {
emailSubject += " with failures"
failureHtml = util.GetFailureEmailHtml(*runID)
}
bodyTemplate := `
The Capture SKPs task on %s pageset has completed. %s.<br/>
Run description: %s<br/>
%s
You can schedule more runs <a href="%s">here</a>.<br/><br/>
Thanks!
`
emailBody := fmt.Sprintf(bodyTemplate, *pagesetType, util.GetSwarmingLogsLink(*runID), *description, failureHtml, frontend.CaptureSKPsTasksWebapp)
if err := util.SendEmail(recipients, emailSubject, emailBody); err != nil {
sklog.Errorf("Error while sending email: %s", err)
return
}
}
func updateWebappTask() {
vars := capture_skps.UpdateVars{}
vars.Id = *gaeTaskID
vars.SetCompleted(taskCompletedSuccessfully)
skutil.LogErr(frontend.UpdateWebappTaskV2(&vars))
}
func main() {
defer common.LogPanic()
master_common.Init("capture_skps")
// Send start email.
emailsArr := util.ParseEmails(*emails)
emailsArr = append(emailsArr, util.CtAdmins...)
if len(emailsArr) == 0 {
sklog.Error("At least one email address must be specified")
return
}
skutil.LogErr(frontend.UpdateWebappTaskSetStarted(&capture_skps.UpdateVars{}, *gaeTaskID))
skutil.LogErr(util.SendTaskStartEmail(emailsArr, "Capture SKPs", *runID, *description))
// Ensure webapp is updated and completion email is sent even if task
// fails.
defer updateWebappTask()
defer sendEmail(emailsArr)
// Finish with glog flush and how long the task took.
defer util.TimeTrack(time.Now(), "Running capture skps task on workers")
defer sklog.Flush()
if *pagesetType == "" {
sklog.Error("Must specify --pageset_type")
return
}
if *chromiumBuild == "" {
sklog.Error("Must specify --chromium_build")
return
}
if *runID == "" {
sklog.Error("Must specify --run_id")
return
}
isolateFile := util.CAPTURE_SKPS_ISOLATE
maxPages := MAX_PAGES_PER_SWARMING_BOT_CAPTURE_SKPS
workerDimensions := util.GCE_WORKER_DIMENSIONS
hardTimeout := 3 * time.Hour
ioTimeout := 1 * time.Hour
if strings.Contains(strings.ToUpper(*pagesetType), "PDF") {
// For PDF pagesets use the capture_skps_from_pdfs worker script.
isolateFile = util.CAPTURE_SKPS_FROM_PDFS_ISOLATE
maxPages = MAX_PAGES_PER_SWARMING_BOT_CAPTURE_SKPS_FROM_PDFS
workerDimensions = util.GCE_WORKER_DIMENSIONS
hardTimeout = 12 * time.Hour
ioTimeout = hardTimeout // PDFs do not output any logs thus the ioTimeout must be the same as the hardTimeout.
// TODO(rmistry): Uncomment when ready to capture SKPs.
// TODO(rmistry): Replace the below block with:
// buildRemoteDir, err := util.TriggerBuildRepoSwarmingTask("build_pdfium", *runID, "pdfium", "Linux", []string{}, []string{filepath.Join(remoteOutputDir, chromiumPatchName)}, /*singleBuild*/ true, 2*time.Hour, 1*time.Hour)
// if err != nil {
// sklog.Errorf("Error encountered when swarming build repo task: %s", err)
// return
// }
//
//// Sync PDFium and build pdfium_test binary which will be used by the worker script.
//if err := util.SyncDir(util.PDFiumTreeDir); err != nil {
// sklog.Errorf("Could not sync PDFium: %s", err)
// return
//}
//if err := util.BuildPDFium(); err != nil {
// sklog.Errorf("Could not build PDFium: %s", err)
// return
//}
//// Copy pdfium_test to Google Storage.
//pdfiumLocalDir := path.Join(util.PDFiumTreeDir, "out", "Debug")
//pdfiumRemoteDir := path.Join(util.BINARIES_DIR_NAME, *chromiumBuild)
//// Instantiate GcsUtil object.
//gs, err := util.NewGcsUtil(nil)
//if err != nil {
// sklog.Error(err)
// return
//}
//if err := gs.UploadFile(util.BINARY_PDFIUM_TEST, pdfiumLocalDir, pdfiumRemoteDir); err != nil {
// sklog.Errorf("Could not upload %s to %s: %s", util.BINARY_PDFIUM_TEST, pdfiumRemoteDir, err)
// return
//}
}
// Empty the remote dir before the workers upload to it.
gs, err := util.NewGcsUtil(nil)
if err != nil {
sklog.Error(err)
return
}
skpGCSBaseDir := filepath.Join(util.SWARMING_DIR_NAME, util.SKPS_DIR_NAME, *pagesetType, *chromiumBuild)
skutil.LogErr(gs.DeleteRemoteDir(skpGCSBaseDir))
if strings.Contains(strings.ToUpper(*pagesetType), "PDF") {
pdfGSBaseDir := filepath.Join(util.SWARMING_DIR_NAME, util.PDFS_DIR_NAME, *pagesetType, *chromiumBuild)
skutil.LogErr(gs.DeleteRemoteDir(pdfGSBaseDir))
}
// Archive, trigger and collect swarming tasks.
isolateExtraArgs := map[string]string{
"CHROMIUM_BUILD": *chromiumBuild,
"RUN_ID": *runID,
}
if _, err := util.TriggerSwarmingTask(*pagesetType, "capture_skps", isolateFile, *runID, hardTimeout, ioTimeout, util.ADMIN_TASKS_PRIORITY, maxPages, util.PagesetTypeToInfo[*pagesetType].NumPages, isolateExtraArgs, workerDimensions, 1); err != nil {
sklog.Errorf("Error encountered when swarming tasks: %s", err)
return
}
taskCompletedSuccessfully = true
}