go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/scripts/test-ftt (about)

     1  #!/bin/bash
     2  
     3  # Copyright 2023 The LUCI Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  # http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  # sample usage and meaning
    18  #
    19  # ./test-fft -i   ~/cr     -p      9
    20  #               infra-dir      patchset-#
    21  
    22  # Defensively set the CDPATH to something safe before doing anything.
    23  export CDPATH=
    24  
    25  # This script owns the branch below in every git repo ever. This should be safe
    26  # since it contains a UUID.
    27  readonly MY_INFRA_BRANCH='ftt-test-branch-149cb550-9322-46a2-a27d-06c05781102d'
    28  export MY_INFRA_BRANCH
    29  # We use the devel branch in the LUCI repo to make it easier to patch the
    30  # commit series and upload a new chain.
    31  readonly MY_DEVEL_BRANCH='ftt-devel-branch-91e1de00-c43a-4d07-b6fe-ed05322a465b'
    32  export MY_DEVEL_BRANCH
    33  
    34  # die writes a message to stderr and then exits abnormally.
    35  die() {
    36    printf '%s\n' "$@" 1>&2
    37    exit 1
    38  }
    39  
    40  # checkdep checks for a dependency and dies if it isn't available.
    41  checkdep() {
    42    which -- "$1" 1>/dev/null 2>/dev/null || die 'missing dependency: '"$1"
    43  }
    44  
    45  # backup_self backs up the currently-executing script to ~/test-ftt.
    46  # We do this for convenience.
    47  #
    48  # The script test-ftt is itself checked into the LUCI git repo.
    49  # It also manipulates the git state, which can cause changes to the script
    50  # to be removed from the working directory. We copy ourselves to the home
    51  # directory in order to make it easier to tweak something and then immediately
    52  # run the script again.
    53  backup_self() {
    54    cp -- "${HOME}/test-ftt" "${HOME}/test-ftt.BAK" 1>/dev/null 2>/dev/null
    55    if cmp --silent -- "${selfpath}" "${HOME}"/test-ftt; then
    56      return
    57    fi
    58    cp -- "${selfpath}" "${HOME}"/test-ftt || die 'failed to back up self'
    59  }
    60  
    61  # must_check_git_clean checks that the git repo pointed to by $1 is clean.
    62  # We die informatively if it is not clean.
    63  #
    64  # Submodules being dirty or pointing to the wrong commit is okay here. We are only
    65  # concerend about preventing the user from losing work.
    66  must_check_git_clean() {
    67    [[ -z "$(git -C "$1" status --porcelain --ignore-submodules=all)" ]] || die "directory '$1' is not clean"
    68  }
    69  
    70  # must_checkout_patchset_in_luci_dir checks out the patchset specified by the user in the luci directory.
    71  # This function is only safe to call if we have already checked that the directory is clear.
    72  must_checkout_patchset_in_luci_dir() {
    73    # (1/5) Clear the local version of the dev branch so we have somewhere to work. We don't care whether the branch exists or not.
    74    git -C "$luci_dir" branch -D "$MY_DEVEL_BRANCH" 1>/dev/null 2>/dev/null
    75    # (2/5) Fetch the user-specified patchset. Don't check whether it's the latest or not because I don't know how to do that.
    76    git -C "$luci_dir" fetch https://chromium.googlesource.com/infra/luci/luci-go refs/changes/51/4917851/"$patchset" || die 'failed to fetch patchset'
    77    # (3/5) Move the working directory to point at the thing that we just fetched.
    78    git -C "$luci_dir" checkout FETCH_HEAD || die 'failed to check out fetch head after fetching patch. Wowzers.'
    79    # (4/5) Drop a branch to save our current location. Use the branch name that we freed in step 1.
    80    git -C "$luci_dir" checkout -b "$MY_DEVEL_BRANCH" || die 'failed to drop development branch for later devleopment'
    81    # (5/5) Set the tracking branch of the branch that we just dropped to the upstream so that we can run 'git cl upload' later.
    82    git -C "$luci_dir" branch -u "origin/main" || die 'failed to set the upstream branch of the development branch correctly'
    83  }
    84  
    85  # main takes the input args and runs the tests.
    86  main() {
    87    local -r usage='test-ftt [-h] [-i infra-dir] [-p patchset-number]
    88  
    89    This script produces the branch "ftt-test-branch-149cb550-9322-46a2-a27d-06c05781102d"
    90    in the infra tree. This branch is temporary.
    91  
    92    This script produces the branch "ftt-devel-branch-149cb550-9322-46a2-a27d-06c05781102d"
    93    in the LUCI tree. This branch can be modified and then re-uploaded.
    94    '
    95  
    96    while getopts ':hi:p:' opt; do
    97      case "${opt}" in
    98        h) printf '%s' "${usage}"; exit 0;;
    99        i) local infra_dir="${OPTARG}";;
   100        p) local patchset="${OPTARG}";;
   101        :)
   102           1>&2 printf '%s' "${usage}"; exit 1;;
   103        *)
   104           1>&2 printf '%s' "${usage}"; exit 1;;
   105      esac
   106    done
   107  
   108    checkdep 'realpath'
   109    checkdep 'git'
   110    checkdep 'mktemp'
   111    checkdep 'cp'
   112    checkdep 'unlink'
   113  
   114    [[ -n ${infra_dir} ]] || die "no directory given"
   115    [[ -e ${infra_dir} ]] || die "path \`${infra_dir}' does not exist"
   116    [[ -d ${infra_dir} ]] || die "path \`${infra_dir}' is not directory"
   117  
   118    [[ -n "${patchset}" ]] || die 'no patchset given'
   119  
   120    local -r selfpath="$(realpath -- "$0")"
   121  
   122    local -r infra_dir="$(realpath -- "${infra_dir}")" || die "failed to get realpath to \`$1'"
   123  
   124    # cd to a defensive dir so we catch inadvertent uses of relative paths rather
   125    # than computed absolute paths.
   126    local -r defensive_dir="$(mktemp -d)" || die 'failed to make defensive dir'
   127    cd -- "${defensive_dir}" || die 'failed to cd to defensive dir'
   128  
   129    [[ -f ${infra_dir}/.gclient ]] || die 'failed heuristic: no gclient file: is the file path correct?'
   130  
   131    local -r luci_dir="${infra_dir}"/infra/go/src/go.chromium.org/luci
   132  
   133    [[ -d $luci_dir ]] || die "luci directory \`${luci_dir}' does not exist or is not directory"
   134    [[ -f $luci_dir/AUTHORS ]] || die "failed heuristic: derived directory \`${luci_dir}' has no AUTHORS file"
   135  
   136    local -r infra_go_root="${infra_dir}/infra/go/src/infra"
   137    [[ -d "${infra_dir}" ]] || die "infra go root directory ${infra_go_root} does not exist"
   138    [[ -d "${infra_go_root}/unifiedfleet" ]] || die "failed heuristic: derived directory '${infra_go_root}/unifiedfleet' does not exist."
   139  
   140    must_check_git_clean "${infra_go_root}"
   141    must_check_git_clean "${luci_dir}"
   142  
   143    # Back ourselves up, after this point all subsequent commands can change the git state.
   144    backup_self
   145  
   146    must_checkout_patchset_in_luci_dir
   147  
   148    die 'not yet implemented'
   149  }
   150  
   151  main "$@"