pokeapi/Resources/scripts/updater.sh

273 lines
10 KiB
Bash
Raw Normal View History

2020-04-23 19:48:55 +00:00
#!/bin/bash
2020-04-25 20:50:08 +00:00
# Executed when the master branch of PokeAPI/pokeapi gets updated
# Runs in CircleCI
# Generates new data using the latest changes of PokeAPI/pokeapi in order to open a Pull Request towards PokeAPI/api-data
2020-04-23 19:48:55 +00:00
set -o pipefail
org='PokeAPI'
data_repo='api-data'
2020-04-25 19:15:41 +00:00
engine_repo='pokeapi'
branch_name='staging'
2020-04-25 19:15:41 +00:00
username='pokeapi-machine-user'
email='pokeapi.co@gmail.com'
2020-06-01 20:01:56 +00:00
staging_environment_url='https://staging.pokeapi.co/api/v2/'
production_environment_url='https://pokeapi.co/api/v2/'
data_repo_url='https://github.com/PokeAPI/api-data'
engine_circleci_status_url='https://app.circleci.com/pipelines/github/PokeAPI/pokeapi'
deploy_circleci_status_url='https://app.circleci.com/pipelines/github/PokeAPI/deploy'
2020-04-25 19:15:41 +00:00
2020-04-30 21:53:46 +00:00
# Exit the script notifying the user about its success
cleanexit() {
2020-04-25 19:15:41 +00:00
echo "Exiting"
echo "$2"
2020-04-30 12:51:52 +00:00
if [ "$1" -gt "0" ]; then
notify_engine_pr "end_failed"
else
notify_engine_pr "end_success"
fi
2020-04-25 20:50:08 +00:00
exit $1
2020-04-25 19:15:41 +00:00
}
2020-04-23 19:48:55 +00:00
# Create and use a personal folder
2020-04-23 19:48:55 +00:00
prepare() {
2020-04-24 20:49:53 +00:00
mkdir -p ./repositories
2020-04-25 19:15:41 +00:00
cd repositories || cleanexit 1 "Failed to cd"
}
# GraphQL query to retrieve a PR's number based on a commit hash
2020-05-31 21:28:32 +00:00
pr_associated_with_sha_graphql_query_content() {
cat <<EOF
query associatedPRs {
repository(name: \"pokeapi\", owner: \"PokeAPI\") {
commit: object(expression: \"$1\") {
... on Commit {
associatedPullRequests(first: 1) {
edges {
node {
number
}
}
}
}
}
}
}
EOF
}
# Get the PR's numer associated with the last commit
get_invokator_pr_number_from_graphql() {
last_commit_sha="$(git rev-parse HEAD)"
2020-05-31 21:28:32 +00:00
query="$(pr_associated_with_sha_graphql_query_content "$last_commit_sha")"
query=$(echo $query) # echo strips all IFS characters (newline, space)
pr_number=$(curl -s -H "Content-Type: application/json" -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X POST --data "{\"query\": \"$query\"}" "https://api.github.com/graphql" | jq ".data.repository.commit.associatedPullRequests.edges[0].node.number" )
echo "$pr_number"
}
# Check and return the number of the Pull Request that started this job
2020-04-25 19:15:41 +00:00
get_invokator_pr_number() {
commit_msg_regex="Merge pull request #([0-9]+) from PokeAPI/(.*)"
last_commit_message=$(git log --oneline --format=%B -n 1 HEAD | head -n 1)
invokator_pr_number_from_graphql="$(get_invokator_pr_number_from_graphql)"
if ! [ -z "$CIRCLE_PULL_REQUEST" ]; then
2020-04-25 19:15:41 +00:00
echo "${CIRCLE_PULL_REQUEST##*/}"
elif [ "$invokator_pr_number_from_graphql" != 'null' ]; then
echo "$invokator_pr_number_from_graphql"
elif [[ $last_commit_message =~ $commit_msg_regex ]]; then
echo "${BASH_REMATCH[1]}"
else
echo 'null'
2020-04-25 19:15:41 +00:00
fi
2020-04-23 19:48:55 +00:00
}
# Clone the repository containing the static JSON files
2020-04-23 19:48:55 +00:00
clone() {
2020-04-25 19:15:41 +00:00
git clone "https://github.com/${org}/${data_repo}.git" "$data_repo"
2020-04-23 19:48:55 +00:00
}
# Configure git to use the supplied user when committing
2020-04-23 19:48:55 +00:00
configure_git() {
2020-04-25 19:15:41 +00:00
git config --global user.name "$username"
git config --global user.email "$email"
}
2020-04-30 12:51:52 +00:00
pr_input_updater_start() {
2020-04-25 19:15:41 +00:00
cat <<EOF
{
"body": "A [PokeAPI/api-data](${data_repo_url}) refresh has started. In 45 minutes the staging branch of [PokeAPI/api-data](${data_repo_url}/tree/staging) will be pushed with the new generated data. <br><br> The staging branch will be deployed in our [staging environment]($staging_environment_url) and you will be able to review the entire API. <br><br> A Pull Request ([master](${data_repo_url}/tree/master)<-[staging](${data_repo_url}/tree/staging)) will be also created at [PokeAPI/api-data](${data_repo_url}/pulls) and assigned to the PokeAPI Core team to be reviewed. If approved and merged new data will soon be available worldwide at [pokeapi.co]($production_environment_url)"
2020-04-25 19:15:41 +00:00
}
EOF
}
2020-04-30 12:51:52 +00:00
pr_input_updater_end_success() {
cat <<EOF
{
"body": "The updater script has finished its job and has now opened a Pull Request towards [PokeAPI/api-data](${data_repo_url}/pulls) with the updated data. <br><br> You can see the Pull Request deployed at our [staging environment]($staging_environment_url) when [CircleCI deploy]($deploy_circleci_status_url) will be finished (_check the started time of the last build_)"
2020-04-30 12:51:52 +00:00
}
EOF
}
pr_input_updater_end_failed() {
cat <<EOF
{
"body": "The updater script couldn't finish its job. Please check [CircleCI's builds]($engine_circleci_status_url) and [logs](${CIRCLE_BUILD_URL})."
2020-04-30 12:51:52 +00:00
}
EOF
}
2020-04-30 21:53:46 +00:00
# If the job was started by a Pull Request, add a comment to notify the users
2020-04-30 12:51:52 +00:00
notify_engine_pr() {
2020-04-30 17:42:56 +00:00
if [[ $1 == "start" || $1 == "end_failed" || $1 == "end_success" ]]; then
engine_repo_pr_number=$(get_invokator_pr_number)
if [ "$engine_repo_pr_number" != "null" ]; then
curl -f -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X POST --data "$(pr_input_updater_$1)" "https://api.github.com/repos/$org/$engine_repo/issues/$engine_repo_pr_number/comments"
2020-04-30 12:51:52 +00:00
fi
2020-04-25 19:15:41 +00:00
fi
2020-04-23 19:48:55 +00:00
}
# Run the updater script (https://github.com/PokeAPI/api-data/blob/master/updater/cmd.bash) which will generate the new pokeapi data and push it to the api-data repository under a new branch
2020-04-24 20:49:53 +00:00
run_updater() {
cd "$data_repo/updater" || cleanexit 1 "Failed to cd"
2020-05-13 14:01:54 +00:00
# Wait to be sure PokeAPI/pokeapi's master branch has been updated on Github with the lastest merged PR content
2020-04-25 19:15:41 +00:00
sleep 10
# Build the updater image
2020-04-24 20:49:53 +00:00
docker build -t pokeapi-updater .
2020-04-25 19:15:41 +00:00
if [ $? -ne 0 ]; then
cleanexit 1 "Failed to build the pokeapi-updater image"
fi
# Run the updater
docker run --privileged -e COMMIT_EMAIL="$email" -e COMMIT_NAME="$username" -e BRANCH_NAME="$branch_name" -e REPO_POKEAPI="https://github.com/$org/$engine_repo.git" -e REPO_DATA="https://$MACHINE_USER_GITHUB_API_TOKEN@github.com/$org/$data_repo.git" pokeapi-updater
2020-04-25 19:15:41 +00:00
if [ $? -ne 0 ]; then
2020-04-25 20:50:08 +00:00
cleanexit 1 "Failed to run the pokeapi-updater container"
2020-04-25 19:15:41 +00:00
fi
cd .. || cleanexit 1 "Failed to cd"
2020-04-23 19:48:55 +00:00
}
# Check if the updater script has pushed the data to a new branch
2020-04-25 19:15:41 +00:00
check_remote_branch() {
# Wait for Github to update origin/${branch_name}
sleep 10
2020-04-25 19:15:41 +00:00
curl -f -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X GET "https://api.github.com/repos/$org/$data_repo/branches/$1"
if [ $? -ne 0 ]; then
cleanexit 1 "The updater script failed to push the new data"
2020-04-25 19:15:41 +00:00
fi
}
2020-04-24 20:49:53 +00:00
# Generate the input content that will be sent to Github's API to open a refresh-data PR towards PokeAPI/api-data
pr_input_content_with_pr_number() {
2020-04-23 19:48:55 +00:00
cat <<EOF
{
"title": "API data update from \`${org}/${engine_repo}#${1}\`",
"body": "Incoming data generated by [${org}/${engine_repo}](https://github.com/${org}/${engine_repo})'s CircleCI worker since Pull Request [#${1}](https://github.com/${org}/${engine_repo}/pull/${1}) was merged into the \`master\` branch. <br><br> The new data was generated using a copy of [${org}/${engine_repo}](https://github.com/${org}/${engine_repo}/commits/master) repository when the \`HEAD\` was pointing to \`${CIRCLE_SHA1}\`. <br><br> This Pull Request should have been deployed in our [staging environment]($staging_environment_url), check [here]($deploy_circleci_status_url) for the lastest build timestamp and status code.",
2020-04-23 19:48:55 +00:00
"head": "$branch_name",
"base": "master",
"assignees": [
"Naramsim"
],
"labels": [
"api-data-update"
]
}
EOF
}
# Copy of pr_input_content_with_pr_number
# run when the script cannot detect the merged PR number that started the CircleCI job
pr_input_content_without_pr_number() {
cat <<EOF
{
"title": "API data update from \`${org}/${engine_repo}\`",
"body": "Incoming data generated by [${org}/${engine_repo}](https://github.com/${org}/${engine_repo})'s CircleCI worker. <br><br> The new data was generated using a copy of [${org}/${engine_repo}](https://github.com/${org}/${engine_repo}/commits/master) repository when the \`HEAD\` was pointing to \`${CIRCLE_SHA1}\`. <br><br> This Pull Request should have been deployed in our [staging environment]($staging_environment_url), check [here]($deploy_circleci_status_url) for the lastest build timestamp and status code.",
"head": "$branch_name",
"base": "master",
"assignees": [
"Naramsim"
],
"labels": [
"api-data-update"
]
}
EOF
}
# Create a Pull Request to merge the branch recently pushed by the updater with the master branch
create_pr() {
engine_repo_pr_number=$(get_invokator_pr_number)
if [ "$engine_repo_pr_number" != "null" ]; then
data_repo_pr_number=$(curl -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X POST --data "$(pr_input_content_with_pr_number "$engine_repo_pr_number")" "https://api.github.com/repos/$org/$data_repo/pulls" | jq '.number')
else
data_repo_pr_number=$(curl -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X POST --data "$(pr_input_content_without_pr_number)" "https://api.github.com/repos/$org/$data_repo/pulls" | jq '.number')
fi
2020-04-30 12:51:52 +00:00
if [[ "$data_repo_pr_number" = "null" ]]; then
cleanexit 1 "Couldn't create the Pull Request"
fi
2020-04-30 12:51:52 +00:00
echo "$data_repo_pr_number"
}
pr_input_assignees_and_labels() {
2020-04-23 20:31:08 +00:00
cat <<EOF
{
"assignees": [
"Naramsim"
],
"labels": [
"api-data-update"
]
}
EOF
}
# Assign the PR to Naramsim and add a label
customize_pr() {
# Wait for Github to open the PR
sleep 10
2020-04-30 12:51:52 +00:00
data_repo_pr_number=$1
curl -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X PATCH --data "$(pr_input_assignees_and_labels)" "https://api.github.com/repos/$org/$data_repo/issues/$data_repo_pr_number"
if [ $? -ne 0 ]; then
echo "Couldn't add Assignees and Labes to the Pull Request"
fi
}
2020-04-25 20:50:08 +00:00
pr_input_reviewers() {
2020-04-23 19:48:55 +00:00
cat <<EOF
{
"reviewers": [
"Naramsim"
2020-04-25 20:50:08 +00:00
],
"team_reviewers": [
"core-team"
2020-04-23 19:48:55 +00:00
]
}
EOF
}
# Request the Core team to review the Pull Request
add_reviewers_to_pr() {
2020-04-30 12:51:52 +00:00
data_repo_pr_number=$1
curl -H "Authorization: token $MACHINE_USER_GITHUB_API_TOKEN" -X POST --data "$(pr_input_reviewers)" "https://api.github.com/repos/$org/$data_repo/pulls/$data_repo_pr_number/requested_reviewers"
2020-04-24 19:18:26 +00:00
if [ $? -ne 0 ]; then
echo "Couldn't add Reviewers to the Pull Request"
fi
2020-04-23 19:48:55 +00:00
}
prepare
configure_git
2020-04-30 21:53:46 +00:00
clone
2020-04-30 12:51:52 +00:00
notify_engine_pr "start"
2020-04-24 20:49:53 +00:00
run_updater
2020-04-25 19:15:41 +00:00
check_remote_branch "$branch_name"
if [ "$CIRCLE_BRANCH" = 'master' ]; then
sleep 300 # 5 minutes, the time it takes for CircleCI's api-data script to generate the data and for CircleCI's deploy script to deploy it to the staging environment
check_remote_branch "$branch_name"
data_repo_pr_number=$(create_pr)
customize_pr "$data_repo_pr_number"
add_reviewers_to_pr "$data_repo_pr_number"
fi
2020-04-25 20:50:08 +00:00
cleanexit 0 'Done'