| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | #!/usr/bin/env bash
 | 
					
						
							|  |  |  | # vim: ts=2 et | 
					
						
							| 
									
										
										
										
											2019-04-17 20:41:06 +08:00
										 |  |  | # Setting -x is absolutely forbidden as it could leak the GitHub token. | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | set -uo pipefail | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # GITHUB_TOKEN required scope: repo.repo_public | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | git_mail="prometheus-team@googlegroups.com" | 
					
						
							|  |  |  | git_user="prombot" | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  | branch="repo_sync" | 
					
						
							|  |  |  | commit_msg="Update common Prometheus files" | 
					
						
							|  |  |  | pr_title="Synchronize common files from prometheus/prometheus" | 
					
						
							|  |  |  | pr_msg="Propagating changes from prometheus/prometheus default branch." | 
					
						
							| 
									
										
										
										
											2020-04-10 21:34:34 +08:00
										 |  |  | orgs="prometheus prometheus-community" | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  | color_red='\e[31m' | 
					
						
							|  |  |  | color_green='\e[32m' | 
					
						
							| 
									
										
										
										
											2021-06-01 18:45:31 +08:00
										 |  |  | color_yellow='\e[33m' | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  | color_none='\e[0m' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | echo_red() { | 
					
						
							| 
									
										
										
										
											2021-06-01 18:45:31 +08:00
										 |  |  |   echo -e "${color_red}$@${color_none}" 1>&2 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | echo_green() { | 
					
						
							| 
									
										
										
										
											2021-06-01 18:45:31 +08:00
										 |  |  |   echo -e "${color_green}$@${color_none}" 1>&2 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | echo_yellow() { | 
					
						
							|  |  |  |   echo -e "${color_yellow}$@${color_none}" 1>&2 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | GITHUB_TOKEN="${GITHUB_TOKEN:-}" | 
					
						
							|  |  |  | if [ -z "${GITHUB_TOKEN}" ]; then | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  |   echo_red 'GitHub token (GITHUB_TOKEN) not set. Terminating.' | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |   exit 1 | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  | # List of files that should be synced. | 
					
						
							| 
									
										
										
										
											2021-06-25 19:46:48 +08:00
										 |  |  | SYNC_FILES="CODE_OF_CONDUCT.md LICENSE Makefile.common SECURITY.md .yamllint" | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | # Go to the root of the repo | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | cd "$(git rev-parse --show-cdup)" || exit 1 | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  | source_dir="$(pwd)" | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | tmp_dir="$(mktemp -d)" | 
					
						
							|  |  |  | trap 'rm -rf "${tmp_dir}"' EXIT | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  | prometheus_orb_version="$(yq eval '.orbs.prometheus' .circleci/config.yml)" | 
					
						
							|  |  |  | if [[ -z "${prometheus_orb_version}" ]]; then | 
					
						
							|  |  |  |   echo_red '"ERROR: Unable to get CircleCI orb version' | 
					
						
							|  |  |  |   exit 1 | 
					
						
							|  |  |  | fi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Internal functions | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  | github_api() { | 
					
						
							|  |  |  |   local url | 
					
						
							|  |  |  |   url="https://api.github.com/${1}" | 
					
						
							|  |  |  |   shift 1 | 
					
						
							|  |  |  |   curl --retry 5 --silent --fail -u "${git_user}:${GITHUB_TOKEN}" "${url}" "$@" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | get_default_branch() { | 
					
						
							|  |  |  |   github_api "repos/${1}" 2> /dev/null | | 
					
						
							|  |  |  |     jq -r .default_branch | 
					
						
							| 
									
										
										
										
											2021-02-23 03:19:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | fetch_repos() { | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  |   github_api "orgs/${1}/repos?type=public&per_page=100" 2> /dev/null | | 
					
						
							|  |  |  |     jq -r '.[] | select( .archived == false and .fork == false and .name != "prometheus" ) | .name' | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | push_branch() { | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   local git_url | 
					
						
							|  |  |  |   git_url="https://${git_user}:${GITHUB_TOKEN}@github.com/${1}" | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |   # stdout and stderr are redirected to /dev/null otherwise git-push could leak | 
					
						
							|  |  |  |   # the token in the logs. | 
					
						
							| 
									
										
										
										
											2019-09-12 21:25:26 +08:00
										 |  |  |   # Delete the remote branch in case it was merged but not deleted. | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   git push --quiet "${git_url}" ":${branch}" 1>/dev/null 2>&1 | 
					
						
							|  |  |  |   git push --quiet "${git_url}" --set-upstream "${branch}" 1>/dev/null 2>&1 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | post_pull_request() { | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   local repo="$1" | 
					
						
							|  |  |  |   local default_branch="$2" | 
					
						
							|  |  |  |   local post_json | 
					
						
							|  |  |  |   post_json="$(printf '{"title":"%s","base":"%s","head":"%s","body":"%s"}' "${pr_title}" "${default_branch}" "${branch}" "${pr_msg}")" | 
					
						
							|  |  |  |   echo "Posting PR to ${default_branch} on ${repo}" | 
					
						
							|  |  |  |   github_api "repos/${repo}/pulls" --data "${post_json}" --show-error | | 
					
						
							|  |  |  |     jq -r '"PR URL " + .html_url' | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 18:35:04 +08:00
										 |  |  | check_license() { | 
					
						
							|  |  |  |   # Check to see if the input is an Apache license of some kind | 
					
						
							|  |  |  |   echo "$1" | grep --quiet --no-messages --ignore-case 'Apache License' | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  | check_circleci_orb() { | 
					
						
							|  |  |  |   local org_repo | 
					
						
							|  |  |  |   local default_branch | 
					
						
							|  |  |  |   org_repo="$1" | 
					
						
							|  |  |  |   default_branch="$2" | 
					
						
							|  |  |  |   local ci_config_url="https://raw.githubusercontent.com/${org_repo}/${default_branch}/.circleci/config.yml" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   orb_version="$(curl -sL --fail "${ci_config_url}" | yq eval '.orbs.prometheus' -)" | 
					
						
							|  |  |  |   if [[ -z "${orb_version}" ]]; then | 
					
						
							| 
									
										
										
										
											2021-06-01 18:45:31 +08:00
										 |  |  |     echo_yellow "WARNING: Failed to fetch CirleCI orb version from '${org_repo}'" | 
					
						
							|  |  |  |     return 0 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  |   fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 15:05:59 +08:00
										 |  |  |   if [[ "${orb_version}" != "null" && "${orb_version}" != "${prometheus_orb_version}" ]]; then | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  |     echo "CircleCI-orb" | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | process_repo() { | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   local org_repo | 
					
						
							|  |  |  |   local default_branch | 
					
						
							|  |  |  |   org_repo="$1" | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  |   echo_green "Analyzing '${org_repo}'" | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   default_branch="$(get_default_branch "${org_repo}")" | 
					
						
							| 
									
										
										
										
											2021-02-24 06:23:51 +08:00
										 |  |  |   if [[ -z "${default_branch}" ]]; then | 
					
						
							| 
									
										
										
										
											2021-02-23 03:19:08 +08:00
										 |  |  |     echo "Can't get the default branch." | 
					
						
							|  |  |  |     return | 
					
						
							|  |  |  |   fi | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   echo "Default branch: ${default_branch}" | 
					
						
							| 
									
										
										
										
											2021-02-23 03:19:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 18:35:04 +08:00
										 |  |  |   local needs_update=() | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |   for source_file in ${SYNC_FILES}; do | 
					
						
							| 
									
										
										
										
											2020-06-21 08:18:21 +08:00
										 |  |  |     source_checksum="$(sha256sum "${source_dir}/${source_file}" | cut -d' ' -f1)" | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  |     target_file="$(curl -sL --fail "https://raw.githubusercontent.com/${org_repo}/${default_branch}/${source_file}")" | 
					
						
							| 
									
										
										
										
											2020-06-22 18:35:04 +08:00
										 |  |  |     if [[ "${source_file}" == 'LICENSE' ]] && ! check_license "${target_file}" ; then | 
					
						
							|  |  |  |       echo "LICENSE in ${org_repo} is not apache, skipping." | 
					
						
							|  |  |  |       continue | 
					
						
							|  |  |  |     fi | 
					
						
							| 
									
										
										
										
											2020-06-21 08:18:21 +08:00
										 |  |  |     if [[ -z "${target_file}" ]]; then | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |       echo "${source_file} doesn't exist in ${org_repo}" | 
					
						
							| 
									
										
										
										
											2021-01-17 03:07:55 +08:00
										 |  |  |       case "${source_file}" in | 
					
						
							|  |  |  |         CODE_OF_CONDUCT.md | SECURITY.md) | 
					
						
							|  |  |  |           echo "${source_file} missing in ${org_repo}, force updating." | 
					
						
							|  |  |  |           needs_update+=("${source_file}") | 
					
						
							|  |  |  |           ;; | 
					
						
							|  |  |  |       esac | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |       continue | 
					
						
							|  |  |  |     fi | 
					
						
							|  |  |  |     target_checksum="$(echo "${target_file}" | sha256sum | cut -d' ' -f1)" | 
					
						
							|  |  |  |     if [ "${source_checksum}" == "${target_checksum}" ]; then | 
					
						
							|  |  |  |       echo "${source_file} is already in sync." | 
					
						
							|  |  |  |       continue | 
					
						
							|  |  |  |     fi | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |     echo "${source_file} needs updating." | 
					
						
							| 
									
										
										
										
											2020-06-22 18:35:04 +08:00
										 |  |  |     needs_update+=("${source_file}") | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |   done | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  |   local circleci | 
					
						
							|  |  |  |   circleci="$(check_circleci_orb "${org_repo}" "${default_branch}")" | 
					
						
							|  |  |  |   if [[ -n "${circleci}" ]]; then | 
					
						
							|  |  |  |     echo "${circleci} needs updating." | 
					
						
							|  |  |  |     needs_update+=("${circleci}") | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 18:35:04 +08:00
										 |  |  |   if [[ "${#needs_update[@]}" -eq 0 ]] ; then | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |     echo "No files need sync." | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |     return | 
					
						
							|  |  |  |   fi | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |   # Clone target repo to temporary directory and checkout to new branch | 
					
						
							|  |  |  |   git clone --quiet "https://github.com/${org_repo}.git" "${tmp_dir}/${org_repo}" | 
					
						
							|  |  |  |   cd "${tmp_dir}/${org_repo}" || return 1 | 
					
						
							|  |  |  |   git checkout -b "${branch}" || return 1 | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |   # Update the files in target repo by one from prometheus/prometheus. | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   for source_file in "${needs_update[@]}"; do | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  |     case "${source_file}" in | 
					
						
							|  |  |  |       CircleCI-orb) yq eval -i ".orbs.prometheus = \"${prometheus_orb_version}\"" .circleci/config.yml ;; | 
					
						
							|  |  |  |       *) cp -f "${source_dir}/${source_file}" "./${source_file}" ;; | 
					
						
							|  |  |  |     esac | 
					
						
							| 
									
										
										
										
											2020-06-17 22:51:32 +08:00
										 |  |  |   done | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |   if [[ -n "$(git status --porcelain)" ]]; then | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |     git config user.email "${git_mail}" | 
					
						
							|  |  |  |     git config user.name "${git_user}" | 
					
						
							|  |  |  |     git add . | 
					
						
							|  |  |  |     git commit -s -m "${commit_msg}" | 
					
						
							|  |  |  |     if push_branch "${org_repo}"; then | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |       if ! post_pull_request "${org_repo}" "${default_branch}"; then | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  |       fi | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       echo "Pushing ${branch} to ${org_repo} failed" | 
					
						
							|  |  |  |       return 1 | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |     fi | 
					
						
							|  |  |  |   fi | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 21:33:22 +08:00
										 |  |  | ## main | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  | for org in ${orgs}; do | 
					
						
							|  |  |  |   mkdir -p "${tmp_dir}/${org}" | 
					
						
							|  |  |  |   # Iterate over all repositories in ${org}. The GitHub API can return 100 items | 
					
						
							|  |  |  |   # at most but it should be enough for us as there are less than 40 repositories | 
					
						
							|  |  |  |   # currently. | 
					
						
							|  |  |  |   fetch_repos "${org}" | while read -r repo; do | 
					
						
							| 
									
										
										
										
											2019-09-12 21:25:26 +08:00
										 |  |  |     # Check if a PR is already opened for the branch. | 
					
						
							| 
									
										
										
										
											2021-03-16 06:59:27 +08:00
										 |  |  |     fetch_uri="repos/${org}/${repo}/pulls?state=open&head=${org}:${branch}" | 
					
						
							| 
									
										
										
										
											2021-06-27 06:29:56 +08:00
										 |  |  |     prLink="$(github_api "${fetch_uri}" --show-error | jq -r '.[0].html_url')" | 
					
						
							|  |  |  |     if [[ "${prLink}" != "null" ]]; then | 
					
						
							|  |  |  |       echo_green "Pull request already opened for branch '${branch}': ${prLink}" | 
					
						
							|  |  |  |       echo "Either close it or merge it before running this script again!" | 
					
						
							|  |  |  |       continue | 
					
						
							|  |  |  |     fi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ! process_repo "${org}/${repo}"; then | 
					
						
							| 
									
										
										
										
											2021-03-25 16:52:32 +08:00
										 |  |  |       echo_red "Failed to process '${org}/${repo}'" | 
					
						
							| 
									
										
										
										
											2020-04-10 21:59:16 +08:00
										 |  |  |       exit 1 | 
					
						
							|  |  |  |     fi | 
					
						
							|  |  |  |   done | 
					
						
							| 
									
										
										
										
											2019-04-11 20:31:04 +08:00
										 |  |  | done |