186 lines
6.6 KiB
YAML
186 lines
6.6 KiB
YAML
name: App Version CI/CD
|
||
|
||
on:
|
||
pull_request:
|
||
types:
|
||
- opened
|
||
- synchronize
|
||
- reopened
|
||
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||
|
||
jobs:
|
||
get-latest-commit-author:
|
||
name: Get Latest Commit Author
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
latest_commit_author: ${{ steps.latest-commit-author.outputs.latest_commit_author }}
|
||
steps:
|
||
- name: Get latest commit author
|
||
id: latest-commit-author
|
||
run: |
|
||
resp=$(gh api \
|
||
-H "Accept: application/vnd.github+json" \
|
||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||
/repos/${{ github.repository}}/commits/${{ github.event.pull_request.head.ref }})
|
||
author=$(echo "$resp" | jq -r '.author.login // empty')
|
||
echo "the Author of Latest Commit on Head Branch: $author"
|
||
echo "latest_commit_author=$author" >> $GITHUB_OUTPUT
|
||
|
||
update-app-version:
|
||
name: Update App Version
|
||
needs: get-latest-commit-author
|
||
if: |
|
||
github.actor == 'renovate[bot]' &&
|
||
github.triggering_actor == 'renovate[bot]' &&
|
||
needs.get-latest-commit-author.outputs.latest_commit_author != github.repository_owner &&
|
||
startsWith(github.head_ref, 'renovate/')
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
statuses: write
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v5.0.0
|
||
with:
|
||
fetch-depth: 0
|
||
ref: ${{ github.head_ref }}
|
||
|
||
- uses: actions/setup-python@main
|
||
with:
|
||
python-version: 3.x
|
||
pip-install: PyYAML
|
||
|
||
- name: Configure repo
|
||
run: |
|
||
git config --local user.email "githubaction@githubaction.com"
|
||
git config --local user.name "github-action"
|
||
|
||
- name: Get list of updated files by the last commit in this branch separated by space
|
||
id: updated-files
|
||
run: |
|
||
# 当触发工作流的事件为 pull_request 时,github.sha 值为 github.ref 分支上的最后一次合并提交
|
||
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.pull_request.head.sha }} | tr '\n' ' ')
|
||
if [ -z "$files" ]; then
|
||
echo "❌ 错误:没有检测到文件变更"
|
||
echo "github.sha = ${{ github.sha }}"
|
||
echo "github.event.pull_request.head.sha = ${{ github.event.pull_request.head.sha }}"
|
||
echo "当前分支最新的提交SHA: $(git rev-parse HEAD)"
|
||
echo "💡 最近三次提交:"
|
||
echo " $(git log -3)"
|
||
exit 1
|
||
else
|
||
echo "files=$files" >> $GITHUB_OUTPUT
|
||
fi
|
||
|
||
- name: Run renovate-app-version.py on updated files
|
||
run: |
|
||
IFS=' ' read -ra files <<< "${{ steps.updated-files.outputs.files }}"
|
||
|
||
for file in "${files[@]}"; do
|
||
if [[ $file == *"docker-compose.yml"* ]]; then
|
||
app_name=$(echo $file | cut -d'/' -f 2)
|
||
old_version=$(echo $file | cut -d'/' -f 3)
|
||
chmod +x .github/workflows/renovate-app-version.py
|
||
python3 .github/workflows/renovate-app-version.py $app_name $old_version
|
||
fi
|
||
done
|
||
|
||
- name: Commit & Push Changes
|
||
run: |
|
||
IFS=' ' read -ra files <<< "${{ steps.updated-files.outputs.files }}"
|
||
|
||
for file in "${files[@]}"; do
|
||
if [[ $file == *"docker-compose.yml"* ]]; then
|
||
app_name=$(echo $file | cut -d'/' -f 2)
|
||
old_version=$(echo $file | cut -d'/' -f 3)
|
||
if [ -f "apps/$app_name/${old_version}.version" ]; then
|
||
new_version=$(cat "apps/$app_name/${old_version}.version")
|
||
rm -f "apps/$app_name/${old_version}.version"
|
||
git add "apps/$app_name/*" && git commit -m "🔧 chore($app_name): update app version from $old_version to $new_version" --no-verify && git push || true
|
||
gh api --silent --method POST -H "Accept: application/vnd.github+json" \
|
||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||
/repos/${{ github.repository }}/statuses/$(git show -s --format=%H) \
|
||
-f 'state=success' \
|
||
-f 'target_url=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' \
|
||
-f 'description=CI/CD' \
|
||
-f 'context=${{ github.workflow}}'
|
||
fi
|
||
fi
|
||
done
|
||
|
||
check-labels:
|
||
name: Check labels
|
||
if: |
|
||
github.actor == 'renovate[bot]' &&
|
||
github.triggering_actor == 'renovate[bot]'
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
enable: ${{ steps.check-labels.outputs.enable }}
|
||
permissions:
|
||
contents: write
|
||
pull-requests: write
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v5
|
||
|
||
- name: Check for major label
|
||
id: check-labels
|
||
run: |
|
||
pr_labels='${{ join(github.event.pull_request.labels.*.name, ',') }}'
|
||
if [[ $pr_labels =~ "major" ]]; then
|
||
echo "❌ PR has major label"
|
||
echo "enable=false" >> $GITHUB_OUTPUT
|
||
else
|
||
echo "✅ PR does not have major label"
|
||
echo "enable=true" >> $GITHUB_OUTPUT
|
||
fi
|
||
|
||
- name: Add reviewer and comment for major PR
|
||
if: steps.check-labels.outputs.enable == 'false'
|
||
run: |
|
||
gh pr edit $PR_NUMBER --add-reviewer ${{ github.actor }}
|
||
gh pr edit $PR_NUMBER --add-assignee ${{ github.actor }}
|
||
|
||
- name: remove labels
|
||
run: |
|
||
pr_labels='${{ join(github.event.pull_request.labels.*.name, ',') }}'
|
||
IFS=',' read -ra labels_array <<< "$pr_labels"
|
||
for label in "${labels_array[@]}"; do
|
||
echo "Removing label: $label"
|
||
gh pr edit $PR_NUMBER --remove-label="$label"
|
||
done
|
||
|
||
merge-prs:
|
||
name: Auto Merge the PR
|
||
runs-on: ubuntu-latest
|
||
needs:
|
||
- update-app-version
|
||
- check-labels
|
||
if: |
|
||
needs.check-labels.outputs.enable == 'true' &&
|
||
(needs.update-app-version.result == 'success' || needs.update-app-version.result == 'skipped')
|
||
permissions:
|
||
contents: write
|
||
pull-requests: write
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
ref: ${{ github.base_ref }}
|
||
|
||
- name: Merge PR
|
||
run: |
|
||
max_attempts=5
|
||
for attempt in $(seq 1 $max_attempts); do
|
||
if gh pr merge $PR_NUMBER --squash --delete-branch --body ""; then
|
||
echo "✅ Merge PR #$PR_NUMBER Success"
|
||
exit 0
|
||
else
|
||
echo "⚠️ Merge PR #$PR_NUMBER Failed ($attempt / $max_attempts)"
|
||
sleep 5
|
||
fi
|
||
done
|