blob: 7d7e568733917628c445c093ba1662e77546d8f7 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Set up everything for the roll.
#
# --prompt: require user input before taking any action. Use in conjunction
# with (before) other options.
# --setup: set up the host to do a roll. Idempotent, but probably doesn't
# need to be run more than once in a while.
# --auto-merge: do the merge. Requires --setup to be run first.
# --test: configure ffmpeg for the host machine, and try running media
# unit tests and the ffmpeg regression tests.
# --build-gn: build ffmpeg configs for all platforms, then generate gn config.
# --patches: generate chromium/patches/README and commit it locally.
import getopt
import os
import sys
from subprocess import check_output
import robo_branch
from robo_lib import log
from robo_lib import UserInstructions
import robo_lib
import robo_build
import robo_setup
def AreGnConfigsDone(cfg):
# Try to get everything to build if we haven't committed the configs yet.
# Note that the only time we need to do this again is if some change makes
# different files added / deleted to the build, or if ffmpeg configure
# changes. We don't need to do this if you just edit ffmpeg sources;
# those will be built with the tests if they've changed since last time.
#
# So, if you're just editing ffmpeg sources to get tests to pass, then you
# probably don't need to do this step again.
#
# TODO: Add a way to override this. I guess just edit out the config
# commit with a rebase for now.
return robo_branch.IsCommitOnThisBranch(cfg, cfg.gn_commit_title())
def BuildGnConfigsUnconditionally(robo_configuration):
robo_build.BuildAndImportAllFFmpegConfigs(robo_configuration)
# Run sanity checks on the merge before we commit.
robo_branch.CheckMerge(robo_configuration)
# Write the config changes to help the reviewer.
robo_branch.WriteConfigChangesFile(robo_configuration)
# TODO(liberato): Add the 'autodetect' regex too.
# Handle autorenames last, so that we don't stage things and then fail.
# While it's probably okay, it's nicer if we don't.
robo_branch.HandleAutorename(robo_configuration)
robo_branch.AddAndCommit(robo_configuration,
robo_configuration.gn_commit_title())
# Array of steps that this script knows how to perform. Each step is a
# dictionary that has the following keys:
# desc: (required) user-friendly description of this step.
# pre_fn: (optional) function that will be run first to test if all required
# prerequisites are done. Should throw an exception if not.
# skip_fn: (optional) function that will be run after |pre_fn| to determine if
# this step is already done / not required. Should return True to
# skip the step, False to do it.
# do_fn: (required) function that runs this step.
steps = {
"install_prereqs": { "desc": "Install required software.",
"do_fn": robo_setup.InstallPrereqs },
"ensure_toolchains": { "desc": "Download mac / win toolchains",
"do_fn": robo_setup.EnsureToolchains },
"ensure_asan_dir": { "desc": "Create ninja ASAN output directory if needed",
"do_fn": robo_setup.EnsureASANDirWorks },
"ensure_nasm": { "desc": "Compile chromium's nasm if needed",
"do_fn": robo_setup.EnsureChromiumNasm },
"ensure_remote": { "desc": "Set git remotes if needed",
"do_fn": robo_setup.EnsureUpstreamRemote },
# Convenience roll-up for --setup
"setup": { "do_fn": lambda cfg : RunSteps(cfg, ["install_prereqs",
"ensure_toolchains",
"ensure_asan_dir",
"ensure_nasm",
"ensure_remote"]) },
# TODO(liberato): consider moving the "if needed" to |req_fn|.
"create_sushi_branch":
{ "desc": "Create a sushi-MDY branch if we're not on one",
"do_fn": robo_branch.CreateAndCheckoutDatedSushiBranchIfNeeded },
"merge_from_upstream":
{ "desc": "Merge upstream/master to our local sushi-MDY branch if needed",
"do_fn": robo_branch.MergeUpstreamToSushiBranchIfNeeded },
"push_merge_to_origin":
{ "desc": """Push the merge commit, without review, to origin/sushi-MDY,
if needed. Also sets the local sushi-MDY to track it, so
that 'git cl upload' won't try to upload it for review.""",
"do_fn": robo_branch.PushToOriginWithoutReviewAndTrackIfNeeded },
"build_gn_configs":
{ "desc": "Build gn configs (slow), and commit the results locally.",
"skip_fn": AreGnConfigsDone,
"do_fn": BuildGnConfigsUnconditionally },
"update_patches_file":
{ "desc": "Rewrite chromium/patches/README and commit locally if needed.",
"skip_fn": robo_branch.IsPatchesFileDone,
"do_fn": robo_branch.UpdatePatchesFileUnconditionally },
"update_chromium_readme":
{ "desc": "Rewrite README.chromium to reflect the upstream SHA-1.",
"skip_fn": robo_branch.IsChromiumReadmeDone,
"do_fn": robo_branch.UpdateChromiumReadmeWithUpstream },
"run_tests":
{ "desc": "Compile and run ffmpeg_regression_tests and media_unittests",
"do_fn": robo_build.RunTests },
"upload_for_review":
{ "desc": "Upload everything to Gerrit for review, if needed",
"skip_fn": robo_branch.IsUploadedForReview,
"do_fn": robo_branch.UploadForReview },
# This is a WIP, present in case you're feeling particularly brave. :)
"start_fake_deps_roll":
{ "desc": "Try a test deps roll against the sushi (not master) branch",
"do_fn": robo_branch.TryFakeDepsRoll },
# Some things you probably don't need unless you're debugging.
"download_mac_sdk":
{ "desc": "Try to download the mac SDK, if needed.",
"do_fn": robo_setup.FetchMacSDKs },
# Roll-up for --auto-merge
"auto-merge":
{ "do_fn": lambda cfg : RunSteps(cfg, [ "create_sushi_branch",
"merge_from_upstream",
"push_merge_to_origin",
"build_gn_configs",
"update_patches_file",
"update_chromium_readme",
# TODO: If the tests fail, and this is a manual roll, then the right thing
# to do is to upload the gn config / patches for review and land it.
"run_tests",
"upload_for_review",
]) },
}
def RunSteps(cfg, step_names):
for step_name in step_names:
if not step_name in steps:
raise Exception("Unknown step %s" % step_name)
log("Step %s" % step_name)
step = steps[step_name]
try:
if "pre_fn" in step:
raise Exception("pre_fn not supported yet")
if "skip_fn" in step:
if step["skip_fn"](cfg):
log("Step %s not needed, skipping" % step_name)
continue
step["do_fn"](cfg)
except Exception, e:
log("Step %s failed" % step_name)
raise e
def ListSteps():
for name, step in steps.iteritems():
if "desc" in step:
print "%s: %s\n" % (name, step["desc"])
def main(argv):
robo_configuration = robo_lib.RoboConfiguration()
robo_configuration.chdir_to_ffmpeg_home();
# TODO(liberato): Add a way to skip |skip_fn|.
parsed, remaining = getopt.getopt(argv, "",
[
"prompt",
"setup",
"test",
"build-gn",
"patches",
"auto-merge",
"step=",
"list",
"dev-merge",
])
for opt, arg in parsed:
if opt == "--prompt":
robo_configuration.set_prompt_on_call(True)
elif opt == "--setup":
RunSteps(robo_configuration, ["setup"])
elif opt == "--test":
robo_build.BuildAndImportFFmpegConfigForHost(robo_configuration)
robo_build.RunTests(robo_configuration)
elif opt == "--build-gn":
# Unconditionally build all the configs and import them.
robo_build.BuildAndImportAllFFmpegConfigs(robo_configuration)
elif opt == "--patches":
# To be run after committing a local change to fix the tests.
if not robo_branch.IsWorkingDirectoryClean():
raise UserInstructions(
"Working directory must be clean to generate patches file")
robo_branch.UpdatePatchesFileUnconditionally(robo_configuration)
elif opt == "--auto-merge":
# TODO: make sure that any untracked autorename files are removed, or
# make sure that the autorename git script doesn't try to 'git rm'
# untracked files, else the script fails.
RunSteps(robo_configuration, ["auto-merge"])
# TODO: Start a fake deps roll. To do this, we would:
# Create new remote branch from the current remote sushi branch.
# Create and check out a new local branch at the current local branch.
# Make the new local branch track the new remote branch.
# Push to origin/new remote branch.
# Start a fake deps roll CL that runs the *san bots.
# Switch back to original local branch.
# For extra points, include a pointer to the fake deps roll CL in the
# local branch, so that when it's pushed for review, it'll point the
# reviewer at it.
# TODO: git cl upload for review.
elif opt == "--step":
RunSteps(robo_configuration, arg.split(","))
elif opt == "--list":
ListSteps()
elif opt == "--dev-merge":
# Use HEAD rather than origin/master, so that local robosushi changes
# are part of the merge. Only useful for testing those changes.
new_merge_base = check_output(["git", "log", "--format=%H", "-1"]).strip()
log("Using %s as new origin merge base for testing" % new_merge_base)
robo_configuration.override_origin_merge_base(new_merge_base)
else:
raise Exception("Unknown option '%s'" % opt);
if __name__ == "__main__":
main(sys.argv[1:])