Skip to content

Commit 261fa63

Browse files
committed
Workflow to automatically sync with upstream.
We plan to keep this fork alive for a significant amount of time, because it will hold an extra feature (#1) that upstream doesn't have. Automate keeping up to date with upstream to reduce our overhead. The scheme I chose for this is a little bit convoluted. There are three branches involved, but this means that the patch that we might potentially upstream is clean. Also, this scheme can't fix merge conflicts automatically, but it can find and email about them automatically, which is about as good as we can hope for.
1 parent 53bdc6d commit 261fa63

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

.github/workflows/sync-upstream.yml

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# This soft-fork of Gitea adds git-annex support (https://git-annex.branchable.com/)
2+
# git-annex is like git-lfs, which Gitea already supports, but more complicated,
3+
# except that it doesn't need an extra port open.
4+
#
5+
# We maintain three branches and N tags:
6+
# - main - a mirror of upstream's main
7+
# - git-annex - our patch (see it at: https://github.com/neuropoly/gitea/pull/1)
8+
# - release-action - release scripts + our front page
9+
# - $X-git-annex for each upstream tag $X (each created after we started tracking upstream, that is)
10+
# which = $X + release-action + git-annex
11+
#
12+
# This branch, release-action, contains:
13+
# - sync-upstream.yml (this) - try to update the branches/tags
14+
# - release.yml - build and push to https://github.com/neuropoly/gitea/releases/
15+
# and it is our default branch because cronjobs are
16+
# only allowed to run on the default branch
17+
18+
name: 'Sync Upstream'
19+
20+
on:
21+
workflow_dispatch:
22+
schedule:
23+
# 08:00 Montreal time, every day
24+
- cron: '0 13 * * *'
25+
26+
jobs:
27+
sync_upstream:
28+
name: 'Sync Upstream'
29+
runs-on: ubuntu-latest
30+
steps:
31+
32+
#- name: debug - github object
33+
# run: |
34+
# echo '${{ tojson(github) }}'
35+
36+
- name: Git Identity
37+
run: |
38+
set -ex
39+
git config --global user.name "Actions Bot"
40+
# or 41898282+github-actions[bot]@users.noreply.github.com ?
41+
git config --global user.email action@github.com
42+
43+
#- name: Git config
44+
# run: |
45+
# set -ex
46+
# # disambiguates 'git checkout' so it always uses this repo
47+
# #git config --global checkout.defaultRemote origin
48+
49+
- uses: actions/checkout@v3
50+
51+
- name: Add upstream
52+
run: |
53+
set -ex
54+
55+
PARENT=$(curl -s https://api.github.com/repos/${{github.repository}} | jq -r '.parent.clone_url // empty')
56+
git remote add upstream "$PARENT"
57+
58+
59+
- name: Fetch current origin
60+
run: |
61+
set -ex
62+
# Because actions/checkout does a lazy, shallow checkout
63+
# we need to use --shallow-since to make sure there's
64+
# enough common history that git can tell how the two
65+
# branches relate.
66+
#
67+
# We *could* do a full checkout by setting depth: 0 above,
68+
# but this is faster, especially on a large repo like this one.
69+
#
70+
# Since this runs daily, 1 week should be plenty.
71+
git fetch '--shallow-since=1 week' origin main "${{ github.ref_name }}" git-annex
72+
git fetch '--shallow-since=1 week' upstream main
73+
74+
- name: Sync main
75+
# force main to be identical to upstream
76+
# This throws away any commits to our local main
77+
# so don't commit anything to that branch.
78+
run: |
79+
set -ex
80+
git checkout -B main upstream/main
81+
82+
- name: Sync ${{ github.ref_name }}
83+
run: |
84+
set -ex
85+
git checkout "${{ github.ref_name }}"
86+
git rebase main
87+
88+
- name: Rebase git-annex, the feature branch
89+
# This is the meatiest part of this script: rebase git-annex on top of upstream.
90+
# Occasionally this step will fail -- when there's a merge conflict with upstream.
91+
# In that case, you will get an email about it, and you should run these steps
92+
# manually, and fix the merge conflicts that way.
93+
run: |
94+
set -ex
95+
git checkout git-annex
96+
git rebase main
97+
98+
- name: Construct latest version with git-annex on top
99+
run: |
100+
# for the latest tag vX.Y.Z, construct tag vX.Y.Z-git-annex.
101+
# Only construct the *latest* release to reduce the risk of conflicts
102+
# (we have to ask 'git tag' instead of the more elegant method of syncing tags
103+
# and using Github Actions' `on: push: tags: ...` because those upstream tags
104+
# *don't contain this workflow*, so there would be no way to trigger this)
105+
#
106+
# This will trigger release.yml to build and publish the latest version, too
107+
set -e
108+
109+
# git fetch is supposed to get any tags corresponding to commits it downloads,
110+
# but this behaviour is ignored when combined with --shallow, and there doesn't
111+
# seem to be any other way to get a list of tags without downloading all of them,
112+
# which effectively does --unshallow. But the GitHub API provides a shortcut, and
113+
# using this saves about 30s over downloading the unshallow repo:
114+
PARENT_API=$(curl -s https://api.github.com/repos/${{github.repository}} | jq -r '.parent.url // empty')
115+
PARENT_TAGS=$(curl -s "$PARENT_API"| jq -r '.tags_url // empty')
116+
RELEASE=$(curl -s "$PARENT_TAGS" | jq -r 'map(.name | select(test("dev") | not)) | first // empty')
117+
# https://stackoverflow.com/questions/26617862/git-shallow-fetch-of-a-new-tag
118+
git fetch --depth 1 upstream tag "$RELEASE"
119+
120+
# But if we decide to just unshallow the entire repo from the start,
121+
# then you can use this instead:
122+
#RELEASE="$(git tag -l --sort=-v:refname | egrep -v 'git-annex$' | head -n 1)"
123+
124+
if git fetch -q --depth 1 origin tag "$RELEASE"-git-annex 2>/dev/null; then
125+
echo "$RELEASE-git-annex already published :tada:"
126+
else
127+
set -x
128+
git checkout -q "$RELEASE"
129+
git cherry-pick main.."${{ github.ref_name }}" # Make sure release.yml is in the tag, so it triggers a build
130+
git cherry-pick main..git-annex
131+
git tag "$RELEASE"-git-annex
132+
133+
# If this step fails due to merge conflicts,
134+
# it's probably because the most recent merge conflict
135+
# occurred somewhere after the most recent release but
136+
# before the current upstream/main.
137+
#
138+
# You should just manually create the tag, and fix the merge conflicts.
139+
# This won't try to overwrite a pre-existing tag.
140+
fi
141+
142+
- name: Upload everything back to Github
143+
run: |
144+
git push -f --all
145+
git push -f --tags

0 commit comments

Comments
 (0)