From 3735a516402208720f5fd7d104b2b882d762d2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emek=20Vysok=C3=BD?= Date: Wed, 7 Dec 2022 20:06:24 +0100 Subject: [PATCH] Add a script for reproing VMR synchronization failures locally (#15097) --- eng/vmr-sync.sh | 180 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 eng/vmr-sync.sh diff --git a/eng/vmr-sync.sh b/eng/vmr-sync.sh new file mode 100644 index 000000000..f948ff503 --- /dev/null +++ b/eng/vmr-sync.sh @@ -0,0 +1,180 @@ +#!/bin/bash + +### This script helps to reproduce potential failures of the 'Synchronize dotnet/dotnet' +### build step from the **VMR Source-Build** job locally. +### The following scenario is assumed: +### - There is a PR in dotnet/installer +### - The PR is failing on the 'VMR Source-Build' job in the 'Synchronize dotnet/dotnet' step +### +### There are a few possible reasons but usually this happens because there is a mismatch between +### source patches that are applied on top of the files that are being synchronized from repositories +### into the 'dotnet/dotnet' repo and new changes in the repositories. +### This manifests as the following error: +### fail: Failed to synchronize repo installer +### Failed to apply the patch for src/aspnetcore +### Exit code: 1 +### Std err: +### error: patch failed: src/aspnetcore/eng/SourceBuild.props:55 +### error: src/aspnetcore/eng/SourceBuild.props: patch does not apply +### +### where 'src/aspnetcore/eng/SourceBuild.props' would be the file that is being patched and new +### changes to it are conflicting with the patch that is being applied. +### +### The whole process can be reproduced locally easily by running this script. +### The patches are located in a folder in the 'dotnet/installer' repository. +### At the moment of writing, the location is 'src/SourceBuild/tarball/patches' but to get +### the up-to-date location, please see the 'patchesPath' property in +### https://github.com/dotnet/dotnet/blob/main/src/source-mappings.json +### +### You will need to compare what is in the patch and what is in the file and fix the patch. +### +### The tooling that synchronizes the VMR will need to clone the various repositories. +### It clones them into a temporary folder and re-uses them on future runs so it is advised +### you dedicate a folder to this to speed up your re-runs. +### +### This script will synchronize the 'dotnet/dotnet' repo locally and let you inspect the changes. +### +### USAGE: +### ./vmr-sync.sh --tmp-dir "$HOME/repos/tmp" +### Options: +### -t, --tmp, --tmp-dir PATH +### Required. Path to the temporary folder where repositories will be cloned +### -v, --vmr, --vmr-dir PATH +### Optional. Path to the dotnet/dotnet repository. When null, gets cloned to the temporary folder +### -b, --branch, --vmr-branch BRANCH_NAME +### Optional. Branch of the 'dotnet/dotnet' repo to synchronize to +### This should match the target branch of the PR, defaults to 'main' +### --debug +### Optional. Turns on the most verbose logging for the VMR tooling + +source="${BASH_SOURCE[0]}" + +# resolve $source until the file is no longer a symlink +while [[ -h "$source" ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" +done +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + +function print_help () { + sed -n '/^### /,/^$/p' "$source" | cut -b 5- +} + +COLOR_RED=$(tput setaf 1 2>/dev/null || true) +COLOR_CYAN=$(tput setaf 6 2>/dev/null || true) +COLOR_CLEAR=$(tput sgr0 2>/dev/null || true) +COLOR_RESET=uniquesearchablestring +FAILURE_PREFIX='> ' + +function fail () { + echo "${COLOR_RED}$FAILURE_PREFIX${1//${COLOR_RESET}/${COLOR_RED}}${COLOR_CLEAR}" >&2 +} + +function highlight () { + echo "${COLOR_CYAN}$FAILURE_PREFIX${1//${COLOR_RESET}/${COLOR_CYAN}}${COLOR_CLEAR}" +} + +installer_dir="$scriptroot/../" +tmp_dir='' +vmr_dir='' +vmr_branch='main' +verbosity=verbose +# hashed name coming from the VMR tooling +INSTALLER_TMP_DIR_NAME='03298978DFFFCD23' + +while [[ $# -gt 0 ]]; do + opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" + case "$opt" in + -t|--tmp|--tmp-dir) + tmp_dir=$2 + shift + ;; + -v|--vmr|--vmr-dir) + vmr_dir=$2 + shift + ;; + -b|--branch|--vmr-branch) + vmr_branch=$2 + shift + ;; + -d|--debug) + verbosity=debug + ;; + -h|--help) + print_help + exit 0 + ;; + *) + fail "Invalid argument: $1" + usage + exit 1 + ;; + esac + + shift +done + +if [[ ! -d "$installer_dir" ]]; then + fail "Directory '$installer_dir' does not exist. Please specify the path to the dotnet/installer repo" + exit 1 +fi + +if [[ -z "$tmp_dir" ]]; then + fail "Missing --tmp-dir argument. Please specify the path to the temporary folder where the repositories will be cloned" + exit 1 +fi + +if [[ -z "$vmr_dir" ]]; then + vmr_dir="$tmp_dir/dotnet" +fi + +if [[ ! -d "$tmp_dir" ]]; then + mkdir -p "$tmp_dir" +fi + +if [[ ! -d "$vmr_dir" ]]; then + highlight "Cloning 'dotnet/dotnet' into $vmr_dir.." + git clone https://github.com/dotnet/dotnet "$vmr_dir" +else + if ! git -C "$vmr_dir" diff --quiet; then + fail "There are changes in the working tree of $vmr_dir. Please commit or stash your changes" + exit 1 + fi + + highlight "Preparing $vmr_dir" + git -C "$vmr_dir" checkout "$vmr_branch" + git -C "$vmr_dir" pull +fi + +set -e + +# These lines makes sure the temp dir (which the tooling would clone) +# has the synchronized commit inside as well +highlight 'Preparing the temporary directory..' +rm -rf "${tmp_dir:?}/$INSTALLER_TMP_DIR_NAME" +git clone "$installer_dir" "${tmp_dir:?}/$INSTALLER_TMP_DIR_NAME" + +# Prepare darc +highlight 'Installing .NET, preparing the tooling..' +source "$scriptroot/common/tools.sh" +InitializeDotNetCli true +dotnet="$scriptroot/../.dotnet/dotnet" +"$dotnet" tool restore + +# Run the sync +target_sha=$(git -C "$installer_dir" rev-parse HEAD) +highlight "Starting the synchronization to $target_sha.." +set +e + +if "$dotnet" darc vmr update --vmr "$vmr_dir" --tmp "$tmp_dir" --$verbosity --recursive installer:$target_sha; then + highlight "Synchronization succeeded" +else + fail "Synchronization of dotnet/dotnet to $target_sha failed!" + fail "$vmr_dir is left in its last state (re-run of this script will reset it)." + fail "Please inspect the logs which contain path to the failing patch file (use --debug to get all the details)." + fail "Once you make changes to the conflicting VMR patch, commit it locally and re-run this script." + exit 1 +fi