Repository navigation
Expand file tree
/
Copy pathautomerge.sh
More file actions
executable file
·100 lines (89 loc) · 5.04 KB
/
Copy pathautomerge.sh
File metadata and controls
executable file
·100 lines (89 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/bin/bash -e
# Merge the pull request whose checks just passed on HEAD_SHA, if it's one merged automatically: of Dependabot, or an
# update of PHP of the docker image
# (tests/update_docker.sh, on the docker-php branch of the app of the autobuild). Run by automerge.yml. Only if it's
# still at that commit (not pushed again since), and all of its checks passed (the release label and version too).
#
# Needs GH_TOKEN, able to merge pull requests that update workflows (not the token of a job), HEAD_SHA, and ACTOR, who
# triggered the checks: Dependabot or the app of the autobuild.
set -o pipefail
repository=${GH_REPO:-danog/MadelineProto}
export GH_REPO="$repository"
# Without the versions of PHP and the RELEASE constant.
normalize_versions()
{
sed -E "s/php-[0-9]+\.[0-9]+\.[0-9]+\b/php-VERSION/g; s/^( public const RELEASE = )'[0-9]+\.[0-9]+\.[0-9]+';\$/\1'VERSION';/"
}
pr=$(gh pr list --state open --json number,headRefOid,headRefName,author --jq ".[] | select(.headRefOid == \"$HEAD_SHA\") | select(.author.login == \"app/dependabot\" or (.author.login == \"app/madelineproto-autobuild\" and .headRefName == \"docker-php\")) | .number")
if [ -z "$pr" ]; then
echo "No open pull request to merge automatically at $HEAD_SHA (pushed again or closed since, or not one of those)"
exit 0
fi
git fetch -q origin "+refs/heads/v8:refs/remotes/origin/v8" "$HEAD_SHA"
base=$(git merge-base origin/v8 "$HEAD_SHA")
# The token of the app of the autobuild is in jobs that run the code of dependencies, and can push to any branch: a
# pull request of Dependabot is only merged if its checks ran on a push of Dependabot, and all of its commits are
# Dependabot's. Its release is bumped once merged: see tests/dependabot_release.sh.
if [ "$(gh pr view "$pr" --json author --jq .author.login)" == app/dependabot ]; then
if [ "$ACTOR" != "dependabot[bot]" ]; then
echo "Not merging #$pr: its checks ran on a push of $ACTOR"
exit 0
fi
others=$(git log --format=%ae "$base..$HEAD_SHA" | grep -vFx "49699333+dependabot[bot]@users.noreply.github.com" | sort -u | paste -sd ' ' || true)
if [ -n "$others" ]; then
echo "Not merging #$pr: it has commits of others ($others)"
exit 0
fi
fi
# An update of PHP is merged with the token of an admin, but the token of the app is also in the jobs of the autobuild
# that run the code of the dependencies: only if the app made all of its commits, and it only changes what
# tests/update_docker.sh changes, the versions of PHP of the Dockerfile and the RELEASE constant (the files are the
# same as in the main branch without them).
if [ "$(gh pr view "$pr" --json headRefName --jq .headRefName)" == docker-php ]; then
others=$(gh pr view "$pr" --json commits --jq '[.commits[].authors[].login | select(. != "madelineproto-autobuild[bot]")] | unique | join(", ")')
if [ -n "$others" ]; then
echo "Not merging #$pr: an update of PHP with commits of others ($others)"
exit 0
fi
if [ "$ACTOR" != "madelineproto-autobuild[bot]" ]; then
echo "Not merging #$pr: its checks ran on a push of $ACTOR"
exit 0
fi
# Fails before the loop, rather than in its input, if the diff fails.
git diff -z --no-renames --name-only "$base" "$HEAD_SHA" > /dev/null
while IFS= read -r -d '' file; do
case "$file" in
tests/dockerfiles/Dockerfile|src/API.php) ;;
*)
echo "Not merging #$pr: an update of PHP that changes $file"
exit 0
;;
esac
old=$(git show "$base:$file" | normalize_versions)
new=$(git show "$HEAD_SHA:$file" | normalize_versions)
if [ "$old" != "$new" ]; then
echo "Not merging #$pr: an update of PHP that changes more than the versions of $file"
exit 0
fi
done < <(git diff -z --no-renames --name-only "$base" "$HEAD_SHA")
fi
pending=$(gh pr checks "$pr" --json name,bucket --jq '[.[] | select(.bucket != "pass" and .bucket != "skipping") | .name] | join(", ")')
if [ -n "$pending" ]; then
echo "Not merging #$pr: some of its checks didn't pass ($pending)"
exit 0
fi
# GitHub refuses to merge with GH_TOKEN (without the workflow scope) a pull request whose merge commit writes a
# workflow file anew: one that the main branch changed too since the pull request was opened (Dependabot updates the
# same action in several pull requests). Dependabot rebases it instead, whose checks then merge it.
mapfile -d '' workflows < <(git diff -z --no-renames --name-only "$base" "$HEAD_SHA" -- .github/workflows)
if [ ${#workflows[@]} -ne 0 ] && [ -n "$(git diff --no-renames --name-only "$base" origin/v8 -- "${workflows[@]}")" ]; then
if [ "$(gh pr view "$pr" --json author --jq .author.login)" == app/dependabot ]; then
gh pr comment "$pr" --body "@dependabot rebase"
echo "Asked Dependabot to rebase #$pr: v8 changed its workflows too"
exit 0
fi
echo "Not merging #$pr: v8 changed its workflows too, it must be rebased"
exit 0
fi
gh pr merge "$pr" --merge --match-head-commit "$HEAD_SHA"
echo "Merged #$pr"