Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/docs/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,38 @@ Confirm delete cloud app my-agent-app? (y/N): y
- `agent_module` 自定义的 agent 模块
- `__init__.py` 必须包含 `from . import agent` 语句
- `agent.py` 定义 agent 实例,必须包含 `root_agent=...` 全局变量导出

## 持续交付

VeADK 内置了[火山引擎持续交付](https://www.volcengine.com/product/cp)产品来便捷您的部署与持续交付。结合[火山引擎镜像仓库](https://www.volcengine.com/product/cr)产品,能够通过镜像将您的项目持续交付到火山引擎 FaaS 服务。

> 通过容器部署到云上是最佳实践。

使用命令`veadk pipeline`来连结您的代码仓库与火山引擎镜像仓库、持续交付服务。命令的主要工作流程:

1. 帮助您在 VeFaaS 上创建一个含有模板镜像(Simple FastAPI)的镜像函数
2. 将持续交付服务绑定至您的 Github 仓库与创建好的 VeFaaS 函数

随后,您可以在您的 Github 仓库中进行您的第一次提交,您的仓库项目将会被自动:

1. 打包为镜像,
2. 推送至您的镜像仓库
3. 构建部署到 VeFaaS 函数中

命令`veadk pipeline`参数:

| 参数 | 说明 | 默认值 / 必填 |
|------|------|---------------|
| `--github-url` | Github 仓库 URL | **必填** |
| `--github-branch` | Github 项目的分支 | **必填** |
| `--veadk-version` | VeADK 版本,可选值:`preview`(主分支)、`latest`(最新稳定版)、`x.x.x`(具体版本号) | 当前版本号 |
| `--github-token` | Github Token,用于管理项目 | **必填** |
| `--volcengine-access-key` | 火山引擎 Access Key | 使用环境变量 `VOLCENGINE_ACCESS_KEY` |
| `--volcengine-secret-key` | 火山引擎 Secret Key | 使用环境变量 `VOLCENGINE_SECRET_KEY` |
| `--region` | 火山引擎产品区域 | `cn-beijing` |
| `--cr-instance-name` | 火山引擎容器镜像仓库实例名 | `veadk-user-instance` |
| `--cr-namespace-name` | 火山引擎容器镜像仓库命名空间 | `veadk-user-namespace` |
| `--cr-repo-name` | 火山引擎容器镜像仓库 Repo 名称 | `veadk-user-repo` |
| `--vefaas-function-id` | 火山引擎 FaaS 函数 ID(要求为镜像函数),如未设置,将自动创建新函数 | - |

**注意:**启动命令的目录中请提供 `config.yaml` 文件来将您的环境变量记录到云上。
105 changes: 59 additions & 46 deletions veadk/cli/cli_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@
import warnings

import click
from veadk.version import VERSION

from veadk.config import getenv
from veadk.integrations.ve_code_pipeline.ve_code_pipeline import VeCodePipeline
from veadk.integrations.ve_faas.ve_faas import VeFaaS
from veadk.integrations.ve_cr.ve_cr import VeCR
from veadk.consts import (
DEFAULT_CR_INSTANCE_NAME,
DEFAULT_CR_NAMESPACE_NAME,
DEFAULT_CR_REPO_NAME,
)
from veadk.integrations.ve_code_pipeline.ve_code_pipeline import VeCodePipeline
from veadk.integrations.ve_cr.ve_cr import VeCR
from veadk.integrations.ve_faas.ve_faas import VeFaaS
from veadk.utils.logger import get_logger
from veadk.version import VERSION

logger = get_logger(__name__)


warnings.filterwarnings(
"ignore", category=UserWarning, module="pydantic._internal._fields"
Expand Down Expand Up @@ -65,9 +70,9 @@ def _create_cr(volcengine_settings: dict[str, str], cr_settings: dict[str, str])

@click.command()
@click.option(
"--base-image-tag",
required=True,
help=f"Base VeADK image tag can be 'preview', 'latest', or a VeADK version (e.g., {VERSION})",
"--veadk-version",
default=VERSION,
help=f"Base VeADK image tag can be 'preview', 'latest', or a specific VeADK version (e.g., {VERSION})",
)
@click.option(
"--github-url",
Expand All @@ -76,104 +81,98 @@ def _create_cr(volcengine_settings: dict[str, str], cr_settings: dict[str, str])
)
@click.option(
"--github-branch",
default="main",
help="The github branch of your project, default is main",
required=True,
help="The github branch of your project",
)
@click.option(
"--github-token",
required=True,
help="The github token to manage your project",
)
@click.option(
"--access-key",
default=getenv("VOLCENGINE_ACCESS_KEY"),
"--volcengine-access-key",
default=None,
help="Volcengine access key, if not set, will use the value of environment variable VOLCENGINE_ACCESS_KEY",
)
@click.option(
"--secret-key",
default=getenv("VOLCENGINE_SECRET_KEY"),
"--volcengine-secret-key",
default=None,
help="Volcengine secret key, if not set, will use the value of environment variable VOLCENGINE_SECRET_KEY",
)
@click.option(
"--region",
default="cn-beijing",
help="Volcengine region, default is cn-beijing",
help="Region for Volcengine VeFaaS, CR, and Pipeline. Default is cn-beijing",
)
@click.option(
"--cr-instance-name",
default=DEFAULT_CR_INSTANCE_NAME,
help="Container Registry instance name, default is veadk-user-instance",
help="Volcengine Container Registry instance name, default is veadk-user-instance",
)
@click.option(
"--cr-namespace-name",
default=DEFAULT_CR_NAMESPACE_NAME,
help="Container Registry namespace name, default is veadk-user-namespace",
help="Volcengine Container Registry namespace name, default is veadk-user-namespace",
)
@click.option(
"--cr-repo-name",
default=DEFAULT_CR_REPO_NAME,
help="Container Registry repo name, default is veadk-user-repo",
)
@click.option(
"--cr-region",
default="cn-beijing",
help="Container Registry region, default is cn-beijing",
help="Volcengine Container Registry repo name, default is veadk-user-repo",
)
@click.option(
"--function-id",
"--vefaas-function-id",
default=None,
help="Volcengine FaaS function ID, if not set, a new function will be created automatically",
)
def pipeline(
base_image_tag: str,
veadk_version: str,
github_url: str,
github_branch: str,
github_token: str,
access_key: str,
secret_key: str,
volcengine_access_key: str,
volcengine_secret_key: str,
region: str,
cr_instance_name: str,
cr_namespace_name: str,
cr_repo_name: str,
cr_region: str,
function_id: str,
vefaas_function_id: str,
) -> None:
"""Integrate a veadk project to volcengine pipeline for CI/CD"""

click.echo(
"Welcome use VeADK to integrate your project to volcengine pipeline for CI/CD."
)

if not volcengine_access_key:
volcengine_access_key = getenv("VOLCENGINE_ACCESS_KEY")
if not volcengine_secret_key:
volcengine_secret_key = getenv("VOLCENGINE_SECRET_KEY")

volcengine_settings = {
"volcengine_access_key": access_key,
"volcengine_secret_key": secret_key,
"volcengine_access_key": volcengine_access_key,
"volcengine_secret_key": volcengine_secret_key,
"volcengine_region": region,
}

cr_settings = {
"cr_domain": f"{cr_instance_name}-{cr_region}.cr.volces.com",
"cr_domain": f"{cr_instance_name}-{region}.cr.volces.com",
"cr_instance_name": cr_instance_name,
"cr_namespace_name": cr_namespace_name,
"cr_repo_name": cr_repo_name,
"cr_region": cr_region,
"cr_region": region,
}

_create_cr(volcengine_settings, cr_settings)

click.echo("Using the following CR configuration:")
click.echo(f"Container Registry domain: {cr_settings['cr_domain']}")
click.echo(f"Container Registry namespace name: {cr_settings['cr_namespace_name']}")
click.echo(f"Container Registry region: {cr_settings['cr_region']}")
click.echo(f"Container Registry instance name: {cr_settings['cr_instance_name']}")
click.echo(f"Container Registry repo name: {cr_settings['cr_repo_name']}")

if not function_id:
if not vefaas_function_id:
click.echo(
"No Function ID specified. The system will create one automatically. Please specify a function name:"
"No Function ID specified. VeADK will create one automatically. Please specify a function name:"
)
function_name = click.prompt(
"Function name", default="veadk-function", show_default=False
"Function name", default="veadk-image-function", show_default=False
)

_create_cr(volcengine_settings, cr_settings)

if not vefaas_function_id:
vefaas_client = VeFaaS(
access_key=volcengine_settings["volcengine_access_key"],
secret_key=volcengine_settings["volcengine_secret_key"],
Expand All @@ -184,15 +183,29 @@ def pipeline(
image="veadk-cn-beijing.cr.volces.com/veadk/simple-fastapi:0.1",
registry_name=cr_settings["cr_instance_name"],
)
click.echo(f"Created function {function_name} with ID: {function_id}")
logger.debug(f"Created function {function_name} with ID: {function_id}")

client = VeCodePipeline(
volcengine_access_key=volcengine_settings["volcengine_access_key"],
volcengine_secret_key=volcengine_settings["volcengine_secret_key"],
region=volcengine_settings["volcengine_region"],
)

click.echo("=====================================================")
click.echo("Using the following configuration to create pipeline:")
click.echo(f"Use VeADK version: {veadk_version}")
click.echo(f"Github url: {github_url}")
click.echo(f"Github branch: {github_branch}")
click.echo(f"VeFaaS function name: {function_name}")
click.echo(f"VeFaaS function ID: {function_id}")
click.echo(f"Container Registry domain: {cr_settings['cr_domain']}")
click.echo(f"Container Registry namespace name: {cr_settings['cr_namespace_name']}")
click.echo(f"Container Registry region: {region}")
click.echo(f"Container Registry instance name: {cr_settings['cr_instance_name']}")
click.echo(f"Container Registry repo name: {cr_settings['cr_repo_name']}")

client.deploy(
base_image_tag=base_image_tag,
base_image_tag=veadk_version,
github_url=github_url,
github_branch=github_branch,
github_token=github_token,
Expand Down
6 changes: 3 additions & 3 deletions veadk/integrations/ve_code_pipeline/ve_code_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from string import Template

import requests
from veadk.config import getenv

from veadk.utils.logger import get_logger
from veadk.utils.misc import formatted_timestamp
from veadk.utils.volcengine_sign import ve_request
Expand Down Expand Up @@ -109,8 +109,8 @@ def get_dockerfile(tag: str = "latest") -> str:
class VeCodePipeline:
def __init__(
self,
volcengine_access_key: str = getenv("VOLCENGINE_ACCESS_KEY"),
volcengine_secret_key: str = getenv("VOLCENGINE_SECRET_KEY"),
volcengine_access_key: str,
volcengine_secret_key: str,
region: str = "cn-beijing",
) -> None:
self.volcengine_access_key = volcengine_access_key
Expand Down
25 changes: 20 additions & 5 deletions veadk/integrations/ve_cr/ve_cr.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from veadk.utils.volcengine_sign import ve_request
from veadk.utils.logger import get_logger
import time

from veadk.consts import (
DEFAULT_CR_INSTANCE_NAME,
DEFAULT_CR_NAMESPACE_NAME,
DEFAULT_CR_REPO_NAME,
)
import time
from veadk.utils.logger import get_logger
from veadk.utils.volcengine_sign import ve_request

logger = get_logger(__name__)

Expand Down Expand Up @@ -63,6 +64,20 @@ def _create_instance(self, instance_name: str = DEFAULT_CR_INSTANCE_NAME) -> str
)
logger.debug(f"create cr instance {instance_name}: {response}")

if "Error" in response["ResponseMetadata"]:
error_code = response["ResponseMetadata"]["Error"]["Code"]
error_message = response["ResponseMetadata"]["Error"]["Message"]
if error_code == "AlreadyExists.Registry":
logger.debug(f"cr instance {instance_name} already exists")
return instance_name
else:
logger.error(
f"Error create cr instance {instance_name}: {error_code} {error_message}"
)
raise ValueError(
f"Error create cr instance {instance_name}: {error_code} {error_message}"
)

while True:
status = self._check_instance(instance_name)
if status == "Running":
Expand All @@ -71,7 +86,7 @@ def _create_instance(self, instance_name: str = DEFAULT_CR_INSTANCE_NAME) -> str
raise ValueError(f"cr instance {instance_name} create failed")
else:
logger.debug(f"cr instance status: {status}")
time.sleep(5)
time.sleep(30)

return instance_name

Expand Down Expand Up @@ -142,7 +157,7 @@ def _create_namespace(
error_code = response["ResponseMetadata"]["Error"]["Code"]
error_message = response["ResponseMetadata"]["Error"]["Message"]
if error_code == "AlreadyExists.Namespace":
logger.debug(f"cr namespace {namespace_name} already exists")
logger.warning(f"cr namespace {namespace_name} already exists")
return namespace_name
else:
logger.error(
Expand Down
Loading