This commit is contained in:
jinliyl 2026-09-25 11:03:05 +08:00 • committed by GitHub
commit 980f57a5df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 140 additions and 17 deletions

View file

@ -16,20 +16,3 @@ updates:
commit-message:
prefix: "chore"
include: "scope"
- package-ecosystem: "pip"
directory: "/"
target-branch: "main"
schedule:
interval: "cron"
cronjob: "30 9 * * *"
timezone: "Asia/Shanghai"
allow:
- dependency-name: "agentscope"
cooldown:
exclude:
- "agentscope"
open-pull-requests-limit: 1
commit-message:
prefix: "chore"
include: "scope"

View file

@ -0,0 +1,38 @@
name: Sync AgentScope with QwenPaw
on:
schedule:
- cron: "30 1 * * *" # 09:30 Asia/Shanghai
workflow_dispatch:
permissions:
contents: write
pull-requests: write
concurrency:
group: sync-qwenpaw-agentscope
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Fetch QwenPaw's dependency declaration
run: curl --fail --location --silent --show-error --retry 3 https://raw.githubusercontent.com/agentscope-ai/QwenPaw/main/pyproject.toml --output "$RUNNER_TEMP/qwenpaw-pyproject.toml"
- name: Sync AgentScope pin
run: |
python -m pip install packaging
python scripts/sync_qwenpaw_agentscope.py "$RUNNER_TEMP/qwenpaw-pyproject.toml" pyproject.toml
- name: Create update pull request
uses: peter-evans/create-pull-request@v8
with:
add-paths: pyproject.toml
branch: automation/sync-qwenpaw-agentscope
delete-branch: true
commit-message: "chore(deps): sync AgentScope with QwenPaw"
title: "chore(deps): sync AgentScope with QwenPaw"
body: "Align ReMe's AgentScope pin with the exact stable version in QwenPaw's main-branch pyproject.toml."

View file

@ -0,0 +1,73 @@
"""Sync ReMe's AgentScope pin with QwenPaw's direct dependency."""
import argparse
import re
import tomllib
from pathlib import Path
from packaging.requirements import Requirement
from packaging.version import Version
_PIN = re.compile(r'"agentscope\[model-ollama\]==[^"\n]+"')
def _exact_agentscope_version(dependencies: list[str]) -> str:
requirements = [Requirement(value) for value in dependencies]
matches = [requirement for requirement in requirements if requirement.name.lower() == "agentscope"]
if len(matches) != 1:
raise ValueError(f"Expected one AgentScope dependency, found {len(matches)}")
requirement = matches[0]
specifiers = list(requirement.specifier)
if (
requirement.extras != {"model-ollama"}
or requirement.marker is not None
or len(specifiers) != 1
or specifiers[0].operator != "=="
):
raise ValueError(
f"Expected an exact agentscope[model-ollama] pin, found {requirement}",
)
version = Version(specifiers[0].version)
if version.is_prerelease or version.is_devrelease:
raise ValueError(f"Expected a stable AgentScope version, found {version}")
return str(version)
def sync_pin(qwenpaw_text: str, reme_text: str) -> tuple[str, str]:
"""Return the QwenPaw version and updated ReMe manifest, failing on ambiguous pins."""
qwenpaw = tomllib.loads(qwenpaw_text)
reme = tomllib.loads(reme_text)
version = _exact_agentscope_version(qwenpaw["project"]["dependencies"])
_exact_agentscope_version(reme["project"]["optional-dependencies"]["as"])
matches = list(_PIN.finditer(reme_text))
if len(matches) != 1:
raise ValueError(
f"Expected one replaceable ReMe AgentScope pin, found {len(matches)}",
)
replacement = f'"agentscope[model-ollama]=={version}"'
return (
version,
reme_text[: matches[0].start()] + replacement + reme_text[matches[0].end() :],
)
def main() -> None:
"""Synchronize the local manifest from a downloaded QwenPaw manifest."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("qwenpaw_manifest", type=Path)
parser.add_argument("reme_manifest", type=Path)
args = parser.parse_args()
original = args.reme_manifest.read_text(encoding="utf-8")
version, updated = sync_pin(
args.qwenpaw_manifest.read_text(encoding="utf-8"),
original,
)
if updated != original:
args.reme_manifest.write_text(updated, encoding="utf-8")
print(f"Updated ReMe AgentScope pin to QwenPaw's {version}")
else:
print(f"ReMe already matches QwenPaw's AgentScope {version}")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,29 @@
"""Tests for the QwenPaw AgentScope dependency sync."""
import pytest
from scripts.sync_qwenpaw_agentscope import sync_pin
QWENPAW = '[project]\ndependencies = ["agentscope[model-ollama]==2.0.8"]\n'
REME = '[project.optional-dependencies]\nas = ["agentscope[model-ollama]==2.0.7.post1"]\n'
def test_sync_pin_updates_only_reme_pin():
"""A stable QwenPaw pin replaces ReMe's exact pin."""
version, updated = sync_pin(QWENPAW, REME)
assert version == "2.0.8"
assert updated == REME.replace("2.0.7.post1", "2.0.8")
@pytest.mark.parametrize(
"upstream",
[
'[project]\ndependencies = ["agentscope[model-ollama]>=2.0.8"]\n',
'[project]\ndependencies = ["agentscope[model-ollama]==2.0.9rc1"]\n',
'[project]\ndependencies = ["other==1.0"]\n',
],
)
def test_sync_pin_rejects_missing_nonexact_or_prerelease_upstream_pin(upstream):
"""An absent or ambiguous QwenPaw pin never changes ReMe's manifest."""
with pytest.raises(ValueError):
sync_pin(upstream, REME)