Skip to content

Check Upstream and Rebase #2

Check Upstream and Rebase

Check Upstream and Rebase #2

name: Check Upstream and Rebase
on:
schedule:
- cron: '0 */6 * * *' # 6時間ごと
workflow_dispatch:
jobs:
check-and-rebase:
runs-on: ubuntu-latest
outputs:
new_tag: ${{ steps.check.outputs.new_tag }}
current_tag: ${{ steps.check.outputs.current_tag }}
should_build: ${{ steps.check.outputs.should_build }}
rebase_success: ${{ steps.rebase.outputs.rebase_success }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GH_PAT }}
- name: Check upstream for new tags
id: check
run: |
UPSTREAM_REPO=mastodon/mastodon
# 自リポジトリの最新タグを取得
CURRENT_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
echo "Current tag: $CURRENT_TAG"
# バージョン番号をパース (v4.3.2 -> 4 3 2)
CURRENT_CLEAN=${CURRENT_TAG#v}
IFS='.' read -r CUR_MAJOR CUR_MINOR CUR_PATCH <<< "$CURRENT_CLEAN"
# upstreamの最新タグ一覧を取得し、semver順にソート
UPSTREAM_TAGS=$(gh api repos/$UPSTREAM_REPO/tags --paginate \
--jq '.[].name' \
| grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' \
| sort -Vr \
| head -20)
echo "Upstream tags (sorted):"
echo "$UPSTREAM_TAGS"
# 対象となるタグをフィルタ(現在より新しいもの)
TARGET_TAG=""
while IFS= read -r TAG; do
CLEAN=${TAG#v}
IFS='.' read -r UP_MAJOR UP_MINOR UP_PATCH <<< "$CLEAN"
IS_NEWER=false
if [ "$UP_MAJOR" -gt "$CUR_MAJOR" ]; then
IS_NEWER=true
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -gt "$CUR_MINOR" ]; then
IS_NEWER=true
elif [ "$UP_MAJOR" -eq "$CUR_MAJOR" ] && [ "$UP_MINOR" -eq "$CUR_MINOR" ] && [ "$UP_PATCH" -gt "$CUR_PATCH" ]; then
IS_NEWER=true
fi
if [ "$IS_NEWER" = "true" ]; then
TARGET_TAG=$TAG
break # 最新1件のみ処理(複数あれば次回以降に処理)
fi
done <<< "$UPSTREAM_TAGS"
if [ -z "$TARGET_TAG" ]; then
echo "No new upstream tag found."
echo "should_build=false" >> $GITHUB_OUTPUT
else
echo "New upstream tag found: $TARGET_TAG"
echo "new_tag=$TARGET_TAG" >> $GITHUB_OUTPUT
echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT
echo "should_build=true" >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add upstream remote
if: steps.check.outputs.should_build == 'true'
run: |
git remote add upstream https://github.com/mastodon/mastodon.git || true
git fetch upstream --tags
- name: Rebase onto upstream tag
if: steps.check.outputs.should_build == 'true'
id: rebase
run: |
NEW_TAG=${{ steps.check.outputs.new_tag }}
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git rebase upstream/$NEW_TAG; then
echo "rebase_success=true" >> $GITHUB_OUTPUT
echo "Rebase succeeded!"
else
echo "rebase_success=false" >> $GITHUB_OUTPUT
git rebase --abort
echo "Rebase failed!"
fi
- name: Push rebased branch
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'true'
run: |
git push origin HEAD --force-with-lease
- name: Tag the new release
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'true'
run: |
NEW_TAG=${{ steps.check.outputs.new_tag }}
git tag "$NEW_TAG"
git push origin "$NEW_TAG"
- name: Create issue on rebase failure
if: steps.check.outputs.should_build == 'true' && steps.rebase.outputs.rebase_success == 'false'
uses: actions/github-script@v7
with:
script: |
const newTag = '${{ steps.check.outputs.new_tag }}';
const currentTag = '${{ steps.check.outputs.current_tag }}';
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🚨 Rebase failed: upstream ${newTag}`,
body: `## Rebase Conflict Detected\n\n` +
`- **Current tag**: \`${currentTag}\`\n` +
`- **Upstream tag**: \`${newTag}\`\n` +
`- **Run**: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}\n\n` +
`## 手順\n` +
`\`\`\`bash\n` +
`git fetch upstream\n` +
`git rebase upstream/${newTag}\n` +
`# conflict解消後\n` +
`git push origin HEAD --force-with-lease\n` +
`git tag ${newTag} && git push origin ${newTag}\n` +
`\`\`\`\n\n` +
`解消後は workflow_dispatch で build をトリガーしてください。`,
labels: ['rebase-conflict', 'upstream-update']
});
build-and-push:
needs: check-and-rebase
# rebase_success が明示的に true の場合のみ実行
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: Dockerfile
push_to_images: ghcr.io/${{ github.repository }}
cache: false
flavor: |
latest=true
tags: |
type=semver,pattern={{version}},value=${{ needs.check-and-rebase.outputs.new_tag }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.check-and-rebase.outputs.new_tag }}
secrets: inherit
trigger-gitops:
needs:
- check-and-rebase
- build-and-push
if: needs.check-and-rebase.outputs.should_build == 'true' && needs.check-and-rebase.outputs.rebase_success == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger GitOps update
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.GH_PAT }}
repository: highemerly/k8sg1-repo
event-type: mastodon-image-updated
client-payload: |
{
"image": "ghcr.io/${{ github.repository }}",
"tag": "${{ needs.check-and-rebase.outputs.new_tag }}"
}