Skip to content

Commit ee34a6f

Browse files
committed
new script to merge in upstream changes
1 parent f46d7fd commit ee34a6f

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

merge_upstream.sh

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# For a given argument that is a release version, it will be the tag. For now, want the
6+
# format of `vX.Y.Z_A`. The underscore and `A` is important to include, as that is our
7+
# patch version that is separate from the upstream patch version
8+
release_name=$1
9+
echo "release_name ${release_name}"
10+
11+
# The minor number of the version, so of the release_name above which looks like `vX.Y`,
12+
# we are peeling off the `Y` for further use
13+
expected_minor=${release_name##*.}
14+
echo "expected_minor ${expected_minor}"
15+
16+
# What our branch name will be. Upstream uses the format of `release-vX.Y` so to avoid
17+
# confusion we will pre-pend 'famedly' to that and use a `/` to namespace it. Like this:
18+
# `famedly-release/vX.Y`. We do want patch levels and hotfixes to live on the same
19+
# branch as the release major.minor
20+
release_branch_name="famedly-release/${release_name}"
21+
echo "release_branch_name ${release_branch_name}"
22+
23+
upstream_release_branch_name="release-${release_name}"
24+
echo "upstream_release_branch_name ${upstream_release_branch_name}"
25+
26+
logical_cores=$([ $(uname) = 'Darwin' ] &&
27+
sysctl -n hw.logicalcpu_max ||
28+
nproc)
29+
30+
if [ -z "${release_name}" ]; then
31+
echo "Usage: $0 <release_name>"
32+
exit 1
33+
fi
34+
35+
if [ "${release_name}" = "-h" ]; then
36+
echo "Usage: $0 <release_name>"
37+
exit 0
38+
fi
39+
40+
echo -e "\e[32m>>>> fetching origin branches\e[0m"
41+
# If the release_name that was passed already exists as a tag, this will fatal error.
42+
# Make sure it does not legitimately exist, or that you really mean to replace it before
43+
# running `git tag -d <release_name>` to remove that one single tag
44+
git fetch --tags origin
45+
46+
echo -e "\e[32m>>>> fetching upstream branches\e[0m"
47+
git fetch --tags upstream
48+
49+
echo -e "\e[32m>>>> checkout master branch\e[0m"
50+
git checkout master-test
51+
echo -e "\e[32m>>>> resetting master branch\e[0m"
52+
git reset --hard
53+
54+
echo -e "\e[32m>>>> find/checkout release branch\e[0m"
55+
# Temporarily disable error catching, as it will cause the script to halt
56+
# Normally this is not needed, but apparently our chosen branch name for famedly
57+
# releases causes fatal errors if it does not already exist. I believe it is caused by
58+
# the '/' in the branch name and how that can be a confusing reference for git to try
59+
# and sort out.
60+
# Specifically `famedly-release/vX.Y` comes across as 'fatal' instead of just
61+
# 'non-existent'. I choose to blame the '/'
62+
set +e
63+
64+
# Expect this a '0' for exists and a '1' for not-exists. Fatal is a '128'. We apply a
65+
# NOT so the condition only runs if there was an error
66+
if ! git switch --quiet "$release_branch_name"; then
67+
echo "branch did not exist, creating"
68+
# -c creates the branch at our current checkout. Which should be a clean checkout of
69+
# the master branch from a moment ago
70+
git switch -c "$release_branch_name"
71+
fi
72+
# Have to re-enable error catching in case something else breaks
73+
set -e
74+
75+
# Fetch existing tags on this branch. If this was a new branch from main, ours will be the
76+
# last tag added. If this was an existing branch we are appending to, ours will still be
77+
# the last tag added.
78+
last_tag_on_this_branch=$(git describe --tags --abbrev=0)
79+
echo "last_tag_on_this_branch $last_tag_on_this_branch"
80+
81+
# Our patch level version, everything after the `_`
82+
famedly_patch_level=${last_tag_on_this_branch#*_}
83+
echo "famedly_patch_level ${famedly_patch_level}"
84+
85+
# The major, minor and patch level, so `vX.Y.Z`
86+
long_ver=${last_tag_on_this_branch%_*}
87+
echo "long_ver ${long_ver}"
88+
89+
# Just the patch level integer, so `Z`
90+
patch_level=${long_ver##*.}
91+
echo "patch_level $patch_level"
92+
93+
# The `vX.Y`
94+
major_minor=${long_ver%.*}
95+
echo "major_minor $major_minor"
96+
97+
# and just the `Y`
98+
minor_ver=${major_minor##*.}
99+
echo "minor_ver $minor_ver"
100+
101+
102+
# First determine if the upstream branch has incremented it's patch level
103+
upstreams_last_tag=$(git ls-remote --tags upstream "$release_name"* | grep -o 'refs/tags/v[0-9]*\.[0-9]*\.[0-9]*' | sort -rV | head -n1 | cut --delimiter='/' --fields=3)
104+
echo "upstreams_last_tag $upstreams_last_tag"
105+
upstream_patch_level=${upstreams_last_tag##*.}
106+
echo "upstream_patch_level $upstream_patch_level"
107+
upstream_major_minor=${upstreams_last_tag%.*}
108+
echo "upstream_major_minor $upstream_major_minor"
109+
upstream_minor_ver=${upstream_major_minor##.*}
110+
111+
# if upstream patch level has increased, we bump ours too
112+
if [[ "$expected_minor" != "$minor_ver" ]]; then
113+
# must have been a version bump which means this is a new minor version release. In this case, it's likely that it is the same as what upstream's is
114+
expected_new_version_tag="${upstreams_last_tag}_1"
115+
echo -e "Likely new release minor version $expected_new_version_tag"
116+
117+
elif [[ "$upstream_patch_level" -gt "$patch_level" ]]; then
118+
# no minor version bump but there was a patch level version bump, increment our expected patch level
119+
expected_new_version_tag="${upstreams_last_tag}_1"
120+
echo -e "Likely new release patch version $expected_new_version_tag"
121+
122+
else
123+
# no minor and no patch level increase, this is probably just a famedly patch level increase
124+
increment_patch_level=$(( famedly_patch_level + 1))
125+
expected_new_version_tag="${upstreams_last_tag}_$increment_patch_level"
126+
echo -e "Likely new famedly release patch version $expected_new_version_tag"
127+
128+
fi
129+
130+
echo -e "\e[32m>>>> merging master into release branch\e[0m"
131+
# We let this error if there was a merge conflict that needs to be resolved. It should
132+
# be an idempotent process of just rerunning the script to continue on. After a
133+
# `git merge --continue`, of course
134+
git merge "upstream/release-${release_name}" -m "Famedly ${release_name}"
135+
136+
137+
# Retrieve the git log entries themselves and format them to fit well into the
138+
# markdown format. If there were none, we can skip this whole next section
139+
git_log_output=$(git log $(git describe --tags --abbrev=0)..master-test --pretty=format:'- %s %C(bold blue)(%an)%Creset\' --no-merges --no-decorate | sort -u -f -k2)
140+
141+
if [[ ! -z $git_log_output ]]; then
142+
echo -e "\e[32m>>>> Listing changes from main branch since last release\e[0m"
143+
# Find out how many lines down in CHANGES.md that the previous '# Synapse' entry
144+
# was. This gives us the line number needed to run the insertion.
145+
changelog_line_number=$(grep -n "# Synapse" CHANGES.md | awk 'NR==2 {print $1}' FS=":")
146+
147+
# Shell expansion is stupid when it comes to escaping things. This is a hack to get the
148+
# new line character into a string that sed will actually interpret that does not
149+
# interfere with already appended '\' from the git log output. Used at the end to give
150+
# us the extra line inside the markdown.
151+
NL=$'\n'
152+
# Construct the sed command. This is a little messy. sed requires that new lines are a
153+
# '\' and not a normal ansi '\n'(and it will insert that for us). We need a basic header
154+
# for the entry and an additional new line at the end(the markdown itself does not care
155+
# but this makes it easier to find when opening the file directly).
156+
sed_command="${changelog_line_number} i\### Famedly additions for ${expected_new_version_tag}\n\n"
157+
sed_command+="${git_log_output}${NL}"
158+
159+
# That should do it. The changes from our repo that occurred since the last upstream
160+
# merge(specifically that do not include said merge) should be inserted just above that
161+
# previous upstream merge(and just underneath the merge we are in the middle of).
162+
# Nice little bonus, they are printed in the console for us to see as the script runs
163+
sed -i "${sed_command}" CHANGES.md
164+
165+
# Amend the last commit(which should be the merge commit itself) to incorporate changes
166+
# from the changelog just produced
167+
git add CHANGES.md
168+
git commit --amend --no-edit --allow-empty
169+
fi
170+
#echo "Check any changes or adjustments that need to be made, then"
171+
#read -n 1 -s -r -p "Press any key to continue merge..."
172+
173+
read -n 1 -p "Press 'p' to push branch to Github, or any other key to skip\n" input_key
174+
if [[ $input_key == "p" ]]; then
175+
echo -e "\e[32m>>>> pushing release branch\e[0m"
176+
git push --force -u origin "${release_branch_name}"
177+
fi
178+
179+
read -n 1 -p "Press 't' to run linting and tests, or any other key to skip\n" input_key
180+
if [[ $input_key == "t" ]]; then
181+
echo -e "\e[32m>>>> running lint and tests...\e[0m"
182+
# Make sure there are no weirdities around poetry. Until the deprecation migration
183+
# occurs, expect orange things to read here.
184+
#poetry check
185+
#poetry install --extras all --no-interaction
186+
#poetry run ./scripts-dev/lint.sh
187+
#poetry run trial -j"${logical_cores}" tests
188+
echo -e "\e[32m>>>> Success!\e[0m"
189+
fi
190+
191+
read -n 1 -p "Press 't' to create tag and push to Github, or any other key to skip\n" input_key
192+
if [[ $input_key == "t" ]]; then
193+
echo -e "\e[32m>>>> updating release tag\e[0m"
194+
git tag -f -s -m "${expected_new_version_tag}" "${expected_new_version_tag}"
195+
# git push -f origin "${expected_new_version_tag}"
196+
fi
197+
echo -e "\e[32m>>>> Finished!\e[0m"

0 commit comments

Comments
 (0)