Change:
The 1.45.1 release is primarily being made because of the accidental omission of a rustfmt backport from the 1.45 beta branch after it landed in 1.44.1. The release team discussed this today, and we'd like to implement some automation to try and prevent this in the future at relatively low cost. The plan is to only allow landing commits in beta / stable branches if (or similar, but that seems like the right thing) indicates they've already landed in the preceding branches (beta and master for stable, just master for beta). We will also want an explicit set of commits that are just allowed. This will slightly increase the work needed during beta backports, as this list will need updating if there are any merge conflicts at least -- but since backports are rare and usually rollups, this shouldn't be much of a problem hopefully. We would be interested in seeing someone implement this functionality! <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim

Discussion:
- name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh if: success() && !env.SKIP_JOB <ins> - name: ensure backported commits are in upstream branches run: src/ci/scripts/verify-backported-commits.sh if: success() && !env.SKIP_JOB </ins> - name: run the build run: src/ci/scripts/run-build-from-ci.sh env:

run: src/ci/scripts/verify-line-endings.sh <<: *step <ins> - name: ensure backported commits are in upstream branches run: src/ci/scripts/verify-backported-commits.sh <<: *step </ins> - name: run the build run: src/ci/scripts/run-build-from-ci.sh env:

<ins> #!/bin/bash # Ensure commits in beta are in master & commits in stable are in beta + master. set -euo pipefail IFS=$'nt' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # We don't care about commits that predate this automation check, so we pass a # `<limit>` argument to `git cherry`. BETA_LIMIT="53fd98ca776cb875bc9e5514f56b52eb74f9e7a9" STABLE_LIMIT="a178d0322ce20e33eac124758e837cbd80a6f633" verify_backported_commits_main() { ci_base_branch=$(ciBaseBranch) if [[ "$ci_base_branch" != "beta" && "$ci_base_branch" != "stable" ]]; then echo 'Skipping. This is only run when merging to the beta or stable branches.' exit 0 fi echo 'git: unshallowing the repository so we can check commits' git fetch  --no-tags  --no-recurse-submodules  --progress  --prune  --unshallow if [[ $ci_base_branch == "beta" ]]; then verify_cherries master "$BETA_LIMIT"  || exit 1 elif [[ $ci_base_branch == "stable" ]]; then (verify_cherries master "$STABLE_LIMIT"  & verify_cherries beta "$STABLE_LIMIT")  || exit 1 fi } # Verify all commits in `HEAD` are backports of a commit in <upstream>. See # https://git-scm.com/docs/git-cherry for an explanation of the arguments. # # $1 = <upstream> # $2 = <limit> verify_cherries() { # commits that lack a `backport-of` comment. local no_backports=() # commits with an incorrect `backport-of` comment. local bad_backports=() commits=$(git cherry "origin/$1" HEAD "$2") if [[ -z "$commits" ]]; then echo "All commits in `HEAD` are present in `$1`" return 0 fi commits=$(echo "$commits" | grep '^+' | cut -c 3-) while read sha; do # Check each commit in <current>..<upstream> backport_sha=$(get_backport "$sha") if [[ "$backport_sha" == "nothing" ]]; then echo "✓ `$sha` backports nothing" continue fi if [[ -z "$backport_sha" ]]; then no_backports+=("$sha") continue fi if ! is_in_master "$backport_sha"; then bad_backports+=("$sha") continue fi echo "✓ `$sha` backports `$backport_sha`" done <<< "$commits" failure=0 if [ ${#no_backports[@]} -ne 0 ]; then echo 'Error: Could not find backports for all commits.' echo echo 'All commits in `HEAD` are required to have a corresponding upstream commit.' echo 'It looks like the following commits:' echo for commit in "${no_backports[@]}"; do echo "    $commit" done echo echo "do not match any commits in `$1`. If this was intended, add the text" echo '`backport-of: <SHA of a commit already in master>`' echo 'somewhere in the message of each of these commits.' echo failure=1 fi if [ ${#bad_backports[@]} -ne 0 ]; then echo 'Error: Found incorrectly marked commits.' echo echo 'The following commits:' echo for commit in "${bad_backports[@]}"; do echo "    $commit" done echo echo 'have commit messages marked `backport-of: <SHA>`, but the SHA is not in' echo '`master`.' echo failure=1 fi return $failure } # Get the backport of a commit. It echoes one of: # # 1. A SHA of the backported commit # 2. The string "nothing" # 3. An empty string # # $1 = <sha> get_backport() { # This regex is: # # ^.* - throw away any extra starting characters # backport-of: - prefix # s? - optional space # () - capture group # [a-f0-9]+|nothing - a SHA or the text 'nothing' # .* - throw away any extra ending characters # 1 - replace it with the first match # {s//1/p;q} - print the first occurrence and quit # git show -s --format=%B "$1"  | sed -n '/^.*backport-of:s?([a-f0-9]+|nothing).*/{s//1/p;q}' } # Check if a commit is in master. # # $1 = <sha> is_in_master() { git merge-base --is-ancestor "$1" origin/master 2> /dev/null } verify_backported_commits_main </ins>

<ins> #!/bin/bash set -euo pipefail IFS=$'nt' print_error() { echo "Error: `$1` is not a valid commit. To debug, run:" echo echo "    git rev-parse --verify $1" echo } full_sha() { git rev-parse  --verify  --quiet  "$1^{object}" || print_error $1 } commit_message_with_backport_note() { message=$(git log --format=%B -n 1 $1) echo $message | awk "NR==1{print; print "n(backport-of: $1)"} NR!=1" } cherry_pick_commit() { sha=$(full_sha $1) git cherry-pick $sha > /dev/null git commit  --amend  --file <(commit_message_with_backport_note $sha) } for arg ; do cherry_pick_commit $arg done </ins>