Skip to content

Commit 2d7c854

Browse files
highemerlyclaude
andcommitted
ci: add upstream auto-rebase and GHCR build workflow
- check-upstream.yml: 6時間ごとにupstreamの新しいタグを検知し、 rebaseしてGHCRへbuild&push、GitOpsリポジトリへdispatchする - build-releases.yml: mastodon/mastodon 以外では実行しないよう条件追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b7ceef5 commit 2d7c854

2 files changed

Lines changed: 178 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: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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+
should_build: ${{ steps.check.outputs.should_build }}
15+
rebase_success: ${{ steps.rebase.outputs.rebase_success }}
16+
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
token: ${{ secrets.GH_PAT }}
23+
24+
- name: Check upstream for new tags
25+
id: check
26+
run: |
27+
UPSTREAM_REPO=mastodon/mastodon
28+
29+
# 自リポジトリの最新タグを取得
30+
CURRENT_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
31+
echo "Current tag: $CURRENT_TAG"
32+
33+
# バージョン番号をパース (v4.3.2 -> 4 3 2)
34+
CURRENT_CLEAN=${CURRENT_TAG#v}
35+
IFS='.' read -r CUR_MAJOR CUR_MINOR CUR_PATCH <<< "$CURRENT_CLEAN"
36+
37+
# upstreamの最新タグ一覧を取得し、semver順にソート
38+
UPSTREAM_TAGS=$(gh api repos/$UPSTREAM_REPO/tags --paginate \
39+
--jq '.[].name' \
40+
| grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' \
41+
| sort -Vr \
42+
| head -20)
43+
44+
echo "Upstream tags (sorted):"
45+
echo "$UPSTREAM_TAGS"
46+
47+
# 対象となるタグをフィルタ(現在より新しいもの)
48+
TARGET_TAG=""
49+
while IFS= read -r TAG; do
50+
CLEAN=${TAG#v}
51+
IFS='.' read -r UP_MAJOR UP_MINOR UP_PATCH <<< "$CLEAN"
52+
53+
IS_NEWER=false
54+
if [ "$UP_MAJOR" -gt "$CUR_MAJOR" ]; then
55+
IS_NEWER=true
56+
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -gt "$CUR_MINOR" ]; then
57+
IS_NEWER=true
58+
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -eq "$CUR_MINOR" ] && [ "$UP_PATCH" -gt "$CUR_PATCH" ]; then
59+
IS_NEWER=true
60+
fi
61+
62+
if [ "$IS_NEWER" = "true" ]; then
63+
TARGET_TAG=$TAG
64+
break # 最新1件のみ処理(複数あれば次回以降に処理)
65+
fi
66+
done <<< "$UPSTREAM_TAGS"
67+
68+
if [ -z "$TARGET_TAG" ]; then
69+
echo "No new upstream tag found."
70+
echo "should_build=false" >> $GITHUB_OUTPUT
71+
else
72+
echo "New upstream tag found: $TARGET_TAG"
73+
echo "new_tag=$TARGET_TAG" >> $GITHUB_OUTPUT
74+
echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT
75+
echo "should_build=true" >> $GITHUB_OUTPUT
76+
fi
77+
env:
78+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79+
80+
- name: Add upstream remote
81+
if: steps.check.outputs.should_build == 'true'
82+
run: |
83+
git remote add upstream https://github.com/mastodon/mastodon.git || true
84+
git fetch upstream --tags
85+
86+
- name: Rebase onto upstream tag
87+
if: steps.check.outputs.should_build == 'true'
88+
id: rebase
89+
run: |
90+
NEW_TAG=${{ steps.check.outputs.new_tag }}
91+
92+
git config user.name "github-actions[bot]"
93+
git config user.email "github-actions[bot]@users.noreply.github.com"
94+
95+
if git rebase upstream/$NEW_TAG; then
96+
echo "rebase_success=true" >> $GITHUB_OUTPUT
97+
echo "Rebase succeeded!"
98+
else
99+
echo "rebase_success=false" >> $GITHUB_OUTPUT
100+
git rebase --abort
101+
echo "Rebase failed!"
102+
fi
103+
104+
- name: Push rebased branch
105+
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'true'
106+
run: |
107+
git push origin HEAD --force-with-lease
108+
109+
- name: Tag the new release
110+
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'true'
111+
run: |
112+
NEW_TAG=${{ steps.check.outputs.new_tag }}
113+
git tag "$NEW_TAG"
114+
git push origin "$NEW_TAG"
115+
116+
- name: Create issue on rebase failure
117+
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'false'
118+
uses: actions/github-script@v7
119+
with:
120+
script: |
121+
const newTag = '${{ steps.check.outputs.new_tag }}';
122+
const currentTag = '${{ steps.check.outputs.current_tag }}';
123+
await github.rest.issues.create({
124+
owner: context.repo.owner,
125+
repo: context.repo.repo,
126+
title: `🚨 Rebase failed: upstream ${newTag}`,
127+
body: `## Rebase Conflict Detected\n\n` +
128+
`- **Current tag**: \`${currentTag}\`\n` +
129+
`- **Upstream tag**: \`${newTag}\`\n` +
130+
`- **Run**: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}\n\n` +
131+
`## 手順\n` +
132+
`\`\`\`bash\n` +
133+
`git fetch upstream\n` +
134+
`git rebase upstream/${newTag}\n` +
135+
`# conflict解消後\n` +
136+
`git push origin HEAD --force-with-lease\n` +
137+
`git tag ${newTag} && git push origin ${newTag}\n` +
138+
`\`\`\`\n\n` +
139+
`解消後は workflow_dispatch で build をトリガーしてください。`,
140+
labels: ['rebase-conflict', 'upstream-update']
141+
});
142+
143+
build-and-push:
144+
needs: check-and-rebase
145+
# rebase_success が明示的に true の場合のみ実行
146+
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
147+
uses: ./.github/workflows/build-container-image.yml
148+
with:
149+
file_to_build: Dockerfile
150+
push_to_images: ghcr.io/${{ github.repository }}
151+
cache: false
152+
flavor: |
153+
latest=true
154+
tags: |
155+
type=semver,pattern={{version}},value=${{ needs.check-and-rebase.outputs.new_tag }}
156+
type=semver,pattern={{major}}.{{minor}},value=${{ needs.check-and-rebase.outputs.new_tag }}
157+
secrets: inherit
158+
159+
trigger-gitops:
160+
needs:
161+
- check-and-rebase
162+
- build-and-push
163+
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
164+
runs-on: ubuntu-latest
165+
166+
steps:
167+
- name: Trigger GitOps update
168+
uses: peter-evans/repository-dispatch@v3
169+
with:
170+
token: ${{ secrets.GH_PAT }}
171+
repository: highemerly/k8sg1-repo
172+
event-type: mastodon-image-updated
173+
client-payload: |
174+
{
175+
"image": "ghcr.io/${{ github.repository }}",
176+
"tag": "${{ needs.check-and-rebase.outputs.new_tag }}"
177+
}

0 commit comments

Comments
 (0)