diff --git a/Dockerfile b/Dockerfile index 4a37cc4..34abd37 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,8 @@ FROM alpine:3.7 RUN apk --no-cache add \ bash=4.4.19-r1 \ ca-certificates=20171114-r0 \ - curl=7.60.0-r1 \ - git=2.15.0-r1 \ + curl=7.61.0-r0 \ + git=2.15.2-r0 \ jq=1.5-r5 \ openssh-client=7.5_p1-r8 diff --git a/README.md b/README.md index 3ccaec4..d09ad05 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,10 @@ If a match is found the pull request will be rebuilt. * `create_comments`: *Optional (default: false).* If true write comments with build status to pull requests. +* `paths`: *Optional (default "[]" - matches all).* If specified (as a list of regular expression patterns), only changes to the specified files will be built. + +* `ignore_paths`: *Optional (default "[]" - matches nothing).* If specified (as a list of regular expression patterns), changes to the specified files will not be built, unless other paths have also been changed. + ## Behavior ### `check`: Search for pull requests to build. diff --git a/assets/check b/assets/check index b191f97..1441576 100755 --- a/assets/check +++ b/assets/check @@ -40,6 +40,8 @@ only_when_asked=$(jq -r '.source.only_when_asked // "false"' < "$payload") rebuild_when_target_changed=$(jq -r '.source.rebuild_when_target_changed // "false"' < "$payload") rebuild_phrase=$(jq -r '.source.rebuild_phrase // "test this please"' < "$payload") CURRENT_VERSION_DATE=$(jq -r '.version.date // "0"' < "$payload") +paths=$(jq -r '.source.paths // []' < "${payload}") +ignore_paths=$(jq -r '.source.ignore_paths // []' < "${payload}") configure_git_ssl_verification "$skip_ssl_verification" configure_git_global "${git_config_payload}" @@ -137,6 +139,11 @@ if [ -n "$PULL_REQUESTS" ]; then continue fi + has_changes_in_specified_paths=$(does_pullrequest_include_changes_in_paths "$repo_host" "$repo_project" "$repo_name" "$prq_number" "$paths" "$ignore_paths" "" "$skip_ssl_verification") + if [ "${has_changes_in_specified_paths}" != "true" ]; then + continue + fi + # add prq to versions if [ "$skip_build" == "false" ]; then versions+=" + [{ id: \"$prq_number\", hash: \"$prq_hash\", date: \"$PULL_REQUEST_DATE\" }]" diff --git a/assets/helpers/bitbucket.sh b/assets/helpers/bitbucket.sh index e97f84a..5d7dbf3 100755 --- a/assets/helpers/bitbucket.sh +++ b/assets/helpers/bitbucket.sh @@ -66,8 +66,9 @@ bitbucket_request() { if [ "$(jq -r '.isLastPage' < "$request_result")" == "false" ]; then local nextPage=$(jq -r '.nextPageStart' < "$request_result") - local nextResult=$(bitbucket_request "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "start=${nextPage}&limit=${VALUES_LIMIT}") - jq -c '.values' < "$request_result" | jq -c ". + $nextResult" + bitbucket_request "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "start=${nextPage}&limit=${VALUES_LIMIT}" > tmp.json + + jq -s -c '.[0].values + .[1]' "$request_result" "tmp.json" elif [ "$(jq -c '.values' < "$request_result")" != "null" ]; then jq -c '.values' < "$request_result" elif [ "$(jq -c '.errors' < "$request_result")" == "null" ]; then @@ -82,7 +83,7 @@ bitbucket_request() { printf "DECLINED" return else - log "Bitbucket request ($request_url) failed: $(cat $request_result)" + log "Bitbucket request ($request_url) failed: $(cat ${request_result})" exit 1 fi @@ -229,3 +230,85 @@ bitbucket_pullrequest_update_comment_status() { log "Updating pull request comment (id: $6) for status on #$4 for $2/$3" bitbucket_request "$1" "projects/$2/repos/$3/pull-requests/$4/comments/$6" "" "{\"text\": \"$5\", \"version\": \"$7\" }" "" "$9" "$8" "PUT" } + +bitbucket_pullrequest_changes() { + # $1: host + # $2: project + # $3: repository id + # $4: pullrequest id + # $5: netrc file (default: $HOME/.netrc) + # $6: skip ssl verification + + log "Retrieving pull request changes #$4 for $2/$3" + bitbucket_request "$1" "projects/$2/repos/$3/pull-requests/$4/changes" "" "" "" "$6" "$5" +} + +does_pullrequest_include_changes_in_paths() { + # $1: host + # $2: project + # $3: repository id + # $4: pullrequest id + # $5: paths + # $6: ignore paths + # $7: netrc file (default: $HOME/.netrc) + # $8: skip ssl verification + + local paths=$5 + local ignore_paths=$6 + + if [ -z "${paths}" -o "${paths}" == "[]" ] && \ + [ -z "${ignore_paths}" -o "${ignore_paths}" == "[]" ]; then + echo "true" + + return + fi + + if [ -z "${paths}" -o "${paths}" == "[]" ]; then + paths="[\".*\"]" + fi + + if [ -z "${ignore_paths}" ]; then + ignore_paths="[]" + fi + + set -e -o pipefail + local pull_request_changes + local changed_files + local changed_files_that_match_paths + local grep_arguments_for_paths + + pull_request_changes=$(bitbucket_pullrequest_changes "$1" "$2" "$3" "$4" "$7" "$8") + changed_files=$(echo "${pull_request_changes}" | jq -r ".[] | .path.toString") + grep_arguments_for_paths=$(get_grep_arguments_for_list "${paths}") + + set +e + changed_files_that_match_paths="$(echo "${changed_files}" | grep ${grep_arguments_for_paths})" + set -e + + local grep_arguments_for_ignore_paths + grep_arguments_for_ignore_paths=$(get_grep_arguments_for_list "${ignore_paths}") + + if [ -n "${grep_arguments_for_ignore_paths}" ]; then + set +e + changed_files_that_match_ignore_paths=$(echo "${changed_files_that_match_paths}" | grep -v ${grep_arguments_for_ignore_paths}) + set -e + else + changed_files_that_match_ignore_paths="${changed_files_that_match_paths}" + fi + + if [ -n "${changed_files_that_match_ignore_paths}" ]; then + echo "true" + else + echo "false" + fi +} + +get_grep_arguments_for_list() { + grep_arguments_for_ignore_paths="" + + for element in $(echo $1 | jq -r ".[]"); do + grep_arguments_for_ignore_paths="${grep_arguments_for_ignore_paths} -e ${element}" + done + + echo "${grep_arguments_for_ignore_paths}" +} diff --git a/assets/in b/assets/in index 869e5f5..66c609b 100755 --- a/assets/in +++ b/assets/in @@ -150,7 +150,6 @@ if [ "$prq" != "NO_SUCH_PULL_REQUEST" ] && \ branch=$(echo "$prq" | jq -r '.fromRef.displayId') fi - # expose configuration of pull request that can be used in container git config --add pullrequest.id $prq_id git config --add pullrequest.source $source_commit