Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 203 additions & 0 deletions Utilities/Maintenance/ApplyScriptToRemotes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#!/bin/bash

#==========================================================================
#
# Copyright Insight Software Consortium
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#==========================================================================*/


# This script, given a path to another script, applies this to the source
# code of the remote modules in the ITK source tree whose CI status shows
# a successful build.
#
# The script clones the successful remote modules to the ITK source tree,
# creates a feature branch on each module, applies the provided script to the
# source code of each module, adds the modified files to the git stage area,
# commits them using the provided commit message, and pushes the commit to the
# remote module repository.
#
# Please, review the commit message directives at:
# https://github.com/InsightSoftwareConsortium/ITK/blob/master/CONTRIBUTING.md


# Utility functions
usage() {
cat << EOF
Usage: $0 <script_filename> <feature_branch> <commit_message>

Use this script to apply another script to the source code of the remote
remote modules in the ITK source tree whose CI status shows a successful
build.

The script clones the successful remote modules to the ITK source tree,
creates a feature branch on each module, applies the provided script to the
source code of each module, adds the modified files to the git stage area,
commits them using the provided commit message, and pushes the commit to the
remote module repository.

Please, review the commit message directives at:
https://github.com/InsightSoftwareConsortium/ITK/blob/master/CONTRIBUTING.md
EOF
}

die() {
echo "$@" 1>&2; exit 1
}

# Parse arguments
help=false
script=""
feature_branch=""
commit_message=""
while test $# -gt 0;
do
opt="$1";
case "$opt" in
"-h"|"--help")
shift;
help=true
break;;
*)
break;;
esac
done

script="$1"
feature_branch="$2"
commit_message="$3"

if test "${script}" = "" || "${feature_branch}" = "" || "${commit_message}" = "" || $help; then
usage
exit 1
fi

# Make sure we are inside the repository
cd "${BASH_SOURCE%/*}" &&

remote_modules_path='../../Modules/Remote'

# Ask for GitHub username and password once
echo "Please provide your GitHub (https://github.com)"
read -p "username: " username
read -p "password: " -s password

remotes=()

function list_candidate_remotes() {
if [ $# -ge 1 ] && [ $1 = "-ongreen" ]; then
ongreen=1
failing=()
else
ongreen=0
fi

# Loop over the remote modules' CMake files
for filename in ${remote_modules_path}/*.cmake; do
echo -n "."

# Get the current module name
module_name=$(grep -v "\s*#" $filename | grep -m 1 -o "itk_fetch_module(\(\w\|\.\|\-\|_\)*")
module_name=${module_name/*itk_fetch_module(/}

# Get the current commit hash
curr_commit=$(grep -v "\s*#" $filename | grep -m 1 -o "GIT_TAG \(\w\|\.\|\-\|_\)*")
curr_commit=${curr_commit/*GIT_TAG /}

# Read the git repository information
repository=$(grep -v "\s*#" $filename | grep -m 1 -o "GIT_REPOSITORY \${git_protocol}://github.com/\(\w\|\-\|_\|/\)*")
repository=${repository/*GIT_REPOSITORY \${git_protocol\}:\/\/github.com\//}

# Get the latest git commit hash of the remote module.
# Remotes will usually not be tagged.
latest_commit=$(git ls-remote git://github.com/$repository refs/heads/master)
latest_commit=${latest_commit/[[:space:]]refs\/heads\/master/}

# Skip remotes whose current commit in ITK differs from the latest
if [ $curr_commit != $latest_commit ]; then
continue
fi

# Get the remotes' build status
if [ $ongreen -eq 1 ]; then
# Get the repository status
# Be careful of rate limiting (https://developer.github.com/v3/#rate-limiting)
# alternatively using Azure: https://docs.microsoft.com/en-us/azure/data-factory/monitor-programmatically#rest-api
status=$(curl -s https://api.github.com/repos/$repository/commits/$latest_commit/status | grep -m 1 -o "\"state\": \"\w*\"")
if [ "$status" != "\"state\": \"success\"" ]; then
continue
fi
fi

remotes+=($module_name)

done
}

function configure_itk_remotes() {
mkdir ../../../ITK-build
cd ../../../ITK-build

cmake_remote_flags=()

# Switch on all remotes that have a success build status
for remote in ${remotes[@]}; do
cmake_remote_flags+=(-D'Module_'$remote':BOOL=ON' )
done

cmake ${cmake_remote_flags[@]} ../ITK
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completing all CMake configuration steps is not necessary, so should we just extract (if that is possible) the relevant parts from the CMakeLists.txt to clone the remotes in the ITK source tree?

}

function apply_script_and_push_remotes() {
cd ../ITK/Modules/Remote

# Loop over remotes and apply the changes
for remote in ${remotes[@]}; do
echo -e $remote

cd $remote

repository_basename=$(basename -s .git `git config --get remote.origin.url`)

git checkout master
git checkout -b $feature_branch origin/master
$script

# Add the files, adding filters if necessary
git add -u *.txt ./*.cmake ./*.rst ./*.py ./*.yml ./*.c ./*.cxx ./*.h ./*.hxx ./*.wrap
Copy link
Member Author

@jhlegarreta jhlegarreta Apr 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed files are not added to the commit.

Otherwise, we could assume that a git add . could be done since it will be a new branch, with no files and changes other than those applied by the script.


# Commit and push to the feature branch
git commit -m $commit_message
git push --quiet https://$username:$password@github.com/$username/$repository_basename $feature_branch
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Rather that keeping the remote URLs from the list_candidate_remotes function, I do get the URL again in apply_script_and_push_remotes. I though it was easier than keeping a list from the former method, then finding the appropriate element for the remote at issue (partly because the URL includes the username and password for the push to be done). If you feel there is an alternative to this, please go ahead.


cd ..
done
}

echo -e "\nChecking remote modules build status..."
list_candidate_remotes
echo -e "\nDone checking remote modules build status."

echo -e "Configuring ITK with succeeding remote modules..."
configure_itk_remotes
echo -e "Done configuring ITK with succeeding remote modules."

echo -e "Applying script to remotes..."
apply_script_and_push_remotes
echo -e "Done applying script to remotes."

rm -r ../../../ITK-build

echo -e "Visit the remote repositories and open the corresponding pull requests."