Skip to content

Instantly share code, notes, and snippets.

@22phuber
Last active February 10, 2023 15:14
Show Gist options
  • Save 22phuber/195e6929324e0490eacb3e039f25fad1 to your computer and use it in GitHub Desktop.
Save 22phuber/195e6929324e0490eacb3e039f25fad1 to your computer and use it in GitHub Desktop.
Automating Pull Requests on Bitbucket with new Strapi Github releases, Blog Post: https://supportblog.ch/scheduled-bitbucket-pipeline-automatically-create-a-pull-request-on-new-strapi-github-release/
#!/usr/bin/env bash
# StoneAge IT
# Author: Patrick Huber (22phuber@gmail.com)
#
# Description: Automate Your PR Process with Bitbucket and Strapi
#
# This script streamlines the process of creating a pull request in a Bitbucket repository when a
# new release is available in the Strapi Github repository. Simply run the script within the
# Bitbucket pipeline, such as through a daily scheduled pipeline, to stay up-to-date with
# the latest releases from Strapi (strapi.io).
#
# Access Token and Repository Variable:
#
# This script requires certain setup steps before it can be executed successfully. To start,
# an access token with the "pullrequest:write" permission must be generated in the repository's
# "Security" settings under "Access Tokens". Additionally, the git config user.email must be
# set to a specific value in the format of "<USEREMAILVALUE>@bots.bitbucket.org". Lastly, a
# repository variable named "BITBUCKET_API_TOKEN_STRAPI_RELEASE_BOT" must be created and
# assigned the generated access token.
#
# This script uses non-standard binaries:
# - jq (cli JSON processor)
# - curl
#
[[ "${SCRIPT_DEBUG}" = "true" ]] && set -x
set -e
set -o pipefail
scriptFolderPath=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
# CHECK access token ENV variable BITBUCKET_API_TOKEN_STRAPI_RELEASE_BOT
if [[ "${BITBUCKET_API_TOKEN_STRAPI_RELEASE_BOT}empty" == "empty" ]]; then
# shellcheck disable=SC2016
printf 'Bitbucket API access token `BITBUCKET_API_TOKEN_STRAPI_RELEASE_BOT` is not set.\n'
exit 1
fi
# VARIABLES
# Location of the `package.json`` file from strapi containing the current version
declare -r strapiPackageJsonFileName="package.json"
declare -r strapiPackageJsonFile="backend/${strapiPackageJsonFileName}" # REPLACE the location of your package.json file
# Bitbucket user.email from access token creation
declare -r bitbucketGitConfigUserEmail="<bitbucketGitConfigUserEmail>" # REPLACE: <bitbucketGitConfigUserEmail>
# Set variables for the GitHub repository and Bitbucket repository
declare -r githubRepoApi="https://api.github.com/repos/strapi/strapi"
declare -r bitbucketRepoApi="https://api.bitbucket.org/2.0/repositories/<workspace>/<repo_slug>" # REPLACE: <workspace> and <repo_slug>
declare -r sourceBranch="develop" # Source branch to checkout (you may REPLACE this value as well)
declare -r targetBranch="${sourceBranch}" # Target branch for the pull request (you may REPLACE this value as well)
# Fetch new release on GitHub repository
strapiLatestRelease=$(
set -o pipefail
curl --silent "${githubRepoApi}/releases/latest" | jq -r '.tag_name'
)
strapiLatestRelease="${strapiLatestRelease/v/}" # Removes `v` if any (e.g. `v4.6.0` => `4.6.0`)
declare -r strapiLatestRelease
# Get current release from Strapi `package.json`
strapiCurrentRelease=$(jq -r '.dependencies."@strapi/strapi"' "../${strapiPackageJsonFile}") # REPLACE the path to your package.json file
declare -r strapiCurrentRelease
printf 'Releases found:
strapiLatestRelease: %s
strapiCurrentRelease: %s
\n' "${strapiLatestRelease}" "${strapiCurrentRelease}"
# branch name for pull request
branchName="bot/strapi-update-to-${strapiLatestRelease}" # You may REPLACE this value as well
# Pull request POST payload for Bitbucket API request
payloadBitbucketPullRequest=$(
cat <<EOFPayloadBitbucketPullRequest
{
"title": "Update Strapi to version ${strapiLatestRelease}",
"description": "This pull request has been automatically created by the \`$(basename "${0}")\` script using a pipeline schedule",
"close_source_branch": true,
"source": {
"branch": {
"name": "${branchName}"
}
},
"destination": {
"branch": {
"name": "${targetBranch}"
}
}
}
EOFPayloadBitbucketPullRequest
)
# MAIN
# If a new release is found
if [[ "$strapiLatestRelease" != "$strapiCurrentRelease" ]]; then
cd "${scriptFolderPath}/.." # Change directory to root of repo (you may REPLACE or even REMOVE this cd command as well)
# Git: Set git user.email
git config user.email "${bitbucketGitConfigUserEmail}@bots.bitbucket.org"
# Git: Check for existing update branch
if gitLsRemoteResponse=$(git ls-remote --exit-code --head origin "${branchName}"); then
printf 'Strapi update branch with name "%s" already exists.\n%s\n' "${branchName}" "${gitLsRemoteResponse}"
exit 0
fi
printf "New Strapi release found: %s\n" "${strapiLatestRelease}"
# Git: Checkout source branch
git checkout "${sourceBranch}" || {
printf 'Failed to checkout source branch "%s"\n' "${sourceBranch}"
exit 1
}
# Git: Create a new branch for the release
git checkout -b "${branchName}"
# Determine & handle package.json updates
updatedStrapiPackageJsonFile=$(STRAPI_LATEST_RELEASE="${strapiLatestRelease}" jq '.dependencies |= with_entries(if .key | startswith("@strapi/") then .value = env.STRAPI_LATEST_RELEASE else . end)' "${strapiPackageJsonFile}")
# Also update the "app" version (optional, can be removed)
updatedStrapiPackageJsonFile=$(
set -o pipefail
printf '%s' "${updatedStrapiPackageJsonFile}" | jq --arg version "${strapiLatestRelease}" '.version = $version'
)
# Override the original package.json with the updated content
printf '%s' "${updatedStrapiPackageJsonFile}" >"${strapiPackageJsonFile}"
# Git: Add the changes and commit them
git add .
git commit -m "Update Strapi to version ${strapiLatestRelease}"
# Git: Push the changes to the Bitbucket repository
git push origin "${branchName}"
# Curl: Create a pull request (Bitbucket API) for the release branch
if curlResponse=$(curl \
--header "Authorization: Bearer ${BITBUCKET_API_TOKEN_STRAPI_RELEASE_BOT}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--request POST \
--data "${payloadBitbucketPullRequest}" \
"${bitbucketRepoApi}/pullrequests"); then
printf "Pull request created.\n"
else
printf "Failed to create pull request.\n"
fi
# Print reponse from curl
printf '\nCurl response:\n'
if printf '%s' "${curlResponse}" | jq . >/dev/null 2>&1; then
# Contains a JSON reponse
printf '%s\n' "${curlResponse}" | jq .
else
printf '%s\n' "${curlResponse}"
fi
else
printf "No new Strapi release found.\n"
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment