OLD | NEW |
(Empty) | |
| 1 #!/bin/bash |
| 2 |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. |
| 6 |
| 7 # Script to sync your checkout, build a Chromium OS image, and test it all |
| 8 # with one command. Can also check out a new Chromium OS checkout and |
| 9 # perform a subset of the above operations. |
| 10 # |
| 11 # Here are some example runs: |
| 12 # |
| 13 # sync_build_test.sh |
| 14 # syncs, recreates local repo and chroot, builds, and masters an |
| 15 # image in the checkout based on your current directory, or if you |
| 16 # are not in a checkout, based on the top level directory the script |
| 17 # is run from. |
| 18 # |
| 19 # sync_build_test.sh --image_to_usb=/dev/sdb -i |
| 20 # same as above but then images USB device /dev/sdb with the image. |
| 21 # Also prompt the user in advance of the steps we'll take to make |
| 22 # sure they agrees. |
| 23 # |
| 24 # sync_build_test.sh --top=~/foo --nosync --remote 192.168.1.2 |
| 25 # builds and masters an image in ~/foo, and live updates the machine |
| 26 # at 192.168.1.2 with that image. |
| 27 # |
| 28 # sync_build_test.sh --top=~/newdir --test "Pam BootPerfServer" \ |
| 29 # --remote=192.168.1.2 |
| 30 # creates a new checkout in ~/newdir, builds and masters an image |
| 31 # which is live updated to 192.168.1.2 and then runs |
| 32 # two tests (Pam and BootPerfServer) against that machine. |
| 33 # |
| 34 # sync_build_test.sh --grab_buildbot=LATEST --test Pam --remote=192.168.1.2 |
| 35 # grabs the latest build from the buildbot, properly modifies it, |
| 36 # reimages 192.168.1.2, and runs the given test on it. |
| 37 # |
| 38 # Environment variables that may be useful: |
| 39 # BUILDBOT_URI - default value for --buildbot_uri |
| 40 # CHROMIUM_REPO - default value for --repo |
| 41 # CHRONOS_PASSWD - default value for --chronos_passwd |
| 42 # |
| 43 |
| 44 # Load common constants. This should be the first executable line. |
| 45 # The path to common.sh should be relative to your script's location. |
| 46 . "$(dirname "$0")/common.sh" |
| 47 |
| 48 |
| 49 DEFINE_string top "" \ |
| 50 "Root directory of your checkout (defaults to determining from your cwd)" |
| 51 DEFINE_string repo "${CHROMIUMOS_REPO}" "gclient repo for chromiumos" |
| 52 DEFINE_boolean sync ${FLAGS_TRUE} "Sync the checkout" |
| 53 DEFINE_boolean force_make_local_repo ${FLAGS_FALSE} \ |
| 54 "Run make_local_repo indep of sync" |
| 55 DEFINE_boolean force_make_chroot ${FLAGS_FALSE} "Run make_chroot indep of sync" |
| 56 DEFINE_boolean build ${FLAGS_TRUE} \ |
| 57 "Build all code (but not necessarily master image)" |
| 58 DEFINE_boolean master ${FLAGS_TRUE} "Master an image from built code" |
| 59 DEFINE_string grab_buildbot "" \ |
| 60 "Instead of building, grab this full image.zip URI generated by the \ |
| 61 buildbot" |
| 62 DEFINE_string chronos_passwd "${CHRONOS_PASSWD}" \ |
| 63 "Use this as the chronos user passwd (defaults to \$CHRONOS_PASSWD)" |
| 64 DEFINE_boolean mod_image_for_test ${FLAGS_FALSE} "Modify the image for testing" |
| 65 DEFINE_boolean image_to_live ${FLAGS_FALSE} \ |
| 66 "Put the resulting image on live instance (requires --remote)" |
| 67 DEFINE_string remote "" \ |
| 68 "Use this hostname/IP for live updating and running tests" |
| 69 DEFINE_string image_to_usb "" \ |
| 70 "Treat this device as USB and put the image on it after build" |
| 71 DEFINE_string test "" \ |
| 72 "Test the built image with the given params to run_remote_tests" |
| 73 DEFINE_string buildbot_uri "${BUILDBOT_URI}" \ |
| 74 "Base URI to buildbot build location which contains LATEST file" |
| 75 DEFINE_boolean unittest ${FLAGS_TRUE} "Run unit tests" |
| 76 DEFINE_boolean prompt ${FLAGS_FALSE} \ |
| 77 "Tell user what we plan to do and wait for input to proceed" i |
| 78 |
| 79 |
| 80 # Returns a heuristic indicating if we believe this to be a google internal |
| 81 # development environment. |
| 82 # Returns: |
| 83 # 0 if so, 1 otherwise |
| 84 function is_google_environment() { |
| 85 hostname | egrep -q .google.com\$ |
| 86 return $? |
| 87 } |
| 88 |
| 89 |
| 90 # Validates parameters and sets "intelligent" defaults based on other |
| 91 # parameters. |
| 92 function validate_and_set_param_defaults() { |
| 93 if [[ -z "${FLAGS_top}" ]]; then |
| 94 local test_dir=$(pwd) |
| 95 while [[ "${test_dir}" != "/" ]]; do |
| 96 if [[ -d "${test_dir}/src/platform/pam_google" ]]; then |
| 97 FLAGS_top="${test_dir}" |
| 98 break |
| 99 fi |
| 100 test_dir=$(dirname "${test_dir}") |
| 101 done |
| 102 fi |
| 103 |
| 104 if [[ -z "${FLAGS_top}" ]]; then |
| 105 # Use the top directory based on where this script runs from |
| 106 FLAGS_top=$(dirname $(dirname $(dirname $0))) |
| 107 fi |
| 108 |
| 109 if [[ -z "${FLAGS_repo}" ]]; then |
| 110 if is_google_environment; then |
| 111 FLAGS_repo="ssh://git@chromiumos-git//chromeos" |
| 112 else |
| 113 FLAGS_repo="http://src.chromium.org/git/chromiumos.git" |
| 114 fi |
| 115 fi |
| 116 |
| 117 if [[ -n "${FLAGS_test}" ]]; then |
| 118 # If you specify that tests should be run, we assume the image |
| 119 # is modified to run tests. |
| 120 FLAGS_mod_image_for_test=${FLAGS_TRUE} |
| 121 # If you specify that tests should be run, we assume you want |
| 122 # to live update the image. |
| 123 FLAGS_image_to_live=${FLAGS_TRUE} |
| 124 fi |
| 125 |
| 126 # If they gave us a remote host, then we assume they want us to do a live |
| 127 # update. |
| 128 if [[ -n "${FLAGS_remote}" ]]; then |
| 129 FLAGS_image_to_live=${FLAGS_TRUE} |
| 130 fi |
| 131 |
| 132 # Grabbing a buildbot build is exclusive with building |
| 133 if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
| 134 if [[ -z "${FLAGS_buildbot_uri}" ]]; then |
| 135 echo "--grab_buildbot requires --buildbot_uri" |
| 136 exit 1 |
| 137 fi |
| 138 FLAGS_build=${FLAGS_FALSE} |
| 139 FLAGS_master=${FLAGS_FALSE} |
| 140 fi |
| 141 |
| 142 if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
| 143 if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_FALSE} ]]; then |
| 144 echo "WARNING: You have specified to live reimage a machine with" |
| 145 echo "an image that is not modified for test (so it cannot be" |
| 146 echo "later live reimaged)" |
| 147 fi |
| 148 if [[ -n "${FLAGS_image_to_usb}" ]]; then |
| 149 echo "WARNING: You have specified to both live reimage a machine and" |
| 150 echo "write a USB image. Is this what you wanted?" |
| 151 fi |
| 152 if [[ -z "${FLAGS_remote}" ]]; then |
| 153 echo "Please specify --remote with --image_to_live" |
| 154 exit 1 |
| 155 fi |
| 156 fi |
| 157 |
| 158 if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
| 159 # Override any specified chronos password with the test one |
| 160 local test_file=$(dirname $0)"/mod_for_test_scripts/test_account.passwd" |
| 161 FLAGS_chronos_passwd=$(head -1 "${test_file}") |
| 162 fi |
| 163 |
| 164 if [[ -n "${FLAGS_image_to_usb}" ]]; then |
| 165 local device=${FLAGS_image_to_usb#/dev/} |
| 166 if [[ -z "${device}" ]]; then |
| 167 echo "Expected --image_to_usb option of /dev/* format" |
| 168 exit 1 |
| 169 fi |
| 170 local is_removable=$(cat /sys/block/${device}/removable) |
| 171 if [[ "${is_removable}" != "1" ]]; then |
| 172 echo "Could not verify that ${device} for image_to_usb is removable" |
| 173 exit 1 |
| 174 fi |
| 175 fi |
| 176 } |
| 177 |
| 178 |
| 179 # Prints a description of what we are doing or did |
| 180 function describe_steps() { |
| 181 if [[ ${FLAGS_sync} -eq ${FLAGS_true} ]]; then |
| 182 echo " * Sync client (gclient sync)" |
| 183 if is_google_environment; then |
| 184 echo " * Create proper src/scripts/.chromeos_dev" |
| 185 fi |
| 186 fi |
| 187 if [[ ${FLAGS_force_make_local_repo} -eq ${FLAGS_true} ]]; then |
| 188 echo " * (Re-)create local package repository (make_local_repo.sh)" |
| 189 fi |
| 190 if [[ ${FLAGS_force_make_chroot} -eq ${FLAGS_true} ]]; then |
| 191 echo " * (Re-)create development chroot (make_chroot.sh)" |
| 192 fi |
| 193 local set_passwd=${FLAGS_FALSE} |
| 194 if [[ ${FLAGS_build} -eq ${FLAGS_true} ]]; then |
| 195 echo " * Build image (build_platform_packages.sh, build_kernel.sh)" |
| 196 set_passwd=${FLAGS_TRUE} |
| 197 fi |
| 198 if [[ ${FLAGS_master} -eq ${FLAGS_true} ]]; then |
| 199 echo " * Master image (build_image.sh)" |
| 200 fi |
| 201 if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
| 202 if [[ "${FLAGS_grab_buildbot}" == "LATEST" ]]; then |
| 203 echo " * Grabbing latest buildbot image under ${FLAGS_buildbot_uri}" |
| 204 else |
| 205 echo " * Grabbing buildbot image zip at URI ${FLAGS_grab_buildbot}" |
| 206 fi |
| 207 fi |
| 208 if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
| 209 echo " * Make image able to run tests (mod_image_for_test)" |
| 210 set_passwd=${FLAGS_TRUE} |
| 211 fi |
| 212 if [[ ${set_passwd} -eq ${FLAGS_TRUE} ]]; then |
| 213 if [[ -n "${FLAGS_chronos_passwd}" ]]; then |
| 214 echo " * Set chronos password to ${FLAGS_chronos_passwd}" |
| 215 else |
| 216 echo " * Set chronos password randomly" |
| 217 fi |
| 218 fi |
| 219 if [[ -n "${FLAGS_image_to_usb}" ]]; then |
| 220 echo " * Write the image to USB device ${FLAGS_image_to_usb}" |
| 221 fi |
| 222 if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
| 223 echo " * Reimage live test Chromium OS instance at ${FLAGS_remote}" |
| 224 fi |
| 225 if [[ -n "${FLAGS_test}" ]]; then |
| 226 echo " * Run tests (${FLAGS_test}) on machine at ${FLAGS_remote}" |
| 227 fi |
| 228 } |
| 229 |
| 230 |
| 231 # Get user's permission on steps to take |
| 232 function prompt() { |
| 233 echo "Planning these steps on ${FLAGS_top}:" |
| 234 describe_steps |
| 235 read -p "Are you sure (y/N)? " SURE |
| 236 # Get just the first character |
| 237 if [[ "${SURE:0:1}" != "y" ]]; then |
| 238 echo "Ok, better safe than sorry." |
| 239 exit 1 |
| 240 fi |
| 241 } |
| 242 |
| 243 |
| 244 # Runs gclient config on a new checkout directory. |
| 245 function config_new_checkout() { |
| 246 # We only know how to check out to a pattern like ~/foo/chromeos so |
| 247 # make sure that's the pattern the user has given. |
| 248 echo "Checking out ${FLAGS_top}" |
| 249 if [[ $(basename "${FLAGS_top}") != "chromeos" ]]; then |
| 250 echo "The --top directory does not exist and to check it out requires" |
| 251 echo "the name to end in chromeos (try --top=${FLAGS_top}/chromeos)" |
| 252 exit 1 |
| 253 fi |
| 254 local top_parent=$(dirname "${FLAGS_top}") |
| 255 mkdir -p "${top_parent}" |
| 256 cd "${top_parent}" |
| 257 gclient config "${FLAGS_repo}" |
| 258 } |
| 259 |
| 260 |
| 261 # Changes to a directory relative to the top/root directory of |
| 262 # the checkout. |
| 263 # Arguments: |
| 264 # $1 - relative path |
| 265 function chdir_relative() { |
| 266 local dir=$1 |
| 267 echo "+ cd ${dir}" |
| 268 # Allow use of .. before the innermost directory of FLAGS_top exists |
| 269 if [[ "${dir}" == ".." ]]; then |
| 270 dir=$(dirname "${FLAGS_top}") |
| 271 else |
| 272 dir="${FLAGS_top}/${dir}" |
| 273 fi |
| 274 cd "${dir}" |
| 275 } |
| 276 |
| 277 |
| 278 # Describe to the user that a phase is running (and make it obviously when |
| 279 # scrolling through lots of output). |
| 280 # Arguments: |
| 281 # $1 - phase description |
| 282 function describe_phase() { |
| 283 local desc="$1" |
| 284 echo "" |
| 285 echo "#" |
| 286 echo "#" |
| 287 echo "# ${desc}" |
| 288 echo "#" |
| 289 } |
| 290 |
| 291 |
| 292 # Runs a phase, describing it first, and also updates the sudo timeout |
| 293 # afterwards. |
| 294 # Arguments: |
| 295 # $1 - phase description |
| 296 # $2.. - command/params to run |
| 297 function run_phase() { |
| 298 local desc="$1" |
| 299 shift |
| 300 describe_phase "${desc}" |
| 301 echo "+ $@" |
| 302 "$@" |
| 303 sudo -v |
| 304 } |
| 305 |
| 306 |
| 307 # Runs gclient sync, setting up .chromeos_dev and preparing for |
| 308 # local repo setup |
| 309 function sync() { |
| 310 # cd to the directory below |
| 311 chdir_relative .. |
| 312 run_phase "Synchronizing client" gclient sync |
| 313 chdir_relative . |
| 314 git cl config "file://$(pwd)/codereview.settings" |
| 315 if is_google_environment; then |
| 316 local base_dir=$(dirname $(dirname "${FLAGS_top}")) |
| 317 echo <<EOF > src/scripts/.chromeos_dev |
| 318 # Use internal chromeos-deb repository |
| 319 CHROMEOS_EXT_MIRROR="http://chromeos-deb/ubuntu" |
| 320 CHROMEOS_EXT_SUITE="karmic" |
| 321 |
| 322 # Assume Chrome is checked out nearby |
| 323 CHROMEOS_CHROME_DIR="${base_dir}/chrome" |
| 324 EOF |
| 325 fi |
| 326 } |
| 327 |
| 328 |
| 329 # Downloads a buildbot image |
| 330 function grab_buildbot() { |
| 331 if [[ "${FLAGS_grab_buildbot}" == "LATEST" ]]; then |
| 332 local latest=$(curl "${FLAGS_buildbot_uri}/LATEST") |
| 333 if [[ -z "${latest}" ]]; then |
| 334 echo "Error finding latest." |
| 335 exit 1 |
| 336 fi |
| 337 FLAGS_grab_buildbot="${FLAGS_buildbot_uri}/${latest}/image.zip" |
| 338 fi |
| 339 local dl_dir=$(mktemp -d "/tmp/image.XXXX") |
| 340 echo "Grabbing image from ${FLAGS_grab_buildbot} to ${dl_dir}" |
| 341 run_phase "Downloading image" curl "${FLAGS_grab_buildbot}" \ |
| 342 -o "${dl_dir}/image.zip" |
| 343 cd "${dl_dir}" |
| 344 unzip image.zip |
| 345 echo "Copying in local_repo/local_packages" |
| 346 # TODO(kmixter): Make this architecture indep once buildbot is. |
| 347 mv -f local_repo/local_packages/* "${FLAGS_top}/src/build/x86/local_packages" |
| 348 local image_basename=$(basename $(dirname "${FLAGS_grab_buildbot}")) |
| 349 local image_dir="${FLAGS_top}/src/build/images/${image_basename}" |
| 350 echo "Copying in build image to ${image_dir}" |
| 351 rm -rf "${image_dir}" |
| 352 mkdir -p "${image_dir}" |
| 353 # Note that if mbr.image does not exist, this image was not successful. |
| 354 mv mbr.image rootfs.image "${image_dir}" |
| 355 chdir_relative . |
| 356 run_phase "Removing downloaded image" rm -rf "${dl_dir}" |
| 357 } |
| 358 |
| 359 |
| 360 function main() { |
| 361 assert_outside_chroot |
| 362 assert_not_root_user |
| 363 |
| 364 # Parse command line |
| 365 FLAGS "$@" || exit 1 |
| 366 eval set -- "${FLAGS_ARGV}" |
| 367 |
| 368 # Die on any errors. |
| 369 set -e |
| 370 |
| 371 validate_and_set_param_defaults |
| 372 |
| 373 # Cache up sudo status |
| 374 sudo -v |
| 375 |
| 376 if [[ ${FLAGS_prompt} -eq ${FLAGS_TRUE} ]]; then |
| 377 prompt |
| 378 fi |
| 379 |
| 380 if [[ ! -e "${FLAGS_top}" ]]; then |
| 381 config_new_checkout |
| 382 fi |
| 383 |
| 384 if [[ ${FLAGS_sync} -eq ${FLAGS_TRUE} ]]; then |
| 385 sync |
| 386 # The package repository is now potentially out of date, so |
| 387 # reflect that. |
| 388 run_phase "Removing existing package repo" sudo rm -rf repo |
| 389 FLAGS_force_make_local_repo=${FLAGS_TRUE} |
| 390 FLAGS_force_make_chroot=${FLAGS_TRUE} |
| 391 fi |
| 392 |
| 393 if [[ -n "${FLAGS_grab_buildbot}" ]]; then |
| 394 grab_buildbot |
| 395 fi |
| 396 |
| 397 if [[ ${FLAGS_force_make_local_repo} -eq ${FLAGS_TRUE} ]]; then |
| 398 chdir_relative src/scripts |
| 399 run_phase "Refetching local repo" ./make_local_repo.sh |
| 400 fi |
| 401 |
| 402 if [[ ${FLAGS_force_make_chroot} -eq ${FLAGS_TRUE} ]]; then |
| 403 chdir_relative src/scripts |
| 404 run_phase "Replacing chroot" ./make_chroot.sh --replace |
| 405 fi |
| 406 |
| 407 if [[ ${FLAGS_build} -eq ${FLAGS_TRUE} ]]; then |
| 408 chdir_relative src/scripts |
| 409 run_phase "Building platform packages and kernel" ./enter_chroot.sh \ |
| 410 "./build_platform_packages.sh && ./build_kernel.sh" |
| 411 |
| 412 if [[ ${FLAGS_build} -eq ${FLAGS_TRUE} ]]; then |
| 413 run_phase "Building and running unit tests" ./enter_chroot.sh \ |
| 414 "./build_tests.sh && ./run_tests.sh" |
| 415 fi |
| 416 fi |
| 417 |
| 418 if [[ ${FLAGS_master} -eq ${FLAGS_TRUE} ]]; then |
| 419 chdir_relative src/scripts |
| 420 if [[ -n "${FLAGS_chronos_passwd}" ]]; then |
| 421 describe_phase "Setting default chronos password" |
| 422 ./enter_chroot.sh "echo '${FLAGS_chronos_passwd}' | \ |
| 423 ./set_shared_user_password.sh" |
| 424 fi |
| 425 run_phase "Mastering image" ./enter_chroot.sh "./build_image.sh --replace" |
| 426 fi |
| 427 |
| 428 if [[ ${FLAGS_mod_image_for_test} -eq ${FLAGS_TRUE} ]]; then |
| 429 chdir_relative src/scripts |
| 430 run_phase "Modifying image for test" ./enter_chroot.sh \ |
| 431 "./mod_image_for_test.sh" |
| 432 fi |
| 433 |
| 434 if [[ -n "${FLAGS_image_to_usb}" ]]; then |
| 435 chdir_relative src/scripts |
| 436 run_phase "Installing image to USB" \ |
| 437 ./image_to_usb.sh --yes "--to=${FLAGS_image_to_usb}" |
| 438 fi |
| 439 |
| 440 if [[ ${FLAGS_image_to_live} -eq ${FLAGS_TRUE} ]]; then |
| 441 chdir_relative src/scripts |
| 442 run_phase "Re-imaging live Chromium OS machine ${FLAGS_remote}" \ |
| 443 ./image_to_live.sh "--remote=${FLAGS_remote}" --update_known_hosts |
| 444 fi |
| 445 |
| 446 if [[ -n "${FLAGS_test}" ]]; then |
| 447 chdir_relative src/scripts |
| 448 # We purposefully do not quote FLAGS_test below as we expect it may |
| 449 # have multiple parameters |
| 450 run_phase "Running tests on Chromium OS machine ${FLAGS_remote}" \ |
| 451 ./run_remote_tests.sh --remote="${FLAGS_remote}" ${FLAGS_test} |
| 452 fi |
| 453 |
| 454 echo "Successfully used ${FLAGS_top} to:" |
| 455 describe_steps |
| 456 } |
| 457 |
| 458 |
| 459 main $@ |
OLD | NEW |