Index: src/scripts/sync_build_test.sh |
diff --git a/src/scripts/sync_build_test.sh b/src/scripts/sync_build_test.sh |
new file mode 100755 |
index 0000000000000000000000000000000000000000..808eb0b10115d13b83cfc15e9bbcda468a015c56 |
--- /dev/null |
+++ b/src/scripts/sync_build_test.sh |
@@ -0,0 +1,459 @@ |
+#!/bin/bash |
+ |
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+# Script to sync your checkout, build a Chromium OS image, and test it all |
+# with one command. Can also check out a new Chromium OS checkout and |
+# perform a subset of the above operations. |
+# |
+# Here are some example runs: |
+# |
+# sync_build_test.sh |
+# syncs, recreates local repo and chroot, builds, and masters an |
+# image in the checkout based on your current directory, or if you |
+# are not in a checkout, based on the top level directory the script |
+# is run from. |
+# |
+# sync_build_test.sh --image_to_usb=/dev/sdb -i |
+# same as above but then images USB device /dev/sdb with the image. |
+# Also prompt the user in advance of the steps we'll take to make |
+# sure they agrees. |
+# |
+# sync_build_test.sh --top=~/foo --nosync --remote 192.168.1.2 |
+# builds and masters an image in ~/foo, and live updates the machine |
+# at 192.168.1.2 with that image. |
+# |
+# sync_build_test.sh --top=~/newdir --test "Pam BootPerfServer" \ |
+# --remote=192.168.1.2 |
+# creates a new checkout in ~/newdir, builds and masters an image |
+# which is live updated to 192.168.1.2 and then runs |
+# two tests (Pam and BootPerfServer) against that machine. |
+# |
+# sync_build_test.sh --grab_buildbot=LATEST --test Pam --remote=192.168.1.2 |
+# grabs the latest build from the buildbot, properly modifies it, |
+# reimages 192.168.1.2, and runs the given test on it. |
+# |
+# Environment variables that may be useful: |
+# BUILDBOT_URI - default value for --buildbot_uri |
+# CHROMIUM_REPO - default value for --repo |
+# CHRONOS_PASSWD - default value for --chronos_passwd |
+# |
+ |
+# Load common constants. This should be the first executable line. |
+# The path to common.sh should be relative to your script's location. |
+. "$(dirname "$0")/common.sh" |
+ |
+ |
+DEFINE_string top "" \ |
+ "Root directory of your checkout (defaults to determining from your cwd)" |
+DEFINE_string repo "${CHROMIUMOS_REPO}" "gclient repo for chromiumos" |
+DEFINE_boolean sync ${FLAGS_TRUE} "Sync the checkout" |
+DEFINE_boolean force_make_local_repo ${FLAGS_FALSE} \ |
+ "Run make_local_repo indep of sync" |
+DEFINE_boolean force_make_chroot ${FLAGS_FALSE} "Run make_chroot indep of sync" |
+DEFINE_boolean build ${FLAGS_TRUE} \ |
+ "Build all code (but not necessarily master image)" |
+DEFINE_boolean master ${FLAGS_TRUE} "Master an image from built code" |
+DEFINE_string grab_buildbot "" \ |
+ "Instead of building, grab this full image.zip URI generated by the \ |
+buildbot" |
+DEFINE_string chronos_passwd "${CHRONOS_PASSWD}" \ |
+ "Use this as the chronos user passwd (defaults to \$CHRONOS_PASSWD)" |
+DEFINE_boolean mod_image_for_test ${FLAGS_FALSE} "Modify the image for testing" |
+DEFINE_boolean image_to_live ${FLAGS_FALSE} \ |
+ "Put the resulting image on live instance (requires --remote)" |
+DEFINE_string remote "" \ |
+ "Use this hostname/IP for live updating and running tests" |
+DEFINE_string image_to_usb "" \ |
+ "Treat this device as USB and put the image on it after build" |
+DEFINE_string test "" \ |
+ "Test the built image with the given params to run_remote_tests" |
+DEFINE_string buildbot_uri "${BUILDBOT_URI}" \ |
+ "Base URI to buildbot build location which contains LATEST file" |
+DEFINE_boolean unittest ${FLAGS_TRUE} "Run unit tests" |
+DEFINE_boolean prompt ${FLAGS_FALSE} \ |
+ "Tell user what we plan to do and wait for input to proceed" i |
+ |
+ |
+# Returns a heuristic indicating if we believe this to be a google internal |
+# development environment. |
+# Returns: |
+# 0 if so, 1 otherwise |
+function is_google_environment() { |
+ hostname | egrep -q .google.com\$ |
+ return $? |
+} |
+ |
+ |
+# Validates parameters and sets "intelligent" defaults based on other |
+# parameters. |
+function validate_and_set_param_defaults() { |
+ if [[ -z "${FLAGS_top}" ]]; then |
+ local test_dir=$(pwd) |
+ while [[ "${test_dir}" != "/" ]]; do |
+ if [[ -d "${test_dir}/src/platform/pam_google" ]]; then |
+ FLAGS_top="${test_dir}" |
+ break |
+ fi |
+ test_dir=$(dirname "${test_dir}") |
+ done |
+ fi |
+ |
+ if [[ -z "${FLAGS_top}" ]]; then |
+ # Use the top directory based on where this script runs from |
+ FLAGS_top=$(dirname $(dirname $(dirname $0))) |
+ fi |
+ |
+ if [[ -z "${FLAGS_repo}" ]]; then |
+ if is_google_environment; then |
+ FLAGS_repo="ssh://git@chromiumos-git//chromeos" |
+ else |
+ FLAGS_repo="http://src.chromium.org/git/chromiumos.git" |
+ fi |
+ fi |
+ |
+ if [[ -n "${FLAGS_test}" ]]; then |
+ # If you specify that tests should be run, we assume the image |
+ # is modified to run tests. |
+ FLAGS_mod_image_for_test=${FLAGS_TRUE} |
+ # If you specify that tests should be run, we assume you want |
+ # to live update the image. |
+ FLAGS_image_to_live=${FLAGS_TRUE} |
+ fi |
+ |
+ # If they gave us a remote host, then we assume they want us to do a live |
+ # update. |
+ if [[ -n "${FLAGS_remote}" ]]; then |
+ FLAGS_image_to_live=${FLAGS_TRUE} |
+ fi |
+ |
+ # Grabbing a buildbot build is exclusive with building |
+ if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
+ if [[ -z "${FLAGS_buildbot_uri}" ]]; then |
+ echo "--grab_buildbot requires --buildbot_uri" |
+ exit 1 |
+ fi |
+ FLAGS_build=${FLAGS_FALSE} |
+ FLAGS_master=${FLAGS_FALSE} |
+ fi |
+ |
+ if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
+ if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_FALSE} ]]; then |
+ echo "WARNING: You have specified to live reimage a machine with" |
+ echo "an image that is not modified for test (so it cannot be" |
+ echo "later live reimaged)" |
+ fi |
+ if [[ -n "${FLAGS_image_to_usb}" ]]; then |
+ echo "WARNING: You have specified to both live reimage a machine and" |
+ echo "write a USB image. Is this what you wanted?" |
+ fi |
+ if [[ -z "${FLAGS_remote}" ]]; then |
+ echo "Please specify --remote with --image_to_live" |
+ exit 1 |
+ fi |
+ fi |
+ |
+ if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
+ # Override any specified chronos password with the test one |
+ local test_file=$(dirname $0)"/mod_for_test_scripts/test_account.passwd" |
+ FLAGS_chronos_passwd=$(head -1 "${test_file}") |
+ fi |
+ |
+ if [[ -n "${FLAGS_image_to_usb}" ]]; then |
+ local device=${FLAGS_image_to_usb#/dev/} |
+ if [[ -z "${device}" ]]; then |
+ echo "Expected --image_to_usb option of /dev/* format" |
+ exit 1 |
+ fi |
+ local is_removable=$(cat /sys/block/${device}/removable) |
+ if [[ "${is_removable}" != "1" ]]; then |
+ echo "Could not verify that ${device} for image_to_usb is removable" |
+ exit 1 |
+ fi |
+ fi |
+} |
+ |
+ |
+# Prints a description of what we are doing or did |
+function describe_steps() { |
+ if [[ ${FLAGS_sync} -eq ${FLAGS_true} ]]; then |
+ echo " * Sync client (gclient sync)" |
+ if is_google_environment; then |
+ echo " * Create proper src/scripts/.chromeos_dev" |
+ fi |
+ fi |
+ if [[ ${FLAGS_force_make_local_repo} -eq ${FLAGS_true} ]]; then |
+ echo " * (Re-)create local package repository (make_local_repo.sh)" |
+ fi |
+ if [[ ${FLAGS_force_make_chroot} -eq ${FLAGS_true} ]]; then |
+ echo " * (Re-)create development chroot (make_chroot.sh)" |
+ fi |
+ local set_passwd=${FLAGS_FALSE} |
+ if [[ ${FLAGS_build} -eq ${FLAGS_true} ]]; then |
+ echo " * Build image (build_platform_packages.sh, build_kernel.sh)" |
+ set_passwd=${FLAGS_TRUE} |
+ fi |
+ if [[ ${FLAGS_master} -eq ${FLAGS_true} ]]; then |
+ echo " * Master image (build_image.sh)" |
+ fi |
+ if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
+ if [[ "${FLAGS_grab_buildbot}" == "LATEST" ]]; then |
+ echo " * Grabbing latest buildbot image under ${FLAGS_buildbot_uri}" |
+ else |
+ echo " * Grabbing buildbot image zip at URI ${FLAGS_grab_buildbot}" |
+ fi |
+ fi |
+ if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
+ echo " * Make image able to run tests (mod_image_for_test)" |
+ set_passwd=${FLAGS_TRUE} |
+ fi |
+ if [[ ${set_passwd} -eq ${FLAGS_TRUE} ]]; then |
+ if [[ -n "${FLAGS_chronos_passwd}" ]]; then |
+ echo " * Set chronos password to ${FLAGS_chronos_passwd}" |
+ else |
+ echo " * Set chronos password randomly" |
+ fi |
+ fi |
+ if [[ -n "${FLAGS_image_to_usb}" ]]; then |
+ echo " * Write the image to USB device ${FLAGS_image_to_usb}" |
+ fi |
+ if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
+ echo " * Reimage live test Chromium OS instance at ${FLAGS_remote}" |
+ fi |
+ if [[ -n "${FLAGS_test}" ]]; then |
+ echo " * Run tests (${FLAGS_test}) on machine at ${FLAGS_remote}" |
+ fi |
+} |
+ |
+ |
+# Get user's permission on steps to take |
+function prompt() { |
+ echo "Planning these steps on ${FLAGS_top}:" |
+ describe_steps |
+ read -p "Are you sure (y/N)? " SURE |
+ # Get just the first character |
+ if [[ "${SURE:0:1}" != "y" ]]; then |
+ echo "Ok, better safe than sorry." |
+ exit 1 |
+ fi |
+} |
+ |
+ |
+# Runs gclient config on a new checkout directory. |
+function config_new_checkout() { |
+ # We only know how to check out to a pattern like ~/foo/chromeos so |
+ # make sure that's the pattern the user has given. |
+ echo "Checking out ${FLAGS_top}" |
+ if [[ $(basename "${FLAGS_top}") != "chromeos" ]]; then |
+ echo "The --top directory does not exist and to check it out requires" |
+ echo "the name to end in chromeos (try --top=${FLAGS_top}/chromeos)" |
+ exit 1 |
+ fi |
+ local top_parent=$(dirname "${FLAGS_top}") |
+ mkdir -p "${top_parent}" |
+ cd "${top_parent}" |
+ gclient config "${FLAGS_repo}" |
+} |
+ |
+ |
+# Changes to a directory relative to the top/root directory of |
+# the checkout. |
+# Arguments: |
+# $1 - relative path |
+function chdir_relative() { |
+ local dir=$1 |
+ echo "+ cd ${dir}" |
+ # Allow use of .. before the innermost directory of FLAGS_top exists |
+ if [[ "${dir}" == ".." ]]; then |
+ dir=$(dirname "${FLAGS_top}") |
+ else |
+ dir="${FLAGS_top}/${dir}" |
+ fi |
+ cd "${dir}" |
+} |
+ |
+ |
+# Describe to the user that a phase is running (and make it obviously when |
+# scrolling through lots of output). |
+# Arguments: |
+# $1 - phase description |
+function describe_phase() { |
+ local desc="$1" |
+ echo "" |
+ echo "#" |
+ echo "#" |
+ echo "# ${desc}" |
+ echo "#" |
+} |
+ |
+ |
+# Runs a phase, describing it first, and also updates the sudo timeout |
+# afterwards. |
+# Arguments: |
+# $1 - phase description |
+# $2.. - command/params to run |
+function run_phase() { |
+ local desc="$1" |
+ shift |
+ describe_phase "${desc}" |
+ echo "+ $@" |
+ "$@" |
+ sudo -v |
+} |
+ |
+ |
+# Runs gclient sync, setting up .chromeos_dev and preparing for |
+# local repo setup |
+function sync() { |
+ # cd to the directory below |
+ chdir_relative .. |
+ run_phase "Synchronizing client" gclient sync |
+ chdir_relative . |
+ git cl config "file://$(pwd)/codereview.settings" |
+ if is_google_environment; then |
+ local base_dir=$(dirname $(dirname "${FLAGS_top}")) |
+ echo <<EOF > src/scripts/.chromeos_dev |
+# Use internal chromeos-deb repository |
+CHROMEOS_EXT_MIRROR="http://chromeos-deb/ubuntu" |
+CHROMEOS_EXT_SUITE="karmic" |
+ |
+# Assume Chrome is checked out nearby |
+CHROMEOS_CHROME_DIR="${base_dir}/chrome" |
+EOF |
+ fi |
+} |
+ |
+ |
+# Downloads a buildbot image |
+function grab_buildbot() { |
+ if [[ "${FLAGS_grab_buildbot}" == "LATEST" ]]; then |
+ local latest=$(curl "${FLAGS_buildbot_uri}/LATEST") |
+ if [[ -z "${latest}" ]]; then |
+ echo "Error finding latest." |
+ exit 1 |
+ fi |
+ FLAGS_grab_buildbot="${FLAGS_buildbot_uri}/${latest}/image.zip" |
+ fi |
+ local dl_dir=$(mktemp -d "/tmp/image.XXXX") |
+ echo "Grabbing image from ${FLAGS_grab_buildbot} to ${dl_dir}" |
+ run_phase "Downloading image" curl "${FLAGS_grab_buildbot}" \ |
+ -o "${dl_dir}/image.zip" |
+ cd "${dl_dir}" |
+ unzip image.zip |
+ echo "Copying in local_repo/local_packages" |
+ # TODO(kmixter): Make this architecture indep once buildbot is. |
+ mv -f local_repo/local_packages/* "${FLAGS_top}/src/build/x86/local_packages" |
+ local image_basename=$(basename $(dirname "${FLAGS_grab_buildbot}")) |
+ local image_dir="${FLAGS_top}/src/build/images/${image_basename}" |
+ echo "Copying in build image to ${image_dir}" |
+ rm -rf "${image_dir}" |
+ mkdir -p "${image_dir}" |
+ # Note that if mbr.image does not exist, this image was not successful. |
+ mv mbr.image rootfs.image "${image_dir}" |
+ chdir_relative . |
+ run_phase "Removing downloaded image" rm -rf "${dl_dir}" |
+} |
+ |
+ |
+function main() { |
+ assert_outside_chroot |
+ assert_not_root_user |
+ |
+ # Parse command line |
+ FLAGS "$@" || exit 1 |
+ eval set -- "${FLAGS_ARGV}" |
+ |
+ # Die on any errors. |
+ set -e |
+ |
+ validate_and_set_param_defaults |
+ |
+ # Cache up sudo status |
+ sudo -v |
+ |
+ if [[ ${FLAGS_prompt} -eq ${FLAGS_TRUE} ]]; then |
+ prompt |
+ fi |
+ |
+ if [[ ! -e "${FLAGS_top}" ]]; then |
+ config_new_checkout |
+ fi |
+ |
+ if [[ ${FLAGS_sync} -eq ${FLAGS_TRUE} ]]; then |
+ sync |
+ # The package repository is now potentially out of date, so |
+ # reflect that. |
+ run_phase "Removing existing package repo" sudo rm -rf repo |
+ FLAGS_force_make_local_repo=${FLAGS_TRUE} |
+ FLAGS_force_make_chroot=${FLAGS_TRUE} |
+ fi |
+ |
+ if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
+ grab_buildbot |
+ fi |
+ |
+ if [[ ${FLAGS_force_make_local_repo} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Refetching local repo" ./make_local_repo.sh |
+ fi |
+ |
+ if [[ ${FLAGS_force_make_chroot} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Replacing chroot" ./make_chroot.sh --replace |
+ fi |
+ |
+ if [[ ${FLAGS_build} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Building platform packages and kernel" ./enter_chroot.sh \ |
+ "./build_platform_packages.sh && ./build_kernel.sh" |
+ |
+ if [[ ${FLAGS_build} -eq ${FLAGS_TRUE} ]]; then |
+ run_phase "Building and running unit tests" ./enter_chroot.sh \ |
+ "./build_tests.sh && ./run_tests.sh" |
+ fi |
+ fi |
+ |
+ if [[ ${FLAGS_master} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ if [[ -n "${FLAGS_chronos_passwd}" ]]; then |
+ describe_phase "Setting default chronos password" |
+ ./enter_chroot.sh "echo '${FLAGS_chronos_passwd}' | \ |
+ ./set_shared_user_password.sh" |
+ fi |
+ run_phase "Mastering image" ./enter_chroot.sh "./build_image.sh --replace" |
+ fi |
+ |
+ if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Modifying image for test" ./enter_chroot.sh \ |
+ "./mod_image_for_test.sh" |
+ fi |
+ |
+ if [[ -n "${FLAGS_image_to_usb}" ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Installing image to USB" \ |
+ ./image_to_usb.sh --yes "--to=${FLAGS_image_to_usb}" |
+ fi |
+ |
+ if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
+ chdir_relative src/scripts |
+ run_phase "Re-imaging live Chromium OS machine ${FLAGS_remote}" \ |
+ ./image_to_live.sh "--remote=${FLAGS_remote}" --update_known_hosts |
+ fi |
+ |
+ if [[ -n "${FLAGS_test}" ]]; then |
+ chdir_relative src/scripts |
+ # We purposefully do not quote FLAGS_test below as we expect it may |
+ # have multiple parameters |
+ run_phase "Running tests on Chromium OS machine ${FLAGS_remote}" \ |
+ ./run_remote_tests.sh --remote="${FLAGS_remote}" ${FLAGS_test} |
+ fi |
+ |
+ echo "Successfully used ${FLAGS_top} to:" |
+ describe_steps |
+} |
+ |
+ |
+main $@ |