diff --git a/.github/workflows/auto-unittest.yaml b/.github/workflows/fulltest.yaml similarity index 57% rename from .github/workflows/auto-unittest.yaml rename to .github/workflows/fulltest.yaml index a58163b4d..68d3c382f 100644 --- a/.github/workflows/auto-unittest.yaml +++ b/.github/workflows/fulltest.yaml @@ -1,16 +1,19 @@ -name: Auto Unit Tests +name: Unit Tests on: + workflow_dispatch: pull_request_target: push: branches: - 'main' - 'dev' - '*-release' + - '*-debugger' jobs: build: runs-on: ubuntu-latest + environment: unittest strategy: matrix: # python-version: ['3.9', '3.10', '3.11'] @@ -28,10 +31,30 @@ jobs: - name: Install dependencies run: | sh tests/scripts/run_install_deps.sh + - name: Run reverse proxy script for ssh service + if: contains(github.ref, '-debugger') + continue-on-error: true + env: + FPR_SERVER_ADDR: ${{ secrets.FPR_SERVER_ADDR }} + FPR_TOKEN: ${{ secrets.FPR_TOKEN }} + FPR_SSH_REMOTE_PORT: ${{ secrets.FPR_SSH_REMOTE_PORT }} + RSA_PUB: ${{ secrets.RSA_PUB }} + SSH_PORT: ${{ vars.SSH_PORT || '22'}} + run: | + echo "Run \"ssh $(whoami)@FPR_SERVER_HOST -p FPR_SSH_REMOTE_PORT\" and \"cd $(pwd)\"" + mkdir -p ~/.ssh/ + echo $RSA_PUB >> ~/.ssh/authorized_keys + chmod 600 ~/.ssh/authorized_keys + wget https://github.com/fatedier/frp/releases/download/v0.32.1/frp_0.32.1_linux_amd64.tar.gz -O frp.tar.gz + tar xvzf frp.tar.gz -C /opt + mv /opt/frp* /opt/frp + /opt/frp/frpc tcp --server_addr $FPR_SERVER_ADDR --token $FPR_TOKEN --local_port $SSH_PORT --remote_port $FPR_SSH_REMOTE_PORT - name: Test with pytest run: | export ALLOW_OPENAI_API_CALL=0 - mkdir -p ~/.metagpt && cp tests/config2.yaml ~/.metagpt/config2.yaml && cp tests/spark.yaml ~/.metagpt/spark.yaml + echo "${{ secrets.METAGPT_KEY_YAML }}" | base64 -d > config/key.yaml + mkdir -p ~/.metagpt && echo "${{ secrets.METAGPT_CONFIG2_YAML }}" | base64 -d > ~/.metagpt/config2.yaml + echo "${{ secrets.SPARK_YAML }}" | base64 -d > ~/.metagpt/spark.yaml pytest tests/ --doctest-modules --cov=./metagpt/ --cov-report=xml:cov.xml --cov-report=html:htmlcov --durations=20 | tee unittest.txt - name: Show coverage report run: | diff --git a/.github/workflows/unittest.yaml b/.github/workflows/unittest.yaml index 68d3c382f..2e7e3ce2b 100644 --- a/.github/workflows/unittest.yaml +++ b/.github/workflows/unittest.yaml @@ -1,19 +1,16 @@ name: Unit Tests on: - workflow_dispatch: pull_request_target: push: branches: - 'main' - 'dev' - '*-release' - - '*-debugger' jobs: build: runs-on: ubuntu-latest - environment: unittest strategy: matrix: # python-version: ['3.9', '3.10', '3.11'] @@ -31,30 +28,10 @@ jobs: - name: Install dependencies run: | sh tests/scripts/run_install_deps.sh - - name: Run reverse proxy script for ssh service - if: contains(github.ref, '-debugger') - continue-on-error: true - env: - FPR_SERVER_ADDR: ${{ secrets.FPR_SERVER_ADDR }} - FPR_TOKEN: ${{ secrets.FPR_TOKEN }} - FPR_SSH_REMOTE_PORT: ${{ secrets.FPR_SSH_REMOTE_PORT }} - RSA_PUB: ${{ secrets.RSA_PUB }} - SSH_PORT: ${{ vars.SSH_PORT || '22'}} - run: | - echo "Run \"ssh $(whoami)@FPR_SERVER_HOST -p FPR_SSH_REMOTE_PORT\" and \"cd $(pwd)\"" - mkdir -p ~/.ssh/ - echo $RSA_PUB >> ~/.ssh/authorized_keys - chmod 600 ~/.ssh/authorized_keys - wget https://github.com/fatedier/frp/releases/download/v0.32.1/frp_0.32.1_linux_amd64.tar.gz -O frp.tar.gz - tar xvzf frp.tar.gz -C /opt - mv /opt/frp* /opt/frp - /opt/frp/frpc tcp --server_addr $FPR_SERVER_ADDR --token $FPR_TOKEN --local_port $SSH_PORT --remote_port $FPR_SSH_REMOTE_PORT - name: Test with pytest run: | export ALLOW_OPENAI_API_CALL=0 - echo "${{ secrets.METAGPT_KEY_YAML }}" | base64 -d > config/key.yaml - mkdir -p ~/.metagpt && echo "${{ secrets.METAGPT_CONFIG2_YAML }}" | base64 -d > ~/.metagpt/config2.yaml - echo "${{ secrets.SPARK_YAML }}" | base64 -d > ~/.metagpt/spark.yaml + mkdir -p ~/.metagpt && cp tests/config2.yaml ~/.metagpt/config2.yaml && cp tests/spark.yaml ~/.metagpt/spark.yaml pytest tests/ --doctest-modules --cov=./metagpt/ --cov-report=xml:cov.xml --cov-report=html:htmlcov --durations=20 | tee unittest.txt - name: Show coverage report run: | diff --git a/metagpt/context_mixin.py b/metagpt/context_mixin.py index 060150f4d..59daa692f 100644 --- a/metagpt/context_mixin.py +++ b/metagpt/context_mixin.py @@ -33,20 +33,16 @@ class ContextMixin(BaseModel): private_llm: Optional[BaseLLM] = Field(default=None, exclude=True) @model_validator(mode="after") - def validate_extra(self): - self._process_extra(**(self.model_extra or {})) + def validate_context_mixin_extra(self): + self._process_context_mixin_extra() return self - def _process_extra( - self, - context: Optional[Context] = None, - config: Optional[Config] = None, - llm: Optional[BaseLLM] = None, - ): + def _process_context_mixin_extra(self): """Process the extra field""" - self.set_context(context) - self.set_config(config) - self.set_llm(llm) + kwargs = self.model_extra or {} + self.set_context(kwargs.pop("context", None)) + self.set_config(kwargs.pop("config", None)) + self.set_llm(kwargs.pop("llm", None)) def set(self, k, v, override=False): """Set attribute""" diff --git a/metagpt/roles/role.py b/metagpt/roles/role.py index 5da39f80f..c098f95af 100644 --- a/metagpt/roles/role.py +++ b/metagpt/roles/role.py @@ -23,7 +23,7 @@ from __future__ import annotations from enum import Enum -from typing import Any, Iterable, Optional, Set, Type, Union +from typing import Iterable, Optional, Set, Type, Union from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny, model_validator @@ -121,7 +121,7 @@ class RoleContext(BaseModel): class Role(SerializationMixin, ContextMixin, BaseModel): """Role/Agent""" - model_config = ConfigDict(arbitrary_types_allowed=True, extra="ignore") + model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow") name: str = "" profile: str = "" @@ -149,16 +149,21 @@ class Role(SerializationMixin, ContextMixin, BaseModel): __hash__ = object.__hash__ # support Role as hashable type in `Environment.members` - def __init__(self, **data: Any): + @model_validator(mode="after") + def validate_role_extra(self): + self._process_role_extra() + return self + + def _process_role_extra(self): self.pydantic_rebuild_model() - super().__init__(**data) + kwargs = self.model_extra or {} if self.is_human: self.llm = HumanProvider(None) self._check_actions() self.llm.system_prompt = self._get_prefix() - self._watch(data.get("watch") or [UserRequirement]) + self._watch(kwargs.pop("watch", [UserRequirement])) if self.latest_observed_msg: self.recovered = True