1
0
Fork 0

Merge branch 'config' into localApps

This commit is contained in:
pooneyy 2025-10-06 16:48:43 +08:00
commit 4802fe6f1a
No known key found for this signature in database
4 changed files with 260 additions and 53 deletions

View File

@ -0,0 +1,131 @@
#!/usr/bin/env python3
import os
import re
import shutil
import sys
import yaml
def extract_version_from_string(input_string):
"""
从字符串中提取版本号支持镜像名和文件夹名
Args:
input_string (str): 可以是Docker镜像名或文件夹名
Returns:
dict: 包含提取结果的字典 {success: bool, version: str}
"""
if ':' in input_string:
parts = input_string.split(':')
candidate = parts[-1]
else:
candidate = os.path.basename(input_string)
# 保存原始候选字符串用于失败时返回
original_candidate = candidate
# 标准的 major.minor.patch 格式(点号分隔)
pattern1 = r'(\d+\.\d+\.\d+)'
match1 = re.search(pattern1, candidate)
if match1:
return {"success": True, "version": match1.group(1)}
# 连字符分隔的版本号 major-minor-patch
pattern2 = r'(\d+\-\d+\-\d+)'
match2 = re.search(pattern2, candidate)
if match2:
# 将连字符转换为点号
version_with_dots = match2.group(1).replace('-', '.')
return {"success": True, "version": version_with_dots}
# 混合分隔符(如 major.minor-patch
pattern3 = r'(\d+[\.\-]\d+[\.\-]\d+)'
match3 = re.search(pattern3, candidate)
if match3:
# 将所有分隔符统一为点号
version_mixed = match3.group(1)
version_normalized = re.sub(r'[\.\-]', '.', version_mixed)
return {"success": True, "version": version_normalized}
# 两个部分的版本号 (major.minor 或 major-minor)
pattern4 = r'(\d+[\.\-]\d+)(?![\.\-]\d)' # 确保后面没有第三个数字部分
match4 = re.search(pattern4, candidate)
if match4:
version_two_part = match4.group(1)
version_normalized = re.sub(r'[\.\-]', '.', version_two_part)
return {"success": True, "version": version_normalized}
# 从复杂标签中提取包含数字和分隔符的版本号部分
pattern5 = r'(\d+(?:[\.\-]\d+)+)'
matches = re.findall(pattern5, candidate)
if matches:
# 选择最长的匹配项,并统一分隔符为点号
best_match = max(matches, key=len)
normalized_version = re.sub(r'[\.\-]', '.', best_match)
return {"success": True, "version": normalized_version}
return {"success": False, "version": original_candidate}
def replace_version_in_dirname(old_ver_dir, new_version):
"""
将旧版本文件夹名中的版本号替换为新版本号
Args:
old_ver_dir (str): 旧版本文件夹名
new_version (str): 新版本号
Returns:
str: 新版本文件夹名
"""
version_info = extract_version_from_string(old_ver_dir)
if version_info["success"]:
old_version = version_info["original"]
new_ver_dir = old_ver_dir.replace(old_version, new_version)
return new_ver_dir
else:
return new_version
def main():
app_name = sys.argv[1]
old_ver_dir = sys.argv[2]
docker_compose_file = f"apps/{app_name}/{old_ver_dir}/docker-compose.yml"
if not os.path.exists(docker_compose_file):
print(f"错误: 文件 {docker_compose_file} 不存在")
sys.exit(1)
with open(docker_compose_file, 'r') as f:
compose_data = yaml.safe_load(f)
services = compose_data.get('services', {})
first_service = list(services.keys())[0]
print(f"第一个服务是: {first_service}")
image = services[first_service].get('image', '')
print(f"该服务的镜像: {image}")
new_version = extract_version_from_string(image)
print(f"版本号: {new_version}")
old_version = extract_version_from_string(old_ver_dir)
new_ver_dir = replace_version_in_dirname(old_ver_dir, new_version)
if old_version != new_version:
old_path = f"apps/{app_name}/{old_ver_dir}"
new_path = f"apps/{app_name}/{new_ver_dir}"
if not os.path.exists(new_path):
print(f"{old_path} 重命名为 {new_path}")
shutil.move(old_path, new_path)
version_file = f"apps/{app_name}/{old_version}.version"
with open(version_file, 'w') as f:
f.write(new_version)
else:
print(f"错误: {new_path} 文件夹已存在")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,38 +0,0 @@
#!/bin/bash
# This script copies the version from docker-compose.yml to config.json.
app_name=$1
old_version=$2
# find all docker-compose files under apps/$app_name (there should be only one)
docker_compose_files=$(find apps/$app_name/$old_version -name docker-compose.yml)
for docker_compose_file in $docker_compose_files
do
# Assuming that the app version will be from the first docker image
first_service=$(yq '.services | keys | .[0]' $docker_compose_file)
echo "第一个服务是: $first_service"
image=$(yq .services.$first_service.image $docker_compose_file)
echo "该服务的镜像: $image"
# Only apply changes if the format is <image>:<version>
if [[ "$image" == *":"* ]]; then
version=$(cut -d ":" -f2- <<< "$image")
echo "版本号: $version"
# Trim the "v" prefix
trimmed_version=${version/#"v"}
echo "Trimmed version: $trimmed_version"
if [ "$old_version" != "$trimmed_version" ]; then
echo "将 apps/$app_name/$old_version 重命名为 apps/$app_name/$trimmed_version"
if [ ! -d "apps/$app_name/$trimmed_version" ]; then
mv apps/$app_name/$old_version apps/$app_name/$trimmed_version
echo "$trimmed_version" > apps/$app_name/${old_version}.version
else
echo "apps/$app_name/$trimmed_version 文件夹已存在"
exit 1
fi
fi
fi
done

View File

@ -1,11 +1,42 @@
name: Update app version in Renovate Branches
name: App Version CI/CD
on:
push:
branches: [ 'renovate/*' ]
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
@ -16,11 +47,15 @@ jobs:
with:
fetch-depth: 0
- 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"
gh auth login --with-token <<< "${{ github.token }}"
- name: Get list of updated files by the last commit in this branch separated by space
id: updated-files
@ -35,8 +70,8 @@ jobs:
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.sh
.github/workflows/renovate-app-version.sh $app_name $old_version
chmod +x .github/workflows/renovate-app-version.py
python3 .github/workflows/renovate-app-version.py $app_name $old_version
fi
done
@ -61,4 +96,77 @@ jobs:
-f 'context=${{ github.workflow}}'
fi
fi
done
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

View File

@ -3,18 +3,24 @@
"extends": [
"config:recommended"
],
"reviewers": ["pooneyy"],
"gitIgnoredAuthors": [
"githubaction@githubaction.com",
"85266337+pooneyy@users.noreply.github.com"
],
"automerge": true,
"automergeType": "pr",
"automergeStrategy": "squash",
"prBodyColumns": [
"Package",
"Update",
"Change",
"Pending"
],
"rebaseWhen": "never",
"packageRules": [
{
"matchPackageNames": [
"matchUpdateTypes": ["major", "minor", "patch", "pin", "pinDigest", "digest", "lockFileMaintenance", "rollback", "bump", "replacement"],
"addLabels": ["{{ updateType }}"]
},
{
"matchManagers": [
"docker-compose"
],
"automerge": true
@ -150,9 +156,9 @@
"allowedVersions": "<2"
},
{
"matchPackageNames": ["xhofe/alist"],
"matchCurrentVersion": "v3.40.0",
"allowedVersions": "v3.40.0"
"matchPackageNames": ["xhofe/alist**"],
"matchCurrentVersion": "/^v3.40.*/",
"enabled": false
},
{
"matchPackageNames": ["yisier1/npc", "yisier1/nps"],