blob: 257bcb09d17f87950868e1be3acb6e65dae47d66 [file] [log] [blame]
#!/usr/bin/env bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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
#
# 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.
#
#
# common and unlikely to change vars
#
# the upstream apache git repo for apache metron
METRON_UPSTREAM="https://gitbox.apache.org/repos/asf/metron.git"
# the upstream apache git repo for apache metron bro plugin kafka
BRO_PLUGIN_UPSTREAM="https://gitbox.apache.org/repos/asf/metron-bro-plugin-kafka.git"
# the common configuration file with the committer info
CONFIG_FILE=~/.metron-prepare-commit
GITHUB_REMOTE="origin"
BASE_BRANCH=master
# other var setup by these functions
PR=
WORK=
ORIGIN=
UPSTREAM=
PR_BRANCH=
USER=
EMAIL=
JIRA=
DESC=
APACHE_NAME=
APACHE_EMAIL=
GITHUB_NAME=
CHOSEN_REPO=
#
# Initialize the variables from the default configuration file, if it exists
#
function init_configuration {
# does a config file already exist?
echo "$CONFIG_FILE"
if [[ -f ${CONFIG_FILE} ]]; then
#shellcheck source=/dev/null
source ${CONFIG_FILE}
echo " ...using settings from $CONFIG_FILE"
fi
}
#
# Initialize the committer variables if they are not provided through the configuration file.
# If it is not present, it will be written out for the next time
#
function init_committer_info {
# github account of committer (you)
if [[ -z "$GITHUB_NAME" ]]; then
read -p " your github username [$GITHUB_NAME]: " INPUT
[[ -n "$INPUT" ]] && GITHUB_NAME=${INPUT}
# write setting to config file
echo "GITHUB_NAME=$GITHUB_NAME" >> ${CONFIG_FILE}
fi
# apache id of committer (you)
if [[ -z "$APACHE_NAME" ]]; then
read -p " your apache userid [$APACHE_NAME]: " INPUT
[[ -n "$INPUT" ]] && APACHE_NAME=${INPUT}
# write setting to config file
echo "APACHE_NAME=$APACHE_NAME" >> ${CONFIG_FILE}
fi
# apache email addr of committer (you)
if [[ -z "$APACHE_EMAIL" ]]; then
APACHE_EMAIL=${APACHE_NAME}@apache.org
read -p " your apache email [$APACHE_EMAIL]: " INPUT
[[ -n "$INPUT" ]] && APACHE_EMAIL=${INPUT}
# write setting to config file, so it is not needed next time
echo "APACHE_EMAIL=$APACHE_EMAIL" >> ${CONFIG_FILE}
fi
}
#
# Provide the user with a choice of the metron or bro repositories
#
function choose_metron_or_bro_repo {
# which repo? metron or metron-bro-plugin-kafka
echo " [1] metron"
echo " [2] metron-bro-plugin-kafka"
read -p " which repo? [1]: " INPUT
case "${INPUT}" in
[Bb][Rr][Oo]|[Mm][Ee][Tt][Rr][Oo][Nn]-[Bb][Rr][Oo]-[Pp][Ll][Uu][Gg][Ii][Nn]-[Kk][Aa][Ff][Kk][Aa]|*metron-bro-plugin-kafka\.git|2)
INPUT="${BRO_PLUGIN_UPSTREAM}" ;;
[Mm][Ee][Tt][Rr][Oo][Nn]|*metron\.git|1|'')
INPUT="${METRON_UPSTREAM}" ;;
*)
echo "Invalid repo, provided \"${INPUT}\". Please choose between metron or metron-bro-plugin-kafka"
exit 1
;;
esac
[[ -n "$INPUT" ]] && UPSTREAM=${INPUT}
CHOSEN_REPO=$(basename ${UPSTREAM%%.git})
}
#
# Ask the user for the PR number
#
function read_pull_request {
# retrieve the pull request identifier
read -p " pull request: " PR
if [[ -z "$PR" ]]; then
echo "Error: missing pr"
exit 1
fi
# ensure that the pull request exists
PR_EXISTS=$(curl -sI https://api.github.com/repos/apache/${CHOSEN_REPO}/pulls/${PR} | grep Status: | sed 's/[^0-9]//g')
if [[ "$PR_EXISTS" != "200" ]]; then
echo "Error: pull request #$PR does not exist"
exit 1
fi
}
#
# Setup the working directory.
# It is possible to override the default directory name by passing
# the desired directory name, using the available global variables
#
function setup_working_directory {
# working directory
if [[ -z $1 ]]; then
WORK=~/tmp/${CHOSEN_REPO}-pr${PR}
else
WORK=$1
fi
read -p " local working directory [$WORK]: " INPUT
[[ -n "$INPUT" ]] && WORK=${INPUT}
# handle tilde expansion
WORK="${WORK/#\~/$HOME}"
# warn the user if the working directory exists
if [[ -d "$WORK" ]]; then
read -p " directory exists [$WORK]. continue merge on existing repo? [yN] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
#
# If required will clone the desired repo. The default repo is metron, but an override
# may be passed as a parameter.
# If the directory already exists, it will ask the user for the name of the remote to use, with the
# default being "origin"
#
function setup_code {
# if working directory does not exist, checkout the base branch
if [[ ! -d "$WORK" ]]; then
REPO_NAME="metron"
if [[ -n $1 ]]; then
REPO_NAME=$1
fi
# origin repository
ORIGIN="https://github.com/apache/${REPO_NAME}"
read -p " origin repo [$ORIGIN]: " INPUT
[[ -n "$INPUT" ]] && ORIGIN=${INPUT}
# what branch did the PR get submitted against? could be a feature branch
BASE_BRANCH=$(curl -s https://api.github.com/repos/apache/${REPO_NAME}/pulls/${PR} | python -c 'import sys, json; print json.load(sys.stdin)["base"]["ref"]')
read -p " base branch to merge into [$BASE_BRANCH]: " INPUT
[[ -n "$INPUT" ]] && BASE_BRANCH=${INPUT}
# clone the repository and fetch updates
mkdir -p ${WORK}
git clone ${ORIGIN} ${WORK}
cd ${WORK} &> /dev/null || { echo "failed to change directory to ${WORK}" ; exit 1 ;}
# setup the git user and email for your apache account
git config user.name "$APACHE_NAME"
git config user.email "$APACHE_EMAIL"
# fetch any changes from upstream
git remote add upstream ${UPSTREAM}
if git fetch upstream "$BASE_BRANCH"; then
if [[ ${BASE_BRANCH} = "master" ]]; then
# merge any changes from upstream
git checkout ${BASE_BRANCH}
git merge upstream/${BASE_BRANCH}
else
# create a local branch from the remote feature branch
git checkout -B ${BASE_BRANCH} upstream/${BASE_BRANCH}
fi
else
# unable to fetch the base branch
exit $?
fi
else
# if the repo already exists, allow the user to provide the name of the Github remote
# this is needed to checkout the code for the PR
read -p " name of github remote [$GITHUB_REMOTE]: " INPUT
[[ -n "$INPUT" ]] && GITHUB_REMOTE=${INPUT}
fi
PR_BRANCH_REF="pull/$PR/head:pr-$PR"
PR_BRANCH="pr-$PR"
cd ${WORK} &> /dev/null || { echo "failed to change directory to ${WORK}" ; exit 1 ;}
git fetch ${GITHUB_REMOTE} ${PR_BRANCH_REF}
echo ""
}
#
# Populates the contributor information from the PR information
#
function get_contributor_info {
# use github api to retrieve the contributor's login
USER=$(curl -s https://api.github.com/repos/apache/${CHOSEN_REPO}/pulls/${PR} | grep login | head -1 | awk -F":" '{print $2}' | sed 's/[^a-zA-Z0-9.@_-]//g')
read -p " github contributor's username [$USER]: " INPUT
[[ -n "$INPUT" ]] && USER=${INPUT}
# validate the github contributor
if [[ -z "$USER" ]]; then
echo "Error: missing username"
exit 1
fi
# retrieve the contributor's email from the git commit history
EMAIL=$(git log ${PR_BRANCH} | grep Author | head -1 | awk -F"<" '{print $2}' | sed 's/[<>]//g')
read -p " github contributor's email [$EMAIL]: " INPUT
[[ -n "$INPUT" ]] && EMAIL=${INPUT}
# validate email
if [[ -z "$EMAIL" ]] || [[ "$EMAIL" = "null" ]]; then
echo "Error: missing email"
exit 1
fi
}
#
# Populate the information for the JIRA associated with the PR
#
function get_jira_info {
# can we extract the JIRA from the PR title?
JIRA=$(curl -s https://api.github.com/repos/apache/${CHOSEN_REPO}/pulls/${PR} | grep title | head -1 | egrep -o -i 'METRON-[0-9]+' | awk '{print toupper($0)}')
read -p " issue identifier in jira [$JIRA]: " INPUT
[[ -n "$INPUT" ]] && JIRA=${INPUT}
# validate the JIRA issue
if [[ -z "$JIRA" ]]; then
echo "Error: missing jira"
exit 1
fi
# attempt to use the jira api to get a description of the jira
DESC=$(curl -s https://issues.apache.org/jira/si/jira.issueviews:issue-xml/${JIRA}/${JIRA}.xml | grep "<summary>" | sed 's/^.*<summary>//' | sed 's/<.summary>.*$//')
read -p " issue description [$DESC]: " INPUT
[[ -n "$INPUT" ]] && DESC=${INPUT}
# validate description
if [[ -z "$DESC" ]]; then
echo "Error: missing description"
exit 1
fi
}
#
# Merge and Commit
#
function commit {
# commit message
AUTHOR="$USER <$EMAIL>"
if [[ "$USER" == "$GITHUB_NAME" ]]; then
MSG="$JIRA $DESC ($USER) closes apache/${CHOSEN_REPO}#$PR"
else
MSG="$JIRA $DESC ($USER via $GITHUB_NAME) closes apache/${CHOSEN_REPO}#$PR"
fi
read -p " commit message [$MSG]: " INPUT
[[ -n "$INPUT" ]] && MSG=${INPUT}
# merge the contributor's branch and commit
echo ""
if git merge --squash "$PR_BRANCH"; then
git commit --author="$AUTHOR" -a -m "$MSG"
else
exit $?
fi
}
#
# Displays the commit info ( the diff and log )
#
function review_commit_info {
# review the commit
git diff --stat --color "upstream/$BASE_BRANCH..$BASE_BRANCH"
echo ""
echo ""
git log --oneline "$BASE_BRANCH" "^upstream/$BASE_BRANCH"
}
#
# Runs the metron unit, integration and metron-interface tests
#
function run_tests {
read -p " run test suite? [yN] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [[ "${UPSTREAM}" == "${METRON_UPSTREAM}" ]]; then
clean_metron_src
run_mvn_install
run_mvn_unit_tests
run_mvn_integration_tests
run_mvn_ui_tests
run_mvn_build_rpms
verify_licenses
elif [[ "${UPSTREAM}" == "${BRO_PLUGIN_UPSTREAM}" ]]; then
echo " please verify that no bro docker containers are running before continuing,"
read -p " no bro docker containers are running, ready to proceed [yN] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
run_bro_docker
finish_bro_docker
else
echo " when you are ready and the containers are stopped, please cd into the docker"
echo " directory and execute the run_end_to_end.sh script"
fi
fi
fi
}
#
# Cleans the metron src and rpms
#
function clean_metron_src {
mvn -q clean
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED TO CLEAN TOP LEVEL MVN PROJECT"
exit ${rc}
fi
cd metron-deployment &> /dev/null || { echo "failed to change directory to metron-deployment" ; exit 1 ;}
mvn -q clean -Pbuild-rpms
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED TO CLEAN RPMS"
exit ${rc}
fi
cd .. &> /dev/null || { echo "failed to change directory to metron source root" ; exit 1 ;}
}
#
# runs the mvn install
#
function run_mvn_install {
mvn -q -T 2C -DskipTests clean install
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED mvn install"
exit ${rc}
fi
}
#
# runs the mvn unit tests
#
function run_mvn_unit_tests {
mvn -q -T 2C surefire:test@unit-tests
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED mvn unit tests"
exit ${rc}
fi
}
#
# runs the mvn integration tests
#
function run_mvn_integration_tests {
mvn -q surefire:test@integration-tests
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED mvn integration-tests"
exit ${rc}
fi
}
#
# runs the mvn ui related tests
#
function run_mvn_ui_tests {
mvn -q test --projects metron-interface/metron-config,metron-interface/metron-alerts
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED mvn tests for metron-config and metron-alerts"
exit ${rc}
fi
}
#
# runs the mvn rpm build
#
function run_mvn_build_rpms {
cd metron-deployment &> /dev/null || { echo "failed to change directory to metron-deployment" ; exit 1 ; }
mvn -q package -Pbuild-rpms
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED mvn build-rpms"
exit ${rc}
fi
}
#
# runs the bro kafka plugin's docker based tests
#
function run_bro_docker {
cd docker &> /dev/null || { echo "failed to change directory to docker" ; exit 1; }
./run_end_to_end.sh
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED run_end_to_end"
# do NOT exit here
fi
cd .. &> /dev/null || { echo "failed to change directory to plugin root"; exit 1; }
}
#
# runs the finish bro docker script to cleanup
#
function finish_bro_docker {
cd docker &> /dev/null || { echo "failed to change directory to docker"; exit 1; }
./finish_end_to_end.sh
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED finish_end_to_end"
exit ${rc}
fi
cd .. &> /dev/null || { echo "failed to change directory to plugin root";
exit 1; }
}
#
# verifies licenses using our script
#
function verify_licenses {
dev-utilities/build-utils/verify_licenses.sh
rc=$?; if [[ ${rc} != 0 ]]; then
echo "ERROR> FAILED license verification"
exit ${rc}
fi
}
#
# Gives the user instruction on next steps
#
function please_review_then {
echo ""
echo "Review commit carefully then run..."
echo " cd $WORK"
echo " git push upstream $BASE_BRANCH"
echo ""
}