Skip to content

Commit 1e3d615

Browse files
highemerlyclaude
andcommitted
ci: add upstream auto-rebase and GHCR build workflow
- check-upstream.yml: 6時間ごとにupstreamの新しいタグを検知し、 rebaseしてGHCRへbuild&push、GitOpsリポジトリへdispatchする - upstream-vX.Y.Z ブランチ: upstreamタグから作成(-f上書き) - actions-vX.Y.Z-YYYYMMDDHHMMSS ブランチ: rebase作業用(一意) - rebase成功後 handon-production を force update - Docker タグを X.Y.Z-YYYYMMDDHHMMSS 形式に変更 - streaming/Dockerfile の build job を追加 - build-releases.yml: mastodon/mastodon 以外では実行しないよう条件追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b7ceef5 commit 1e3d615

2 files changed

Lines changed: 236 additions & 0 deletions

File tree

.github/workflows/build-releases.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ permissions:
1111
jobs:
1212
check-latest-stable:
1313
runs-on: ubuntu-latest
14+
if: github.repository == 'mastodon/mastodon'
1415
outputs:
1516
latest: ${{ steps.check.outputs.is_latest_stable }}
1617
steps:
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
name: Check Upstream and Rebase
2+
3+
on:
4+
schedule:
5+
- cron: '0 */6 * * *' # 6時間ごと
6+
workflow_dispatch:
7+
8+
jobs:
9+
check-and-rebase:
10+
runs-on: ubuntu-latest
11+
outputs:
12+
new_tag: ${{ steps.check.outputs.new_tag }}
13+
current_tag: ${{ steps.check.outputs.current_tag }}
14+
ci_tag: ${{ steps.prepare.outputs.ci_tag }}
15+
docker_tag: ${{ steps.prepare.outputs.docker_tag }}
16+
should_build: ${{ steps.check.outputs.should_build }}
17+
rebase_success: ${{ steps.rebase.outputs.rebase_success }}
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
token: ${{ secrets.GH_PAT }}
25+
26+
- name: Check upstream for new tags
27+
id: check
28+
run: |
29+
UPSTREAM_REPO=mastodon/mastodon
30+
31+
# 自リポジトリの最新タグを取得 (actions-* や upstream-* を除外)
32+
CURRENT_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
33+
echo "Current tag: $CURRENT_TAG"
34+
35+
# バージョン番号をパース (v4.3.2 -> 4 3 2)
36+
CURRENT_CLEAN=${CURRENT_TAG#v}
37+
IFS='.' read -r CUR_MAJOR CUR_MINOR CUR_PATCH <<< "$CURRENT_CLEAN"
38+
39+
# upstreamの最新タグ一覧を取得し、semver順にソート
40+
UPSTREAM_TAGS=$(gh api repos/$UPSTREAM_REPO/tags --paginate \
41+
--jq '.[].name' \
42+
| grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' \
43+
| sort -Vr \
44+
| head -20)
45+
46+
echo "Upstream tags (sorted):"
47+
echo "$UPSTREAM_TAGS"
48+
49+
# 対象となるタグをフィルタ(現在より新しいもの)
50+
TARGET_TAG=""
51+
while IFS= read -r TAG; do
52+
CLEAN=${TAG#v}
53+
IFS='.' read -r UP_MAJOR UP_MINOR UP_PATCH <<< "$CLEAN"
54+
55+
IS_NEWER=false
56+
if [ "$UP_MAJOR" -gt "$CUR_MAJOR" ]; then
57+
IS_NEWER=true
58+
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -gt "$CUR_MINOR" ]; then
59+
IS_NEWER=true
60+
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -eq "$CUR_MINOR" ] && [ "$UP_PATCH" -gt "$CUR_PATCH" ]; then
61+
IS_NEWER=true
62+
fi
63+
64+
if [ "$IS_NEWER" = "true" ]; then
65+
TARGET_TAG=$TAG
66+
break # 最新1件のみ処理(複数あれば次回以降に処理)
67+
fi
68+
done <<< "$UPSTREAM_TAGS"
69+
70+
if [ -z "$TARGET_TAG" ]; then
71+
echo "No new upstream tag found."
72+
echo "should_build=false" >> $GITHUB_OUTPUT
73+
else
74+
echo "New upstream tag found: $TARGET_TAG"
75+
echo "new_tag=$TARGET_TAG" >> $GITHUB_OUTPUT
76+
echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT
77+
echo "should_build=true" >> $GITHUB_OUTPUT
78+
fi
79+
env:
80+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
81+
82+
- name: Prepare branch and tag names
83+
id: prepare
84+
if: steps.check.outputs.should_build == 'true'
85+
run: |
86+
TIMESTAMP=$(date "+%Y%m%d%H%M%S")
87+
NEW_TAG=${{ steps.check.outputs.new_tag }}
88+
VERSION=${NEW_TAG#v}
89+
90+
# actions-v4.5.9-YYYYMMDDHHMMSS
91+
CI_TAG="actions-${NEW_TAG}-${TIMESTAMP}"
92+
# 4.5.9-YYYYMMDDHHMMSS (Docker タグ)
93+
DOCKER_TAG="${VERSION}-${TIMESTAMP}"
94+
95+
echo "ci_tag=$CI_TAG" >> $GITHUB_OUTPUT
96+
echo "docker_tag=$DOCKER_TAG" >> $GITHUB_OUTPUT
97+
echo "CI tag: $CI_TAG"
98+
echo "Docker tag: $DOCKER_TAG"
99+
100+
- name: Add upstream remote and fetch
101+
if: steps.check.outputs.should_build == 'true'
102+
run: |
103+
git remote add upstream https://github.com/mastodon/mastodon.git || true
104+
git fetch upstream --tags
105+
106+
- name: Create upstream branch
107+
if: steps.check.outputs.should_build == 'true'
108+
run: |
109+
NEW_TAG=${{ steps.check.outputs.new_tag }}
110+
UPSTREAM_BRANCH="upstream-${NEW_TAG}"
111+
112+
# upstream-v4.5.9 ブランチをupstreamタグから作成(-f で上書き)
113+
git checkout -B "$UPSTREAM_BRANCH" "refs/tags/$NEW_TAG"
114+
git push origin "$UPSTREAM_BRANCH" --force
115+
echo "Pushed branch: $UPSTREAM_BRANCH"
116+
117+
# handon-production に戻る
118+
git checkout handon-production
119+
120+
- name: Create CI branch and rebase
121+
if: steps.check.outputs.should_build == 'true'
122+
id: rebase
123+
run: |
124+
NEW_TAG=${{ steps.check.outputs.new_tag }}
125+
CI_TAG=${{ steps.prepare.outputs.ci_tag }}
126+
UPSTREAM_BRANCH="upstream-${NEW_TAG}"
127+
128+
git config user.name "github-actions[bot]"
129+
git config user.email "github-actions[bot]@users.noreply.github.com"
130+
131+
# handon-production から CI ブランチを作成
132+
git checkout -b "$CI_TAG"
133+
134+
# upstream ブランチにrebase (build-taged-release.sh と同じ流れ)
135+
if git rebase "$UPSTREAM_BRANCH"; then
136+
echo "rebase_success=true" >> $GITHUB_OUTPUT
137+
echo "Rebase succeeded!"
138+
else
139+
echo "rebase_success=false" >> $GITHUB_OUTPUT
140+
git rebase --abort
141+
echo "Rebase failed!"
142+
fi
143+
144+
- name: Push CI branch and update handon-production
145+
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'true'
146+
run: |
147+
CI_TAG=${{ steps.prepare.outputs.ci_tag }}
148+
NEW_TAG=${{ steps.check.outputs.new_tag }}
149+
150+
# CI ブランチをpush
151+
git push origin "$CI_TAG"
152+
153+
# actions-v4.5.9-YYYYMMDDHHMMSS タグを打つ
154+
git tag "$CI_TAG"
155+
git push origin "$CI_TAG" --tags
156+
157+
# handon-production を force update
158+
git push origin "HEAD:handon-production" --force
159+
160+
- name: Create issue on rebase failure
161+
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'false'
162+
uses: actions/github-script@v7
163+
with:
164+
script: |
165+
const newTag = '${{ steps.check.outputs.new_tag }}';
166+
const currentTag = '${{ steps.check.outputs.current_tag }}';
167+
await github.rest.issues.create({
168+
owner: context.repo.owner,
169+
repo: context.repo.repo,
170+
title: `🚨 Rebase failed: upstream ${newTag}`,
171+
body: `## Rebase Conflict Detected\n\n` +
172+
`- **Current tag**: \`${currentTag}\`\n` +
173+
`- **Upstream tag**: \`${newTag}\`\n` +
174+
`- **Run**: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}\n\n` +
175+
`## 手順\n` +
176+
`\`\`\`bash\n` +
177+
`git fetch upstream\n` +
178+
`git checkout -B upstream-${newTag} refs/tags/${newTag}\n` +
179+
`git checkout handon-production\n` +
180+
`git rebase upstream-${newTag}\n` +
181+
`# conflict解消後\n` +
182+
`git push origin HEAD:handon-production --force\n` +
183+
`\`\`\`\n\n` +
184+
`解消後は workflow_dispatch で build をトリガーしてください。`,
185+
labels: ['rebase-conflict', 'upstream-update']
186+
});
187+
188+
build-and-push:
189+
needs: check-and-rebase
190+
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
191+
uses: ./.github/workflows/build-container-image.yml
192+
with:
193+
file_to_build: Dockerfile
194+
push_to_images: ghcr.io/${{ github.repository }}
195+
cache: false
196+
flavor: |
197+
latest=true
198+
tags: |
199+
type=raw,value=${{ needs.check-and-rebase.outputs.docker_tag }}
200+
secrets: inherit
201+
202+
build-and-push-streaming:
203+
needs: check-and-rebase
204+
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
205+
uses: ./.github/workflows/build-container-image.yml
206+
with:
207+
file_to_build: streaming/Dockerfile
208+
push_to_images: ghcr.io/${{ github.repository }}-streaming
209+
cache: false
210+
flavor: |
211+
latest=true
212+
tags: |
213+
type=raw,value=${{ needs.check-and-rebase.outputs.docker_tag }}
214+
secrets: inherit
215+
216+
trigger-gitops:
217+
needs:
218+
- check-and-rebase
219+
- build-and-push
220+
- build-and-push-streaming
221+
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
222+
runs-on: ubuntu-latest
223+
224+
steps:
225+
- name: Trigger GitOps update
226+
uses: peter-evans/repository-dispatch@v3
227+
with:
228+
token: ${{ secrets.GH_PAT }}
229+
repository: highemerly/k8sg1-repo
230+
event-type: mastodon-image-updated
231+
client-payload: |
232+
{
233+
"image": "ghcr.io/${{ github.repository }}",
234+
"tag": "${{ needs.check-and-rebase.outputs.docker_tag }}"
235+
}

0 commit comments

Comments
 (0)