From 34ea6d243e0cc2a3e0fef15632aa52368f75fdca Mon Sep 17 00:00:00 2001 From: sagitchu <601096721@qq.com> Date: Wed, 19 Mar 2025 09:32:10 +0800 Subject: [PATCH] feat: add auto merge conflicts --- .github/scripts/resolve_conflicts.py | 65 ++++++++++++++++++++++++++++ .github/workflows/auto-merge.yml | 54 +++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 .github/scripts/resolve_conflicts.py create mode 100644 .github/workflows/auto-merge.yml diff --git a/.github/scripts/resolve_conflicts.py b/.github/scripts/resolve_conflicts.py new file mode 100644 index 00000000..632046b0 --- /dev/null +++ b/.github/scripts/resolve_conflicts.py @@ -0,0 +1,65 @@ +import os +import openai +import subprocess + +# 读取环境变量 +api_key = os.getenv("OPENAI_API_KEY") +base_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1") # 允许自定义 API 地址 + +# 配置 OpenAI +openai.api_key = api_key +openai.base_url = base_url # 支持自定义 API 代理 + +def get_conflicted_files(): + """ 获取所有冲突文件的列表 """ + result = subprocess.run(["git", "diff", "--name-only", "--diff-filter=U"], capture_output=True, text=True) + return result.stdout.strip().split("\n") + +def get_conflict_content(file_path): + """ 获取文件中的冲突内容 """ + with open(file_path, "r") as file: + content = file.read() + return content + +def resolve_conflict_with_ai(content): + """ 通过 OpenAI 解决冲突 """ + prompt = f""" + 你是一个高级软件工程师,我将提供一个代码文件,其中包含 Git 合并冲突 (`<<<<<<<`, `=======`, `>>>>>>>`)。 + 请分析代码并自动解决冲突,提供一个最佳的合并版本。 + + 代码如下: + ``` + {content} + ``` + 请输出合并后的完整代码,不要附加任何解释。 + """ + + response = openai.ChatCompletion.create( + model="gpt-4o", + messages=[{"role": "user", "content": prompt}] + ) + + return response["choices"][0]["message"]["content"] + +def apply_fix(file_path, fixed_content): + """ 将 AI 解决的代码写回文件 """ + with open(file_path, "w") as file: + file.write(fixed_content) + +def main(): + """ 解决所有冲突的主逻辑 """ + conflicted_files = get_conflicted_files() + + for file_path in conflicted_files: + if not file_path.strip(): + continue + + print(f"Resolving conflicts in: {file_path}") + conflict_content = get_conflict_content(file_path) + fixed_content = resolve_conflict_with_ai(conflict_content) + apply_fix(file_path, fixed_content) + + print("All conflicts resolved.") + +if __name__ == "__main__": + main() diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml new file mode 100644 index 00000000..a2ff1109 --- /dev/null +++ b/.github/workflows/auto-merge.yml @@ -0,0 +1,54 @@ +name: Auto Resolve Merge Conflicts + +on: + pull_request: + branches: + - upstream-pr-406 # 仅对指定分支进行操作 + types: + - opened + - synchronize + +jobs: + resolve-conflicts: + runs-on: ubuntu-latest + + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + + - name: Check for Merge Conflicts + id: check_conflicts + run: | + git fetch origin ${{ github.event.pull_request.base.ref }} + if ! git merge --no-commit --no-ff origin/${{ github.event.pull_request.base.ref }}; then + echo "has_conflicts=true" >> $GITHUB_ENV + else + echo "has_conflicts=false" >> $GITHUB_ENV + fi + + - name: Extract Conflict Files + if: env.has_conflicts == 'true' + run: | + git diff --name-only --diff-filter=U > conflict_files.txt + cat conflict_files.txt + + - name: Resolve Conflicts with AI + if: env.has_conflicts == 'true' + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }} # 新增 API 代理支持 + run: python3 .github/scripts/resolve_conflicts.py + + - name: Commit and Push if Changes Exist + if: env.has_conflicts == 'true' + run: | + if [ -n "$(git status --porcelain)" ]; then + git config --global user.email "bot@github.com" + git config --global user.name "MergeBot" + git add . + git commit -m "Auto-resolved merge conflicts using AI" + git push origin HEAD:${{ github.event.pull_request.head.ref }} + fi