ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Elsa.Slack 本地包证明:从固定源码打包、消费验证到发布单元边界的一体化实践

Elsa.Slack 本地包证明:从固定源码打包、消费验证到发布单元边界的一体化实践 后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载在 Elsa 3 生态中一个连接器模块如 Elsa.Slack能否被安全地当作独立 NuGet 发布单元处理取决于它能否通过源码打包 消费验证 符号校验三层证明。本指南以 slack-package-proof.md 为主体结合 Bounded connector release unit ADR 与仓库内的一体化脚本实现完整讲解本地包证明local package proof的边界定义、复现步骤、防护机制与结果判定读者可以据此在任意机器上复现同一套不发布、可审计、fails-closed 的兼容性证明。背景为什么需要一个本地包证明在 integration-program 总览 中Elsa 3 整合计划的一项关键原则是把源码调试证明与包兼容性证明分开——仅靠 ProjectReference 构建成功不足以证明一个已发布包能在干净消费者中恢复和运行。为此Elsa.Slack被选为第一个有界的独立 NuGet 发布单元其设计决策记录在 ADR: Bounded connector release unit and package proof发布单元 单个Elsa.Slack包 其源码工程 聚焦测试工程 包消费证明不将 Studio 折叠进该单元库存中没有 Slack Studio 伴生包证明的兼容性表述被严格限定为由固定 Extensions 3.8.4 源码构建的Elsa.Slack包可以在其声明的每个目标框架上被公共 Elsa 3.8.4 包家族消费它不声称连接真实 Slack 工作区可用不声称 36 个声明的活动全部通过行为验证也不声称六个Watch*触发器已实现它们当前抛出NotImplementedException。这次运行是纯本地性质从固定的 3.8.4 Extensions 源码打包Elsa.Slack到临时 feed从不发布。发布单元与兼容性边界原文档用一组精确参数划定了本次证明的边界这些参数与仓库中 release-units.json 的清单字段一一对应维度值说明发布单元Elsa.Slackonly只打包这一个包 ID包工程src/modules/communication/Elsa.Slack/Elsa.Slack.csprojExtensions脚本以PROJECT_RELATIVE常量引用聚焦测试test/modules/slack/Elsa.Slack.Tests/Elsa.Slack.Tests.csproj目标net10.0仅针对 Slack 的测试工程包目标框架net8.0、net9.0、net10.0三目标矩阵依赖Elsa3.8.4内部兼容基线、SlackNet0.17.7外部清单中以tested_artifact_dependencies声明源码基线Extensions tag154ba15fb4da85b4bebecfbe43639579cbda1d0dCore tag33181ae3048f628f591a0155b5665a8e4d1bcea2双仓库双提交固定对比工件NuGet 上的公共Elsa.Slack3.8.4SHA-2566df6fd1c3e7558c7c1124fa232879cfa539196fa35a3edd9055cfcc2e0a178e6已发布基线本地证明版本3.8.5-proof.154ba15仅本地 prerelease 身份永不发布本地包 SHA-256ea632344c911f07a5968111df9abd9f9291152ac9cf1f528854d5e374f8bfa8a本次打包产物的实际哈希消费者矩阵两图分离原文档强调两条验证路径必须区分已发布包图released package graph干净的消费者工程先用 NuGet 引用公共Elsa.Slack3.8.4再引用临时本地 feed 中的证明版本。两者都从 NuGet 解析对应的Elsa3.8.4 依赖通过 Elsa 服务提供商注册CreateChannel并在net8.0/net9.0/net10.0三个框架上记录IActivityRegistry描述符的TypeName与Version。源码调试图source-debug graph单独的net10.0消费者使用ProjectReferenceUseProjectReferencestrue构建固定的 Extensions/Core 源码依赖图记录同样的描述符身份并与公共包net10.0的描述符比对。此检查验证发布 tag 上的源码集成但不能替代包消费者检查。从源码看消费者工程由 run_slack_package_proof.py 的 consumer_project() 动态生成Program.cs通过services.AddElsa(elsa elsa.AddActivityCreateChannel())搭建服务registry.RegisterAsync(typeof(CreateChannel))注册活动再用ActivityTypeNameHelper.GenerateTypeName推导类型名并输出ELSA_ACTIVITY_DESCRIPTOR标记行。脚本随后在日志中定位该标记反序列化 JSON校验TypeName非空且Version 1并断言所有消费者描述符一致。离线活动冒烟不联网、不泄漏凭据net10.0上另有一个独立的离线活动消费者对公共包与本地包各运行一次CreateChannel用DispatchProxy构造确定性假ISlackApiClient与IConversationsApi断言请求参数channel 名、IsPrivate、TeamId与返回 channel 输出固定C_OFFLINE_PROOF完全一致由于固定的SlackClientFactory拥有一个以 token 为键的私有缓存该消费者先通过反射检查缓存字段名与泛型类型Dictionarystring, ISlackApiClient再把假客户端种入缓存并预检GetClient(token)确认返回的就是假实例后才执行工作流非预期代理调用直接抛异常进程还设置了仅回环的代理陷阱HTTP_PROXY/HTTPS_PROXY/ALL_PROXY指向http://127.0.0.1:9NO_PROXY覆盖 localhost该 harness 被刻意做成对SlackClientFactory内部实现脆弱一旦实现变更就 fails closed且不添加任何生产钩子或测试凭据token 固定为offline-proof-token-never-sent。具体实现见 offline_activity_smoke_project()。临时消费者还引用了Elsa.Testing.Shared.Integration3.8.4 作为测试 harness 支持——该额外依赖不属于Elsa.Slack包本身。聚焦测试的如实报告聚焦源码测试工程只在net10.0上构建并运行在固定 tag 上它唯一的测试以Not implemented yet被跳过因此贡献零条执行的断言。离线活动冒烟提供了唯一一条窄范围行为检查且不取消跳过、不篡改上游测试。脚本对 TRX 的核对非常严格read_focused_test_receipt()遍历全部 TRX 文件要求恰好一个UnitTestResult且testName Elsa.Slack.Tests.Activities.Channels.CreateChannelTests.ExecuteAsync、outcome NotExecuted、跳过消息恰为Not implemented yet.16 个计数器total/executed/passed/failed/error/timeout/aborted/inconclusive 等除total1外全为 0。依赖闭包选择器基于 inventory.json 的静态依赖闭包选择器package_impact.py验证两件事对 Coresrc/modules/Elsa/Elsa.csproj的变更会命中 Slack 测试及另外50 个受影响测试工程合计 51 个显式选择 Slack 发布单元时package_ids_to_pack仅得到Elsa.Slack这一个包 ID。实现上InventoryGraph以(repository, path)为键建立反向依赖边包引用唯一命中时连边同一包 ID 对应多个候选工程重复包 ID 所有者时记录ambiguous_package_edges并对所有候选连边使影响分析宁可多测、不漏依赖。选择器自身的单元测试在 integration-tools 工作流中运行但该图尚未驱动CI 测试矩阵本次本地运行也不执行更广的 50 工程闭包。复现完整的本地证明流程环境准备使用位于固定提交上的干净、可丢弃、分离的 worktree以及位于所有仓库之外的全新空输出目录。dotnet restore/dotnet build会在源码 worktree 内写入被忽略的bin/、obj/因此切勿使用共享的开发 checkout。python3 scripts/integration-program/run_slack_package_proof.py \ --core-source /tmp/elsa-integration-8251/elsa-core \ --extensions-source /tmp/elsa-integration-8251/extensions-3.8.4 \ --output-dir /tmp/elsa-slack-proof-2026-09-23 \ --sourcelink-tool /tmp/codex-sourcelink-8259/sourcelink脚本入口在记录成功前依次执行并强制校验双重干净 pinrequire_clean_pin对 Core 与 Extensions 各执行一次git rev-parse HEAD与git status --porcelain --untracked-filesall要求 SHA 精确匹配且工作树无任何跟踪/未跟踪变更工程引用守卫require_core_project_reference解析 Slack 工程 XML 中全部ProjectReference要求解析结果恰好等于传入的 Core 工程src/modules/Elsa/Elsa.csprojSourceLink 工具校验见下节影响选择器校验运行package_impact.py断言package_ids_to_pack [Elsa.Slack]且受影响测试列表包含 Slack 测试工程依次执行源码图 restore/build → Slack 测试工程 restore/test → 下载并哈希官方基线包 → 消费者矩阵 restore/run → 离线冒烟 → 源码 ProjectReference 消费者 → 最终二次干净 pin 检查全部命令日志、evidence.json、选择器输出、TRX 结果、消费者工程与命令日志都写入输出目录仓库内不落任何证据。SourceLink 工具不信任可替换的 shim运行证明前需先安装固定的 SourceLink CLI使用隔离的 NuGet 配置mkdir -p /tmp/codex-sourcelink-8259 cat /tmp/codex-sourcelink-8259/NuGet.Config EOF configurationpackageSourcesclear /add keynuget.org valuehttps://api.nuget.org/v3/index.json //packageSources/configuration EOF dotnet tool install --tool-path /tmp/codex-sourcelink-8259 sourcelink --version 3.1.1 --configfile /tmp/codex-sourcelink-8259/NuGet.ConfigCLI 路径是必填参数。require_sourcelink_toolL110-L173的防护逻辑值得单独说明要求该路径必须是可执行的、名为sourcelink的文件且dotnet tool list --tool-path唯一返回版本3.1.1但脚本从不执行用户提供的 shim它进一步定位.store/sourcelink/3.1.1/...安装目录核对 nuspec id/version、DotnetToolSettings.xml的 CommandNamesourcelink、EntryPointsourcelink.dll、Runnerdotnet并从同目录的sourcelink.3.1.1.nupkg归档中读出sourcelink.dll比较其 SHA-256 与已安装 DLL 一致随后脚本直接以dotnet verified assembly调用该 DLLprint-json与test而不是执行路径上的 shim。缺失或未固定的工具、不完整的包存储、不匹配的 payload DLL、被篡改的安装都会在包恢复/打包之前失败因此 SourceLink 不可能在未被检查的情况下被静默报告为通过。测试工程 test_package_proof_guards.py 覆盖了这些分支shim 版本匹配但 payload 被替换会报does not match the pinned 3.1.1 packageshim 被写成exit 99也不影响校验结果因为执行的是已验证的 DLL。源与包源的隔离策略脚本为不同阶段生成两份 NuGet 配置L553-L561消费者/打包使用纯nuget.orgCore 源码 restore 需要Elsa.Platform.PackageManifest.Generator0.0.1-preview.53 这个构建工具只有该包 ID通过packageSourceMapping映射到 Elsa Feedz preview 源其余全部走 nuget.org每个阶段使用独立的NUGET_PACKAGES缓存source-build、source-test、local-pack、各消费者的 label/framework 组合并设置DOTNET_CLI_HOME与NUGET_HTTP_CACHE_PATH指向输出目录实现完全隔离。打包阶段用UseProjectReferencesfalse恢复并dotnet pack同时开启ContinuousIntegrationBuildtrue、IncludeSymbolstrue、SymbolPackageFormatsnupkg随后断言本地 feed 中恰好一个Elsa.Slack.3.8.5-proof.154ba15.nupkg外加一个.snupkg任何无关或缺失的包都会使整个证明失败。inspect_package还核对 nuspec 的 id/version、仓库 commit、三个 TFM 分组以及每组恰好Elsa 3.8.4SlackNet 0.17.7的依赖清单。手工 CI 工件证明released-artifact-proofPackage impact closure rehearsal工作流中含一个workflow_dispatch任务released-artifact-proof其 Core/Extensions pin 直接取自本脚本的CORE_SHA/EXTENSIONS_SHA常量因此该已发布 3.8.4 兼容性证明与当前清单源码闭包任务保持分离后者使用清单更新的 pin且其四个已知基线跳过使闭包仍不完整——运行工件任务不代表更广闭包通过任务安装 net8.0/net9.0/net10.0 SDK 与 SourceLink 3.1.1 到 runner 临时目录后原样调用本脚本不改动脚本权限为仓库只读无包发布凭据、无部署权限、无 push 步骤保留证据 JSON、影响选择、TRX、命令日志、生成的消费者输入与 SourceLink PDB 为slack-released-artifact-proof-evidence工件另有elsa-slack-local-proof-nupkg工件仅含Elsa.Slack.3.8.5-proof.154ba15.nupkg——下载的公共 3.8.4 对比包与符号包不上传。两类工件 14 天后过期任务超时 90 分钟且工件步骤在证明失败后仍会运行以保留已产生的证据。运行清单选择器与证明守卫测试普通与优化 Python 两种模式python3 -m unittest discover -s scripts/integration-program -p test_*.py python3 -O -m unittest discover -s scripts/integration-program -p test_*.py结果与判定边界本次运行从固定源码树成功完成。Core 源码构建对Microsoft.Build.Tasks.Git8.0.0 输出了 NU1902GHSA-23fw-v26w-5fgq基线告警该告警未使构建失败也未被本证明改变。不要凭这个有界本地结果把 #8260 的一般性包选择/CI 验收标记为完成。检查项结果公共 3.8.4 nuspec/哈希与源码提交通过NuGet SHA-256 与固定 Extensions 提交匹配Slack 工程直接打包与本地.nupkg精确集合通过恰好一个.nupkg即Elsa.Slack本地 nuspec 依赖、TFM、包 ID/版本、源码提交通过Elsa 3.8.4、SlackNet 0.17.7、net8/9/10、固定 Extensions SHA公共 3.8.4 消费者 restore/build/start 描述符net8/9/10三个 TFM 全部通过本地证明包消费者 restore/build/start 描述符net8/9/10三个 TFM 全部通过固定源码 ProjectReference 消费者 描述符net10通过描述符与公共 3.8.4 消费者一致公共包与本地包离线 CreateChannel 请求/输出冒烟net10两者均通过一次假Conversations.Create调用与匹配输出SourceLink 符号与固定源码 URL 检查sourcelink3.1.1 通过聚焦 Slack 测试工程net10已构建1 跳过、0 通过Not implemented yetCore→Slack 影响选择与 Slack 唯一包选择通过选择器单元测试51 个受影响测试工程被选中重复包所有者保守扩展到全部候选其余 50 个受影响测试 / manifest 驱动的 CI 门未运行保持开放两个重要语义边界CreateChannel描述符注册不使用任何 Slack token 或 API 请求。它证明的是包加载与运行时描述符注册而非 Slack 工作区连通性或连接器行为库存报告了六个抛出NotImplementedException的Watch*Slack 触发器它们被明确排除在本包证明之外。发布单元清单版本策略与发布者约束清单校验器 release_unit_manifest.py 与 release-units.json 共同固化了发布单元的可机读契约版本方案每个包 ID 独立、单调递增的 SemVer 2 流stable_must_increase为 true、已发布版本永不重用3.8.5-proof被local_proof_is_release_allocationfalse与local_proof_may_publishfalse双重锁定为只做本地证明、永不分配/发布发布版本未来自动化预览格式{next_stable}-preview.{run_number}.{run_attempt}.{source_sha}如3.8.5-preview.1234.1.154ba15CI 运行号按发布者单调递增attempt 区分重跑prerelease 工件作为不可变证据保留且不覆盖稳定版版本提升规则兼容修复 → patch3.8.5向后兼容的新增功能 → minor3.9.0不兼容的公共/序列化活动身份变更 → major4.0.0发布者约束当前唯一发布者为 Extensions 的.github/workflows/packages.ymlcutover 必须单独评审Core 现有packages.yml打包整个解决方案不得用于 Slack 有界发布不要为 Slack 证明触发既有全解决方案预览工作流也不要启用第二个发布者依赖语义包声明Elsa3.8.4 为依赖基线本证明精确验证 Core 3.8.4后续 Core 兼容性必须用独立消费者矩阵证明不能从 NuGet 依赖区间推断。对elsa-core仓库而言mapped一节还预留了合并后的映射路径如src/extensions/communication/Elsa.Slack/Elsa.Slack.csproj与test/extensions/modules/slack/...为未来仓库整合时保留上游历史做准备。源码级实现要点速览fails-closed 哲学贯穿全脚本任何期望不变量被违反即抛RuntimeError证据文件只写入通过或已记录失败的状态绝不含糊通过。典型分支见 require_sourcelink_tool、read_focused_test_receipt双阶段干净检查开始与结束各做一次require_sources_unchanged杜绝并发输出污染源码树却仍然报告成功对应测试在 test_package_proof_guards.py证据即产物所有可复现信息源码路径与 SHA、包哈希、SourceLink payload 哈希、命令清单、消费者描述符、选择器输出、TRX receipt统一写入evidence.json命令日志按阶段落在logs/下供审计与复跑比对。边界声明与后续工作本证明是一个有界的、仅本地的、不发布的证据包它验证了固定源码可打包出与公共基线等价的包、可被干净消费者加载并注册活动描述符、离线行为契约一致、SourceLink 符号指向固定提交、打包集合无附带包。它未验证真实 Slack 连通性、36 个活动的完整行为、六个Watch*触发器的实现也未执行 51 个受影响测试工程中的其余 50 个。一个由 manifest 驱动的完整 CI 门测试完整选择闭包且不连带重打包无关包与更广的兼容性矩阵仍作为后续验收标准保持开放——这正是该证明边界清晰、结论可复现的设计价值所在。赞分享后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载相关推荐Elsa 有界连接器发布单元与包级证明以 Elsa.Slack 为第一实践单元的独立 NuGet 发布方案Elsa 有界连接器发布单元与包级证明以 Elsa.Slack 为第一实践单元的独立 NuGet 发布方案 本篇文章围绕 Elsa 项目架构决策记录ADR后端工作流自动化流程编排低代码Elsa.Slack 源映射包证明Elsa Core 仓库合并排练中的可复现本地制品验证Elsa.Slack 源映射包证明Elsa Core 仓库合并排练中的可复现本地制品验证 本指南基于 elsa core 仓库 doc/integration后端工作流自动化流程编排低代码InsForge 开发技能指南Monorepo 包边界、编码约定与 Pre-PR 验证清单InsForge 开发技能指南Monorepo 包边界、编码约定与 Pre PR 验证清单 insforge dev 是 InsForge 仓库内置的 Age后端前端AI 应用上一篇Cataclysm-DDA技能书掉落率终极指南从测试数据看稀有度设计奥秘下一篇打造私人种子服务器WebTorrent CLI创建与分享 torrent 文件教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表