feat: add git cherry

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
pull/825/head
Xinwei Xiong(cubxxw-openim) 2 years ago
parent ec0b9c54e1
commit b34f667a5f
No known key found for this signature in database
GPG Key ID: 1BAD6F395338EFDE

@ -23,6 +23,75 @@ Our collaboration strategy with GitHub necessitates maintenance of multiple `rel
Ensuring this strategy's success extends beyond just documentation; it hinges on well-engineered solutions and automation tools, like Makefile, powerful CI/CD processes, and even Prow. Ensuring this strategy's success extends beyond just documentation; it hinges on well-engineered solutions and automation tools, like Makefile, powerful CI/CD processes, and even Prow.
## Prerequisites
- [Contributor License Agreement](https://github.com/openim-sigs/cla) is considered implicit for all code within cherry pick pull requests, **unless there is a large conflict**.
- A pull request merged against the `main` branch.
- The release branch exists (example: [`release-1.18`](https://github.com/OpenIMSDK/Open-IM-Server/tree/release-v3.1))
- The normal git and GitHub configured shell environment for pushing to your openim-server `origin` fork on GitHub and making a pull request against a configured remote `upstream` that tracks `https://github.com/OpenIMSDK/Open-IM-Server.git`, including `GITHUB_USER`.
- Have GitHub CLI (`gh`) installed following [installation instructions](https://github.com/cli/cli#installation).
- A github personal access token which has permissions "repo" and "read:org". Permissions are required for [gh auth login](https://cli.github.com/manual/gh_auth_login) and not used for anything unrelated to cherry-pick creation process (creating a branch and initiating PR).
## What Kind of PRs are Good for Cherry Picks
Compared to the normal main branch's merge volume across time, the release branches see one or two orders of magnitude less PRs. This is because there is an order or two of magnitude higher scrutiny. Again, the emphasis is on critical bug fixes, e.g.,
- Loss of data
- Memory corruption
- Panic, crash, hang
- Security
A bugfix for a functional issue (not a data loss or security issue) that only affects an alpha feature does not qualify as a critical bug fix.
If you are proposing a cherry pick and it is not a clear and obvious critical bug fix, please reconsider. If upon reflection you wish to continue, bolster your case by supplementing your PR with e.g.,
- A GitHub issue detailing the problem
- Scope of the change
- Risks of adding a change
- Risks of associated regression
- Testing performed, test cases added
- Key stakeholder SIG reviewers/approvers attesting to their confidence in the change being a required backport
If the change is in cloud provider-specific platform code (which is in the process of being moved out of core openim-server), describe the customer impact, how the issue escaped initial testing, remediation taken to prevent similar future escapes, and why the change cannot be carried in your downstream fork of the openim-server project branches.
It is critical that our full community is actively engaged on enhancements in the project. If a released feature was not enabled on a particular provider's platform, this is a community miss that needs to be resolved in the `main` branch for subsequent releases. Such enabling will not be backported to the patch release branches.
## Initiate a Cherry Pick
### Before you begin
- Plan to initiate a cherry-pick against *every* supported release branch. If you decide to skip some release branch, explain your decision in a comment to the PR being cherry-picked.
- Initiate cherry-picks in order, from newest to oldest supported release branches. For example, if 3.1 is the newest supported release branch, then, before cherry-picking to 2.25, make sure the cherry-pick PR already exists for in 2.26 and 3.1. This helps to prevent regressions as a result of an upgrade to the next release.
### Steps
- Run the [cherry pick script](https://github.com/OpenIMSDK/Open-IM-Server/tree/main/scripts/cherry_pick_pull.sh)
This example applies a main branch PR #98765 to the remote branch `upstream/release-v3.1`:
```
scripts/cherry_pick_pull.sh upstream/release-v3.1 98765
```
- Be aware the cherry pick script assumes you have a git remote called `upstream` that points at the openim-server github org.
Please see our [recommended Git workflow](https://github.com/openim-server/community/blob/main/contributors/guide/github-workflow.md#workflow).
- You will need to run the cherry pick script separately for each patch release you want to cherry pick to. Cherry picks should be applied to all [active](https://github.com/openim-server/website/blob/main/content/en/releases/patch-releases.md#detailed-release-history-for-active-branches) release branches where the fix is applicable.
- If `GITHUB_TOKEN` is not set you will be asked for your github password: provide the github [personal access token](https://github.com/settings/tokens) rather than your actual github password. If you can securely set the environment variable `GITHUB_TOKEN` to your personal access token then you can avoid an interactive prompt. Refer [mislav/hub#2655 (comment)](https://github.com/mislav/hub/issues/2655#issuecomment-735836048)
- Your cherry pick PR will immediately get the `do-not-merge/cherry-pick-not-approved` label.
[Normal rules apply for code merge](https://github.com/openim-server/community/blob/main/contributors/devel/sig-release/release.md#tldr), with some additional caveats outlined in the next section of this document.
## Cherry Pick Review
As with any other PR, code OWNERS review (`/lgtm`) and approve (`/approve`) on cherry pick PRs as they deem appropriate.
The same release note requirements apply as normal pull requests, except the release note stanza will auto-populate from the main branch pull request from which the cherry pick originated.
## Using git cherry-pick ## Using git cherry-pick
`git cherry-pick` applies specified commits from one branch to another. `git cherry-pick` applies specified commits from one branch to another.

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Usage Instructions: https://git.k8s.io/community/contributors/devel/sig-release/cherry-picks.md # Usage Instructions: https://github.com/OpenIMSDK/Open-IM-Server/tree/main/docs/contrib/git_cherry-pick.md
# Checkout a PR from GitHub. (Yes, this is sitting in a Git tree. How # Checkout a PR from GitHub. (Yes, this is sitting in a Git tree. How
# meta.) Assumes you care about pulls from remote "upstream" and # meta.) Assumes you care about pulls from remote "upstream" and
@ -11,6 +11,9 @@ set -o errexit
set -o nounset set -o nounset
set -o pipefail set -o pipefail
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
REPO_ROOT="$(git rev-parse --show-toplevel)" REPO_ROOT="$(git rev-parse --show-toplevel)"
declare -r REPO_ROOT declare -r REPO_ROOT
cd "${REPO_ROOT}" cd "${REPO_ROOT}"
@ -26,13 +29,11 @@ MAIN_REPO_ORG=${MAIN_REPO_ORG:-$(git remote get-url "$UPSTREAM_REMOTE" | awk '{g
MAIN_REPO_NAME=${MAIN_REPO_NAME:-$(git remote get-url "$UPSTREAM_REMOTE" | awk '{gsub(/http[s]:\/\/|git@/,"")}1' | awk -F'[@:./]' 'NR==1{print $4}')} MAIN_REPO_NAME=${MAIN_REPO_NAME:-$(git remote get-url "$UPSTREAM_REMOTE" | awk '{gsub(/http[s]:\/\/|git@/,"")}1' | awk -F'[@:./]' 'NR==1{print $4}')}
if [[ -z ${GITHUB_USER:-} ]]; then if [[ -z ${GITHUB_USER:-} ]]; then
echo "Please export GITHUB_USER=<your-user> (or GH organization, if that's where your fork lives)" openim::log::error_exit "Please export GITHUB_USER=<your-user> (or GH organization, if that's where your fork lives)"
exit 1
fi fi
if ! command -v gh > /dev/null; then if ! command -v gh > /dev/null; then
echo "Can't find 'gh' tool in PATH, please install from https://github.com/cli/cli" openim::log::error_exit "Can't find 'gh' tool in PATH, please install from https://github.com/cli/cli"
exit 1
fi fi
if [[ "$#" -lt 2 ]]; then if [[ "$#" -lt 2 ]]; then
@ -40,8 +41,8 @@ if [[ "$#" -lt 2 ]]; then
echo echo
echo " Checks out <remote branch> and handles the cherry-pick of <pr> (possibly multiple) for you." echo " Checks out <remote branch> and handles the cherry-pick of <pr> (possibly multiple) for you."
echo " Examples:" echo " Examples:"
echo " $0 upstream/release-3.14 12345 # Cherry-picks PR 12345 onto upstream/release-3.14 and proposes that as a PR." echo " $0 upstream/release-v3.1 12345 # Cherry-picks PR 12345 onto upstream/release-v3.1 and proposes that as a PR."
echo " $0 upstream/release-3.14 12345 56789 # Cherry-picks PR 12345, then 56789 and proposes the combination as a single PR." echo " $0 upstream/release-v3.1 12345 56789 # Cherry-picks PR 12345, then 56789 and proposes the combination as a single PR."
echo echo
echo " Set the DRY_RUN environment var to skip git push and creating PR." echo " Set the DRY_RUN environment var to skip git push and creating PR."
echo " This is useful for creating patches to a release branch without making a PR." echo " This is useful for creating patches to a release branch without making a PR."
@ -53,7 +54,7 @@ if [[ "$#" -lt 2 ]]; then
echo " Set UPSTREAM_REMOTE (default: upstream) and FORK_REMOTE (default: origin)" echo " Set UPSTREAM_REMOTE (default: upstream) and FORK_REMOTE (default: origin)"
echo " to override the default remote names to what you have locally." echo " to override the default remote names to what you have locally."
echo echo
echo " For merge process info, see https://git.k8s.io/community/contributors/devel/sig-release/cherry-picks.md" echo " For merge process info, see https://github.com/OpenIMSDK/Open-IM-Server/tree/main/docs/contrib/git_cherry-pick.md"
exit 2 exit 2
fi fi
@ -61,13 +62,11 @@ fi
gh auth status gh auth status
if git_status=$(git status --porcelain --untracked=no 2>/dev/null) && [[ -n "${git_status}" ]]; then if git_status=$(git status --porcelain --untracked=no 2>/dev/null) && [[ -n "${git_status}" ]]; then
echo "!!! Dirty tree. Clean up and try again." openim::log::error_exit "!!! Dirty tree. Clean up and try again."
exit 1
fi fi
if [[ -e "${REBASEMAGIC}" ]]; then if [[ -e "${REBASEMAGIC}" ]]; then
echo "!!! 'git rebase' or 'git am' in progress. Clean up and try again." openim::log::error_exit "!!! 'git rebase' or 'git am' in progress. Clean up and try again."
exit 1
fi fi
declare -r BRANCH="$1" declare -r BRANCH="$1"
@ -80,12 +79,12 @@ declare -r PULLDASH
PULLSUBJ=$(join " " "${PULLS[@]/#/#}") # Generates something like "#12345 #56789" PULLSUBJ=$(join " " "${PULLS[@]/#/#}") # Generates something like "#12345 #56789"
declare -r PULLSUBJ declare -r PULLSUBJ
echo "+++ Updating remotes..." openim::log::status "Updating remotes..."
git remote update "${UPSTREAM_REMOTE}" "${FORK_REMOTE}" git remote update "${UPSTREAM_REMOTE}" "${FORK_REMOTE}"
if ! git log -n1 --format=%H "${BRANCH}" >/dev/null 2>&1; then if ! git log -n1 --format=%H "${BRANCH}" >/dev/null 2>&1; then
echo "!!! '${BRANCH}' not found. The second argument should be something like ${UPSTREAM_REMOTE}/release-0.21." openim::log::error " '${BRANCH}' not found. The second argument should be something like ${UPSTREAM_REMOTE}/release-0.21."
echo " (In particular, it needs to be a valid, existing remote branch that I can 'git checkout'.)" openim::log::error " (In particular, it needs to be a valid, existing remote branch that I can 'git checkout'.)"
exit 1 exit 1
fi fi
@ -95,21 +94,21 @@ NEWBRANCH="$(echo "${NEWBRANCHREQ}-${BRANCH}" | sed 's/\//-/g')"
declare -r NEWBRANCH declare -r NEWBRANCH
NEWBRANCHUNIQ="${NEWBRANCH}-$(date +%s)" NEWBRANCHUNIQ="${NEWBRANCH}-$(date +%s)"
declare -r NEWBRANCHUNIQ declare -r NEWBRANCHUNIQ
echo "+++ Creating local branch ${NEWBRANCHUNIQ}" openim::log::info "+++ Creating local branch ${NEWBRANCHUNIQ}"
cleanbranch="" cleanbranch=""
gitamcleanup=false gitamcleanup=false
function return_to_kansas { function return_to_kansas {
if [[ "${gitamcleanup}" == "true" ]]; then if [[ "${gitamcleanup}" == "true" ]]; then
echo echo
echo "+++ Aborting in-progress git am." openim::log::status "Aborting in-progress git am."
git am --abort >/dev/null 2>&1 || true git am --abort >/dev/null 2>&1 || true
fi fi
# return to the starting branch and delete the PR text file # return to the starting branch and delete the PR text file
if [[ -z "${DRY_RUN}" ]]; then if [[ -z "${DRY_RUN}" ]]; then
echo echo
echo "+++ Returning you to the ${STARTINGBRANCH} branch and cleaning up." openim::log::status "Returning you to the ${STARTINGBRANCH} branch and cleaning up."
git checkout -f "${STARTINGBRANCH}" >/dev/null 2>&1 || true git checkout -f "${STARTINGBRANCH}" >/dev/null 2>&1 || true
if [[ -n "${cleanbranch}" ]]; then if [[ -n "${cleanbranch}" ]]; then
git branch -D "${cleanbranch}" >/dev/null 2>&1 || true git branch -D "${cleanbranch}" >/dev/null 2>&1 || true
@ -123,7 +122,7 @@ function make-a-pr() {
local rel local rel
rel="$(basename "${BRANCH}")" rel="$(basename "${BRANCH}")"
echo echo
echo "+++ Creating a pull request on GitHub at ${GITHUB_USER}:${NEWBRANCH}" openim::log::status "Creating a pull request on GitHub at ${GITHUB_USER}:${NEWBRANCH}"
local numandtitle local numandtitle
numandtitle=$(printf '%s\n' "${SUBJECTS[@]}") numandtitle=$(printf '%s\n' "${SUBJECTS[@]}")
@ -132,7 +131,7 @@ Cherry pick of ${PULLSUBJ} on ${rel}.
${numandtitle} ${numandtitle}
For details on the cherry pick process, see the [cherry pick requests](https://git.k8s.io/community/contributors/devel/sig-release/cherry-picks.md) page. For details on the cherry pick process, see the [cherry pick requests](https://github.com/OpenIMSDK/Open-IM-Server/tree/main/docs/contrib/git_cherry-pick.md) page.
\`\`\`release-note \`\`\`release-note
@ -148,11 +147,11 @@ cleanbranch="${NEWBRANCHUNIQ}"
gitamcleanup=true gitamcleanup=true
for pull in "${PULLS[@]}"; do for pull in "${PULLS[@]}"; do
echo "+++ Downloading patch to /tmp/${pull}.patch (in case you need to do this again)" openim::log::status "Downloading patch to /tmp/${pull}.patch (in case you need to do this again)"
curl -o "/tmp/${pull}.patch" -sSL "https://github.com/${MAIN_REPO_ORG}/${MAIN_REPO_NAME}/pull/${pull}.patch" curl -o "/tmp/${pull}.patch" -sSL "https://github.com/${MAIN_REPO_ORG}/${MAIN_REPO_NAME}/pull/${pull}.patch"
echo echo
echo "+++ About to attempt cherry pick of PR. To reattempt:" openim::log::status "About to attempt cherry pick of PR. To reattempt:"
echo " $ git am -3 /tmp/${pull}.patch" echo " $ git am -3 /tmp/${pull}.patch"
echo echo
git am -3 "/tmp/${pull}.patch" || { git am -3 "/tmp/${pull}.patch" || {
@ -161,11 +160,11 @@ for pull in "${PULLS[@]}"; do
|| [[ -e "${REBASEMAGIC}" ]]; do || [[ -e "${REBASEMAGIC}" ]]; do
conflicts=true # <-- We should have detected conflicts once conflicts=true # <-- We should have detected conflicts once
echo echo
echo "+++ Conflicts detected:" openim::log::status "Conflicts detected:"
echo echo
(git status --porcelain | grep ^U) || echo "!!! None. Did you git am --continue?" (git status --porcelain | grep ^U) || echo "!!! None. Did you git am --continue?"
echo echo
echo "+++ Please resolve the conflicts in another window (and remember to 'git add / git am --continue')" openim::log::status "Please resolve the conflicts in another window (and remember to 'git add / git am --continue')"
read -p "+++ Proceed (anything other than 'y' aborts the cherry-pick)? [y/n] " -r read -p "+++ Proceed (anything other than 'y' aborts the cherry-pick)? [y/n] " -r
echo echo
if ! [[ "${REPLY}" =~ ^[yY]$ ]]; then if ! [[ "${REPLY}" =~ ^[yY]$ ]]; then
@ -193,15 +192,15 @@ gitamcleanup=false
if [[ -n "${REGENERATE_DOCS}" ]]; then if [[ -n "${REGENERATE_DOCS}" ]]; then
echo echo
echo "Regenerating docs..." echo "Regenerating docs..."
if ! hack/generate-docs.sh; then if ! scripts/generate-docs.sh; then
echo echo
echo "hack/generate-docs.sh FAILED to complete." echo "scripts/gendoc.sh FAILED to complete."
exit 1 exit 1
fi fi
fi fi
if [[ -n "${DRY_RUN}" ]]; then if [[ -n "${DRY_RUN}" ]]; then
echo "!!! Skipping git push and PR creation because you set DRY_RUN." openim::log::error "!!! Skipping git push and PR creation because you set DRY_RUN."
echo "To return to the branch you were in when you invoked this script:" echo "To return to the branch you were in when you invoked this script:"
echo echo
echo " git checkout ${STARTINGBRANCH}" echo " git checkout ${STARTINGBRANCH}"
@ -216,7 +215,7 @@ if git remote -v | grep ^"${FORK_REMOTE}" | grep "${MAIN_REPO_ORG}/${MAIN_REPO_N
echo "!!! You have ${FORK_REMOTE} configured as your ${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git" echo "!!! You have ${FORK_REMOTE} configured as your ${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git"
echo "This isn't normal. Leaving you with push instructions:" echo "This isn't normal. Leaving you with push instructions:"
echo echo
echo "+++ First manually push the branch this script created:" openim::log::status "First manually push the branch this script created:"
echo echo
echo " git push REMOTE ${NEWBRANCHUNIQ}:${NEWBRANCH}" echo " git push REMOTE ${NEWBRANCHUNIQ}:${NEWBRANCH}"
echo echo
@ -229,7 +228,7 @@ if git remote -v | grep ^"${FORK_REMOTE}" | grep "${MAIN_REPO_ORG}/${MAIN_REPO_N
fi fi
echo echo
echo "+++ I'm about to do the following to push to GitHub (and I'm assuming ${FORK_REMOTE} is your personal fork):" openim::log::status "I'm about to do the following to push to GitHub (and I'm assuming ${FORK_REMOTE} is your personal fork):"
echo echo
echo " git push ${FORK_REMOTE} ${NEWBRANCHUNIQ}:${NEWBRANCH}" echo " git push ${FORK_REMOTE} ${NEWBRANCHUNIQ}:${NEWBRANCH}"
echo echo

Loading…
Cancel
Save