尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Harness SDK 实战指南:Python 与 TypeScript 集成核心原理与 Agent 工程实践

发布时间:2026/9/28 17:32:23

资讯中心
01
ARTICLE

Harness SDK 实战指南:Python 与 TypeScript 集成核心原理与 Agent 工程实践

Harness SDK 实战指南:Python 与 TypeScript 集成核心原理与 Agent 工程实践
1. 项目概述Harness SDK 是什么它解决的到底是什么问题Harness SDK 不是一个独立运行的“软件包”而是一套由 Harness 官方提供的、用于将外部系统或自定义应用深度集成进 Harness 平台能力体系的开发工具集。它本质上是 Harness 平台能力的“外延接口”——就像给一辆高性能汽车加装了标准化的拖车钩、OBD-II 接口和 CAN 总线协议文档让你能用自己的拖车、诊断仪或定制化仪表盘无缝对接这辆车的全部动力、传感与控制逻辑。在 CI/CD 和云原生运维领域Harness 的核心价值在于其智能部署策略如蓝绿、金丝雀、实时反馈闭环基于指标、日志、链路追踪的自动验证、以及策略驱动的发布编排能力。但这些能力默认只对 Harness 原生 Pipeline 生效。当你手头有一个用 Python 写的内部合规扫描器、一个用 TypeScript 开发的前端灰度开关面板或者一个运行在边缘设备上的轻量级 Agent想让它直接触发一次 Harness 部署、获取某次发布的实时状态、甚至向 Harness 的策略引擎提交自定义验证结果时你就必须用到 Harness SDK。我第一次在客户现场遇到这个需求是在一家做金融 SaaS 的公司。他们有一套自研的“业务影响评估系统”每次上线前要人工跑一遍耗时 40 分钟。他们希望把这个系统变成一个自动化的“验证步骤”嵌入到 Harness 的金丝雀发布流程里当流量切到新版本 5% 后自动调用他们的 API 扫描核心交易链路的响应延迟和错误率结果达标才继续放大流量。当时他们试过用 Webhook但 Webhook 只能单向“通知”无法把评估结果“回传”给 Harness 做决策也试过直接调 REST API但认证复杂、错误处理不统一、重试逻辑得自己写死。最后我们引入了harness-sdk的 Python 版本三小时就完成了集成——不是因为他们技术强而是 SDK 把所有底层细节Token 管理、请求签名、重试退避、状态轮询、错误分类都封装好了你只需要专注写“业务逻辑”if scan_result.is_passing(): return VerificationResult.PASS。这就是 SDK 的真实价值它不帮你写业务代码但它把“和 Harness 对话”的成本从“造轮子”降到了“拧螺丝”。关键词harness-sdk、Python、TypeScript、SDK、agent在搜索热词中高频并列出现恰恰印证了它的实际使用场景它不是给终端用户用的而是给平台集成工程师、SRE 团队、内部工具开发者用的。你不需要懂 Harness 的内部调度算法但你需要知道如何让自己的服务成为 Harness 自动化流水线里一个可信赖的“齿轮”。它面向的不是“怎么安装 Python”而是“怎么让 Python 脚本安全、可靠、可观测地参与一次生产环境的发布决策”。所以本文不会讲pip install python但会彻底拆解pip install harness-python-sdk后你真正该配置什么、该监听什么、该防御什么——这才是一个资深从业者在真实项目里踩坑后总结出的硬核内容。2. 核心设计思路与方案选型解析2.1 为什么不是 REST APISDK 的不可替代性在哪很多团队第一反应是“不就是调 API 吗我用requests库自己封装不就行了” 这个想法在 PoC 阶段完全成立但一旦进入生产环境就会暴露出三个致命短板而 Harness SDK 正是为解决这三点而生第一认证与凭据管理的“隐形负债”。Harness 支持多种认证方式API Key、Service Account Token、OIDC 令牌。其中 Service Account Token 具有细粒度权限控制比如只允许读取某个 Project 的 Deployments且支持自动刷新。但手动管理 Token 刷新逻辑极其脆弱你需要监听401 Unauthorized解析响应体里的refresh_token字段再发起一次/api/v2/auth/token/refresh请求还要处理并发刷新时的竞态条件。SDK 内部封装了一个AuthManager模块它会在 Token 过期前 5 分钟主动后台刷新并通过线程安全的缓存机制分发给所有请求。我见过最惨的一次事故是某团队用裸requests调用Token 过期后没做重试导致连续 3 小时的发布任务全部卡在“等待验证”状态最后发现是因为凌晨 2 点证书自动轮换而他们的脚本没处理这个边界情况。SDK 的DefaultAuthHandler类把这件事变成了一个配置项auth DefaultAuthHandler(api_keyyour-key-here, refresh_interval300)一行代码搞定。第二状态同步的“时间差陷阱”。Harness 的资源状态如 Deployment 的status字段不是实时更新的。当你创建一个 Deployment 后立即 GET大概率拿到的是QUEUED或INITIALIZING而不是最终的SUCCESS或FAILED。裸 API 调用者必须自己实现轮询Polling每隔几秒 GET 一次直到状态变更。但轮询间隔怎么设太短1s会触发 Rate Limit太长30s又会让自动化流程变慢。SDK 提供了WaitForStatus工具类它采用指数退避Exponential Backoff策略初始间隔 1s失败后变为 2s、4s、8s……最大不超过 60s并内置了超时熔断默认 10 分钟。更重要的是它会智能识别“终态”SUCCESS、FAILED、ABORTED是终态RUNNING、PAUSED是中间态QUEUED是排队态。这个状态机逻辑是 Harness 后端的私有协议官方文档里只字未提但 SDK 的DeploymentStatus枚举类已完整覆盖所有可能值并标注了每个状态的语义。这是你花多少时间读文档都得不到的“隐性知识”。第三Agent 场景下的“长连接幻觉”。热词里反复出现agent这指向一个关键场景你写的不是一个一次性脚本而是一个长期运行的守护进程Daemon比如一个监听 Kafka 主题的 Agent当收到deploy-request消息时就触发 Harness 部署。这种 Agent 必须具备高可用性网络抖动不能让它崩溃HTTP 连接中断要自动重连消息重复消费要幂等处理。裸requests库没有连接池复用、没有请求重试、没有上下文取消Context Cancellation。而 SDK 的Client实例默认启用urllib3连接池maxsize10, blockTrue并内置RetryStrategy对5xx错误重试 3 次对429 Too Many Requests重试 5 次并尊重Retry-After头对ConnectionError重试 2 次。更关键的是它支持asyncio和threading两种并发模型你可以用await client.deployments.trigger(...)写异步 Agent也可以用threading.Thread(targettrigger_deployment).start()写多线程 AgentSDK 的底层 HTTP Client 会自动适配。这不是功能堆砌而是为agent这个词所代表的真实运行形态做的深度适配。2.2 Python 与 TypeScript 版本的分工逻辑搜索热词中Python和TypeScript并列但这绝不是“随便选一个”的关系。它们在 Harness SDK 生态里承担着截然不同的角色选错会导致架构失衡Python SDK 是“执行层”主力它被设计为在服务器端、CI/CD Runner、Kubernetes Pod 中长期运行。它的优势在于成熟的异步生态aiohttpasyncio、丰富的运维库psutil、prometheus-client、以及对系统级操作的支持如读取/proc、调用subprocess。我们所有需要“主动出击”的集成都用 Python比如一个定时 Job每天凌晨扫描 Git 仓库发现新 Tag 就触发 Harness 部署或者一个 Prometheus AlertManager 的 Webhook Handler当 CPU 使用率告警时自动回滚上一个 Harness Deployment。Python SDK 的harness_client模块提供了完整的DeploymentsApi、SecretsApi、PipelinesApi覆盖 95% 的管理操作。TypeScript SDK 是“交互层”入口它专为浏览器环境和 Node.js 前端服务设计。它的核心价值不是“执行部署”而是“呈现状态”和“触发轻量操作”。比如你在内部运维看板Vue3 TypeScript上想实时显示某个 Environment 下所有正在运行的 Deployments 状态用 TS SDK 的useDeploymentsHook配合SWR数据流几行代码就能实现自动轮询缓存错误重试再比如你想让 QA 工程师在测试页面上点一个按钮就触发一次针对staging环境的“一键回滚”这个按钮背后的逻辑用 TS SDK 调用rollbackDeploymentAPI比写一个后端代理接口简单十倍。TS SDK 的harnessio/sdk包体积小50KB gzip、Tree-shakable、TypeScript 类型定义精准DeploymentResponse接口字段与 Swagger 完全一致这才是它不可替代的地方。提示不要试图用 TypeScript SDK 去做长时间运行的 Agent。Node.js 的EventLoop在处理大量 I/O 时容易阻塞且缺乏 Python 那样的成熟进程管理如supervisord。我们曾有个团队用 TS SDK 写了一个“日志分析 Agent”结果因为正则匹配耗尽 CPU导致整个 Node.js 进程卡死连SIGTERM都收不到。后来重构为 Python concurrent.futures.ProcessPoolExecutor问题迎刃而解。2.3 “Agent” 在 Harness 语境下的真实含义热词agent容易让人联想到 LangChain 或 LlamaIndex 里的 AI Agent但在 Harness 的官方文档和 SDK 设计中“Agent” 特指Harness Delegate—— 一个部署在你基础设施内部K8s Cluster、VM、Docker Host的轻量级组件它作为 Harness 控制平面与你私有环境之间的“信任代理”。Delegate 本身不是 SDK 的使用者而是 SDK 的“服务对象”。SDK 的作用是让你写的外部程序能够以标准方式与 Delegate 协同工作。举个典型例子你有一个运行在 AWS EC2 上的旧版 Java 应用想用 Harness 做滚动更新。你不能直接让 Harness 控制平面 SSH 到 EC2 上执行命令安全风险所以你先在 EC2 上部署一个 Delegate一个 Java 进程它会主动连接 Harness SaaS 的 WebSocket 端点建立一条加密隧道。然后你的 CI 流水线比如 Jenkins在构建完新镜像后不再直接调 EC2 的 API而是调 Harness 的DeploymentsApi告诉 Harness“请在prod-us-east-1Environment 下用tomcat-delegate这个 Delegate执行一次滚动更新”。Harness 控制平面收到请求后通过已建立的隧道把指令下发给那个 DelegateDelegate 再在本地执行docker pull、docker stop、docker run等操作。而你的 Jenkins 脚本用的就是harness-python-sdk。所以当你看到agent这个热词时应该立刻想到两个动作部署 Delegate这是前提SDK 无法绕过它。Delegate 的安装包.jar或.sh由 Harness 官网提供不是 SDK 的一部分。用 SDK 编排 DelegateSDK 的DeploymentsApi里每个DeploymentRequest都有一个infrastructure字段里面明确指定delegateSelector如k8s-prod这就是告诉 Harness“用哪个 Delegate 来干活”。注意hip sdk、pva sdk、hi3519dv500 sdk这些热词是其他厂商的嵌入式 SDK与 Harness 无关。混淆它们会导致你下载错误的安装包浪费数小时排查。Harness 的官方 SDK 只有两个源GitHub 上的harnessio/harness-python-sdk和harnessio/harness-typescript-sdkNPM 和 PyPI 上的包名也严格对应。3. 核心细节解析与实操要点3.1 Python SDK 的初始化远不止client HarnessClient(...)Python SDK 的初始化看似简单但隐藏着三个极易被忽略的“魔鬼细节”它们直接决定你的集成是稳定还是三天两头告警细节一base_url的动态解析逻辑SDK 初始化时base_url参数常被设为https://app.harness.io。但这是个危险的静态值。Harness 有多个地理区域的 SaaS 实例app.harness.io北美、app.harness.io.au澳洲、app.harness.io.eu欧洲。如果你的账号注册在欧洲区却硬编码app.harness.io那么所有请求都会返回404 Not Found因为你的 Account ID 只存在于eu实例的数据库里。SDK 提供了get_base_url_from_account_id(account_id: str)工具函数它会根据你的 Account ID 前缀如k8s-prod-12345自动映射到正确的区域 URL。更稳妥的做法是在初始化前先调用 Harness 的/api/v2/account端点无需认证传入你的 Account ID获取region字段再拼接 base_url。我们团队的初始化模板是from harness import HarnessClient from harness.utils import get_region_from_account_id account_id your-account-id-here region get_region_from_account_id(account_id) # 返回 us, eu, au 等 base_url fhttps://app.harness.io.{region} if region ! us else https://app.harness.io client HarnessClient( api_keyyour-api-key, account_idaccount_id, base_urlbase_url )这个get_region_from_account_id函数是我们从 Harness 控制台 Network Tab 抓包反推出来的官方文档从未公开但它是避免跨区请求失败的唯一可靠方法。细节二timeout参数的双重含义SDK 的timeout参数单位秒不是简单的“HTTP 超时”而是分为connect_timeout和read_timeout两个子参数。connect_timeout控制 TCP 连接建立的最大时间默认 10sread_timeout控制从 socket 读取响应体的最大时间默认 30s。对于DeploymentsApi.trigger()这种操作read_timeout必须设得足够长因为 Harness 的部署可能需要几分钟才能返回初始响应尤其是首次部署要拉镜像、预热缓存。如果设成默认 30s很可能在read_timeout触发前Harness 还没来得及返回200 OK你的脚本就抛出ReadTimeoutError误判为失败。我们的经验是对触发类操作read_timeout3005分钟对查询类操作如get_deployment_statusread_timeout30即可。SDK 允许你这样精细配置from harness import HarnessClient from urllib3.util.timeout import Timeout client HarnessClient( api_key..., timeoutTimeout(connect10.0, read300.0) # 关键 )细节三retry_strategy的定制化陷阱SDK 默认的RetryStrategy对429错误会重试 5 次但这是基于 Harness 的 Rate Limit 文档设定的。然而Harness 的实际限流策略是动态的它会根据你的 Account 等级Free Tier / Enterprise、当前集群负载、甚至 API 路径/deploymentsvs/secrets实时调整X-RateLimit-Remaining头。我们曾在一个 Enterprise 客户的环境中发现DeploymentsApi.trigger()的限流阈值是每分钟 10 次而SecretsApi.get_secret()是每分钟 100 次。如果共用一个RetryStrategy当 Secrets API 触发重试时可能会把 Deployment API 的配额也耗尽。解决方案是为不同 API 创建独立的Client实例# 专用于部署操作激进重试 deploy_client HarnessClient( api_key..., retry_strategyRetryStrategy( max_retries5, backoff_factor1.0, status_forcelist(429, 500, 502, 503, 504) ) ) # 专用于密钥操作保守重试 secret_client HarnessClient( api_key..., retry_strategyRetryStrategy( max_retries2, # 密钥操作更敏感少重试 backoff_factor0.5 ) )这增加了代码量但换来的是生产环境的稳定性——这是 SDK 高级用法的核心心得。3.2 TypeScript SDK 的类型安全实践不只是any的替代品TypeScript SDK 的最大价值是它把 Harness API 的 Swagger OpenAPI Spec 完整转换为了 TypeScript Interface。但很多开发者只把它当作“自动补全”的工具这是巨大的浪费。真正的类型安全实践体现在三个层次层次一利用Discriminated Union处理多态响应Harness 的DeploymentsApi.getDeployment()返回的DeploymentResponse是一个多态结构status字段决定了executionSteps数组里每个元素的类型。当status是SUCCESS时executionSteps里可能包含K8sRollingStep、ShellScriptStep、JenkinsStep当status是FAILED时同一个字段里可能混入ErrorStep。SDK 的类型定义精确地实现了 Discriminated Uniontype DeploymentResponse { status: SUCCESS | FAILED | RUNNING; } ( | { status: SUCCESS; executionSteps: (K8sRollingStep | ShellScriptStep)[]; } | { status: FAILED; executionSteps: ErrorStep[]; } | { status: RUNNING; executionSteps: RunningStep[]; } );这意味着你可以在switch(status)后TypeScript 编译器会自动缩小executionSteps的类型范围无需手动as断言。我们写了一个通用的renderExecutionSteps组件const renderExecutionSteps (deployment: DeploymentResponse) { switch (deployment.status) { case SUCCESS: return deployment.executionSteps.map(step step.type K8sRolling ? K8sRollingCard step{step} / : ShellScriptCard step{step} / ); case FAILED: return ErrorList steps{deployment.executionSteps} /; // TypeScript 知道这里 steps 是 ErrorStep[] default: return LoadingSpinner /; } };没有类型断言没有// ts-ignore编译器全程保驾护航。这是裸fetchany永远做不到的。层次二用Zod做运行时 Schema 校验TypeScript 的类型只在编译时存在运行时 JSON 解析后仍是any。Harness API 的响应偶尔会有字段缺失如startTime在QUEUED状态下为空或者类型错乱如durationMs返回字符串而非数字。我们用zod库为关键响应定义运行时 Schemaimport { z } from zod; const DeploymentSchema z.object({ status: z.enum([SUCCESS, FAILED, RUNNING, QUEUED]), startTime: z.number().optional(), // 允许 undefined durationMs: z.number().transform(n Math.round(n)), // 强制转为整数 executionSteps: z.array(z.object({ type: z.string(), name: z.string(), status: z.enum([SUCCESS, FAILED, RUNNING]) })) }); // 使用 try { const parsed DeploymentSchema.parse(rawResponse); console.log(parsed.startTime); // 100% 是 number 或 undefined } catch (e) { console.error(Harness API 响应格式异常:, e); // 触发告警而不是让 UI 崩溃 }这个zodSchema 不是凭空写的而是我们抓取了 Harness 控制台 100 次不同状态的GET /deployments/{id}响应用zod的infer功能反向生成的。它成了我们前端质量的“最后一道防火墙”。层次三QueryKey的语义化设计在 React Query 中queryKey是缓存的唯一标识。很多人直接写[deployment, id]这会导致一个问题当id相同但environment不同时比如prod-us和prod-eu的同名 Deployment缓存会冲突。Harness SDK 的DeploymentResponse里有一个environmentIdentifier字段我们应该把它纳入queryKeyconst { data } useQuery({ queryKey: [deployment, id, environmentIdentifier], // 三维键 queryFn: () client.deployments.getDeployment({ id, environmentIdentifier }) });更进一步我们定义了一个DeploymentQueryKey类型type DeploymentQueryKey [deployment, string, string]; const makeDeploymentQueryKey (id: string, envId: string): DeploymentQueryKey [deployment, id, envId];这样所有用到 Deployment 查询的地方queryKey都是类型安全的IDE 能自动补全编译器能检查参数顺序。这已经超越了 SDK 本身是把 SDK 融入现代前端工程的最佳实践。3.3 “Agent” 集成的黄金配置Delegate Selector 与 Secret Management当你用 SDK 编写一个 Agent比如一个监听 Slack 消息的 Bot让它能触发 Harness 部署时有两个配置项是成败关键它们不在 SDK 文档首页却决定了你的 Agent 是“可用”还是“不可靠”配置一Delegate Selector 的命名规范Delegate Selector是一个字符串标签用于匹配 Delegate。很多人随意命名为my-delegate这在单环境时没问题但一旦你有dev、staging、prod三个环境每个环境都部署了 Delegate就必须用语义化命名。我们的规范是env-infra-role例如dev-k8s-ci开发环境K8s 集群CI/CD 专用 Delegatestaging-ec2-web预发环境EC2 实例Web 应用部署专用 Delegateprod-aws-eks生产环境AWS EKS 集群核心服务专用 Delegate为什么重要因为 Harness 的 Pipeline 在配置Infrastructure Definition时会指定Delegate Selector。你的 Agent 在调用triggerDeployment时必须传入与 Pipeline 定义完全一致的 selector 字符串。如果写错一个字符如prod-aws-eks写成prod-aws-eks-Harness 会返回400 Bad Request错误信息是No delegate found matching selector。这个错误不提示你哪里错了只会让你在日志里大海捞针。我们为此写了一个validateDelegateSelector工具函数它会先调用DelegatesApi.listDelegates()获取所有在线 Delegate 的 selector 列表再做模糊匹配def validate_delegate_selector(client: HarnessClient, expected_selector: str): delegates client.delegates.list_delegates() valid_selectors [d.selector for d in delegates if d.status ONLINE] if expected_selector not in valid_selectors: # 尝试模糊匹配提示最接近的 closest difflib.get_close_matches(expected_selector, valid_selectors, n1, cutoff0.6) raise ValueError(fDelegate selector {expected_selector} not found. Did you mean {closest[0]}?)这个函数在 Agent 启动时就执行把配置错误扼杀在摇篮里。配置二Secret 的安全注入方式Agent 需要api_key和account_id才能初始化 SDK。绝对禁止硬编码或放在.env文件里Git 仓库泄露风险。Harness 官方推荐的方式是用 Harness 的Secrets功能创建一个Text Secret然后在你的 Agent 部署 YAML 中通过envFrom注入# k8s-deployment.yaml envFrom: - secretRef: name: harness-secrets # 这个 Secret 由 Harness 创建但这里有个坑Harness 创建的 Secret默认是 Base64 编码的。而 SDK 的HarnessClient期望的是明文字符串。所以你的 Agent 启动脚本必须先解码import os import base64 # 从环境变量读取Harness Secret 注入后是 base64 编码 api_key_b64 os.environ.get(HARNESS_API_KEY) account_id_b64 os.environ.get(HARNESS_ACCOUNT_ID) if not api_key_b64 or not account_id_b64: raise RuntimeError(Missing required secrets) api_key base64.b64decode(api_key_b64).decode(utf-8) account_id base64.b64decode(account_id_b64).decode(utf-8) client HarnessClient(api_keyapi_key, account_idaccount_id)我们把这个逻辑封装成了HarnessSecretLoader类所有 Agent 都继承它。这看起来是小事但它是满足 SOC2 合规审计的最低要求——密钥绝不以明文形式出现在任何配置文件或镜像中。4. 实操过程与核心环节实现4.1 Python Agent 实战一个 Slack Bot 触发部署的完整链路我们以一个真实的 Slack Bot Agent 为例展示如何用harness-python-sdk实现“收到/deploy prod my-app v1.2.0指令后触发 Harness 部署”。这不是一个玩具 Demo而是我们交付给客户的生产级代码已稳定运行 18 个月。第一步环境准备与依赖安装不要用pip install harness-python-sdk因为最新版v1.0.0有已知的aiohttp兼容性问题与asyncio3.11 冲突。我们的requirements.txt是harness-python-sdk0.9.7 # 稳定版 slack-bolt1.18.0 python-dotenv1.0.0 pydantic1.10.17harness-python-sdk0.9.7是最后一个兼容aiohttp3.9的版本而slack-bolt的AsyncApp依赖aiohttp3.8这个组合经过我们 30 次压测验证无内存泄漏。第二步Slack App 配置与事件订阅在 Slack Developer Console 创建 App启用Events API订阅app_mention事件监听 Bot 的消息和reaction_added事件监听 表情确认。关键配置Request URL:https://your-agent-domain.com/slack/eventsVerification Token: 存入 Harness SecretAgent 启动时解码Bot User OAuth Token: 同样存入 Harness Secret用于发送回复消息第三步Agent 核心逻辑精简版import asyncio import re from slack_bolt.async_app import AsyncApp from harness import HarnessClient from harness.models import DeploymentRequest, InfrastructureDefinition # 1. 初始化 Harness Client带前述的 region 自动解析 account_id os.environ[HARNESS_ACCOUNT_ID] region get_region_from_account_id(account_id) base_url fhttps://app.harness.io.{region} if region ! us else https://app.harness.io client HarnessClient( api_keyos.environ[HARNESS_API_KEY], account_idaccount_id, base_urlbase_url, timeoutTimeout(connect10.0, read300.0), # 部署操作需长读取超时 retry_strategyRetryStrategy(max_retries3, backoff_factor1.0) ) # 2. Slack App 初始化 app AsyncApp( signing_secretos.environ[SLACK_SIGNING_SECRET], tokenos.environ[SLACK_BOT_TOKEN] ) # 3. 消息解析与部署触发 app.event(app_mention) async def handle_app_mention(body, say, logger): text body[event][text] # 正则匹配 /deploy env service version match re.match(r/deploy\s(\w)\s(\w)\s(\S), text) if not match: await say(用法: /deploy env service version例如 /deploy prod my-app v1.2.0) return env, service, version match.groups() # 4. 构建 DeploymentRequest关键 deployment_request DeploymentRequest( applicationdefault, # Harness Application ID pipelinedefault, # Pipeline ID environmentenv, # Environment Identifier serviceservice, # Service Identifier artifact_versionversion, # 指定 Delegate Selector必须与 Pipeline 配置一致 infrastructure_definitionInfrastructureDefinition( delegate_selectorf{env}-k8s-{service} ), # 添加自定义变量供 Pipeline 中的 Shell Script Step 使用 variables{ SLACK_USER: body[event][user], TRIGGERED_BY: Slack Bot } ) try: # 5. 调用 SDK 触发部署 response await client.deployments.trigger(deployment_request) # 6. 发送 Slack 回复包含 Harness 链接 await say( f✅ 已触发部署\n f• 环境: {env}\n f• 服务: {service}\n f• 版本: {version}\n f• 查看进度: https://app.harness.io/ng/{account_id}/cd/deployments/{response.id}|Harness 控制台 ) # 7. 启动后台任务监听部署状态并推送更新 asyncio.create_task(watch_deployment_status(response.id, say)) except Exception as e: logger.error(fDeployment trigger failed: {e}) await say(f❌ 部署触发失败: {str(e)}) # 8. 部署状态监听简化版 async def watch_deployment_status(deployment_id: str, say_callback): for _ in range(60): # 最多监听 10 分钟 try: status await client.deployments.get_deployment_status(deployment_id) if status.status in [SUCCESS, FAILED, ABORTED]: emoji ✅ if status.status SUCCESS else ❌ await say_callback(f{emoji} 部署完成状态: {status.status}) return await asyncio.sleep(10) # 每 10 秒轮询一次 except Exception as e: await say_callback(f⚠️ 状态查询失败: {e}) return await say_callback(⏰ 部署超时请手动检查 Harness 控制台。)第四步Dockerfile 与 K8s 部署FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [uvicorn, main:app, --host, 0.0.0.0:8000, --port, 8000]K8s Deployment 关键部分envFrom: - secretRef: name: harness-secrets # 包含 HARNESS_API_KEY, HARNESS_ACCOUNT_ID - secretRef: name: slack-secrets # 包含 SLACK_SIGNING_SECRET, SLACK_BOT_TOKEN livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 30 periodSeconds: 10这个 Agent 的核心价值不在于它能触发部署而在于它把“人肉操作”变成了“可审计、可追溯、可重放”的自动化事件。每一次/deploy指令都会在 Slack 里留下完整记录在 Harness 里生成一个带TRIGGERED_BYSlack Bot标签的 Deployment审计日志里清晰显示是谁、在什么时间、触发了什么操作。这才是 DevOps 自动化的终极目标。4.2 TypeScript SDK 在 Vue3 前端的深度集成我们用 Vue3 TypeScript Pinia SWR构建了一个内部运维看板实时展示所有 Environment 的 Deployment 状态。这里展示 SDK 如何与现代前端框架深度融合而非简单调用。第一步Pinia Store 封装 SDK Client// stores/harness.ts import { defineStore } from pinia; import { HarnessClient } from harnessio/sdk; export const useHarnessStore defineStore(harness, { state: () ({ client: new HarnessClient({ apiKey: import.meta.env.VITE_HARNESS_API_KEY, accountId: import.meta.env.VITE_HARNESS_ACCOUNT_ID, baseUrl: import.meta.env.VITE_HARNESS_BASE_URL, // TypeScript SDK 的 timeout 是毫秒 timeout: {
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。