feat: update package version to 0.0.42 and add CNB version fetching functionality

- Updated package version in package.json from 0.0.40 to 0.0.42.
- Added getCNBVersion function to fetch CNB version information from the API.
- Enhanced Issue class with methods for managing comments (list, create, get, update).
- Introduced new NPC and comment environment hooks for better context management.
- Implemented Docker image synchronization route for CNB.
- Added tests for version fetching and issue comment functionalities.
This commit is contained in:
xiongxiao
2026-03-10 03:45:02 +08:00
committed by cnb
parent 7b8f6fbf9f
commit 38ee73e48f
14 changed files with 927 additions and 115 deletions

417
src/issue/npc/env.ts Normal file
View File

@@ -0,0 +1,417 @@
// CNB_NPC_SLUG 对于 @ 知识库角色触发的 NPC 事件,值为 NPC 所属仓库路径,否则为空字符串
// CNB_NPC_NAME 对于 NPC 事件触发的构建,值为 NPC 角色名,否则为空字符串
// CNB_NPC_SHA 对于 @ 知识库角色触发的 NPC 事件,值为 NPC 所属仓库默认分支最新提交的 sha否则为空字符串
// CNB_NPC_PROMPT 对于 @ 知识库角色触发的 NPC 事件,值为 NPC 角色 Prompt否则为空字符串
// CNB_NPC_AVATAR 对于 @ 知识库角色触发的 NPC 事件,值为 NPC 角色头像,否则为空字符串
// CNB_NPC_ENABLE_THINKING 对于 @npc 事件触发的构建,值为 NPC 角色是否开启思考,否则为空字符串
import { useKey } from "@kevisual/context";
export function useNPCEnv() {
const npcSlug = useKey("CNB_NPC_SLUG");
const npcName = useKey("CNB_NPC_NAME");
const npcSha = useKey("CNB_NPC_SHA");
const npcPrompt = useKey("CNB_NPC_PROMPT");
const npcAvatar = useKey("CNB_NPC_AVATAR");
const npcEnableThinking = useKey("CNB_NPC_ENABLE_THINKING");
return {
/**
* @key CNB_NPC_SLUG
* @description:对于 @ 知识库角色触发的 NPC 事件,值为 NPC 所属仓库路径,否则为空字符串
*/
npcSlug,
/**
* @key CNB_NPC_NAME
* @description:对于 NPC 事件触发的构建,值为 NPC 角色名,否则为空字符串
*/
npcName,
/**
* @key CNB_NPC_SHA
* @description:对于 @ 知识库角色触发的 NPC 事件,值为 NPC 所属仓库默认分支最新提交的 sha否则为空字符串
*/
npcSha,
/**
* @key CNB_NPC_PROMPT
* @description:对于 @ 知识库角色触发的 NPC 事件,值为 NPC 角色 Prompt否则为空字符串
*/
npcPrompt,
/**
* @key CNB_NPC_AVATAR
* @description:对于 @ 知识库角色触发的 NPC 事件,值为 NPC 角色头像,否则为空字符串
*/
npcAvatar,
/**
* @key CNB_NPC_ENABLE_THINKING
* @description:对于 @npc 事件触发的构建,值为 NPC 角色是否开启思考,否则为空字符串
*/
npcEnableThinking
};
}
// CNB_COMMENT_ID 对于评论事件触发的构建,值为评论全局唯一 ID否则为空字符串
// CNB_COMMENT_BODY 对于评论事件触发的构建,值为评论内容,否则为空字符串
// CNB_COMMENT_TYPE note 对于 PR 代码评审评论,值为 diff_note对于 PR 非代码评审评论以及 Issue 评论,值为 note否则为空字符串
// CNB_COMMENT_FILE_PATH 对于 PR 代码评审评论,值为评论所在文件,否则为空字符串
// CNB_COMMENT_RANGE 对于 PR 代码评审评论,值为评论所在代码行。如,单行为 L12多行为 L13-L16否则为空字符串
// CNB_REVIEW_ID 对于 PR 代码评审,值为评审 ID否则为空字符串
export function useCommentEnv() {
const commentId = useKey("CNB_COMMENT_ID");
const commentBody = useKey("CNB_COMMENT_BODY");
const commentType = useKey("CNB_COMMENT_TYPE");
const commentFilePath = useKey("CNB_COMMENT_FILE_PATH");
const commentRange = useKey("CNB_COMMENT_RANGE");
const reviewId = useKey("CNB_REVIEW_ID");
return {
/**
* @key CNB_COMMENT_ID
* @description:对于评论事件触发的构建,值为评论全局唯一 ID否则为空字符串
*/
commentId,
/**
* @key CNB_COMMENT_BODY
* @description:对于评论事件触发的构建,值为评论内容,否则为空字符串
*/
commentBody,
/**
* @key CNB_COMMENT_TYPE
* @description:note 对于 PR 代码评审评论,值为 diff_note对于 PR 非代码评审评论以及 Issue 评论,值为 note否则为空字符串
*/
commentType,
/**
* @key CNB_COMMENT_FILE_PATH
* @description:对于 PR 代码评审评论,值为评论所在文件,否则为空字符串
*/
commentFilePath,
/**
* @key CNB_COMMENT_RANGE
* @description:对于 PR 代码评审评论,值为评论所在代码行。如,单行为 L12多行为 L13-L16否则为空字符串
*/
commentRange,
/**
* @key CNB_REVIEW_ID
* @description:对于 PR 代码评审,值为评审 ID否则为空字符串
*/
reviewId
};
}
// CNB_BUILD_ID cnb-75b-1jj9hnk99 当前构建的流水号,全局唯一
// CNB_BUILD_WEB_URL https://cnb.cool/kevision/dev-cnb/-/build/logs/cnb-75b-1jj9hnk99 当前构建的日志地址
// CNB_BUILD_START_TIME 2026-03-09T14:59:01.550Z 当前构建的开始时间UTC 格式,示例 2025-08-21T09:13:45.803Z
// CNB_BUILD_USER xiongxiao 当前构建的触发者用户名
// CNB_BUILD_USER_NICKNAME 小熊猫呜呜呜 当前构建的触发者昵称
// CNB_BUILD_USER_EMAIL kevisual@xiongxiao.me 当前构建的触发者邮箱
// CNB_BUILD_USER_ID 1935321989751226368 当前构建的触发者 id
// CNB_BUILD_USER_NPC_SLUG 当前构建若为 NPC 触发,则为 NPC 所属仓库的路径
// CNB_BUILD_USER_NPC_NAME 当前构建若为 NPC 触发,则为 NPC 角色名
// CNB_BUILD_STAGE_NAME 初始化开发机 当前构建的 stage 名称
// CNB_BUILD_JOB_NAME 初始化开发机 当前构建的 job 名称
// CNB_BUILD_JOB_KEY job-0 当前构建的 job key同 stage 下唯一
// CNB_BUILD_WORKSPACE /workspace/ 自定义 shell 脚本执行的工作空间根目录
// CNB_BUILD_FAILED_MSG 流水线构建失败的错误信息,可在 failStages 中使用
// CNB_BUILD_FAILED_STAGE_NAME 流水线构建失败的 stage 的名称,可在 failStages 中使用
// CNB_PIPELINE_NAME pipeline-1 当前 pipeline 的 name没声明时为空
// CNB_PIPELINE_KEY pipeline-1 当前 pipeline 的索引 key例如 pipeline-0
// CNB_PIPELINE_ID cnb-75b-1jj9hnk99-001 当前 pipeline 的 id全局唯一字符串
// CNB_PIPELINE_DOCKER_IMAGE docker.cnb.cool/kevisual/dev-env:latest 当前 pipeline 所使用的 docker imagealpine:latest
// CNB_PIPELINE_STATUS 当前流水线的构建状态,可在 endStages 中查看其可能的值包括success、error、cancel
// CNB_PIPELINE_MAX_RUN_TIME 72000000 流水线最大运行时间,单位为毫秒
// CNB_RUNNER_IP 10.235.16.3 当前 pipeline 所在 Runner 的 ip
// CNB_CPUS 16 当前构建流水线可以使用的最大 CPU 核数
// CNB_MEMORY 32 当前构建流水线可以使用的最大内存大小,单位为 GiB
// CNB_IS_RETRY false 当前构建是否由 rebuild 触发
// HUSKY_SKIP_INSTALL 1 兼容 ci 环境下 husky
export const useBuildEnv = () => {
const buildId = useKey("CNB_BUILD_ID");
const buildWebUrl = useKey("CNB_BUILD_WEB_URL");
const buildStartTime = useKey("CNB_BUILD_START_TIME");
const buildUser = useKey("CNB_BUILD_USER");
const buildUserNickname = useKey("CNB_BUILD_USER_NICKNAME");
const buildUserEmail = useKey("CNB_BUILD_USER_EMAIL");
const buildUserId = useKey("CNB_BUILD_USER_ID");
const buildUserNpcSlug = useKey("CNB_BUILD_USER_NPC_SLUG");
const buildUserNpcName = useKey("CNB_BUILD_USER_NPC_NAME");
const buildStageName = useKey("CNB_BUILD_STAGE_NAME");
const buildJobName = useKey("CNB_BUILD_JOB_NAME");
const buildJobKey = useKey("CNB_BUILD_JOB_KEY");
const buildWorkspace = useKey("CNB_BUILD_WORKSPACE");
const buildFailedMsg = useKey("CNB_BUILD_FAILED_MSG");
const buildFailedStageName = useKey("CNB_BUILD_FAILED_STAGE_NAME");
const pipelineName = useKey("CNB_PIPELINE_NAME");
const pipelineKey = useKey("CNB_PIPELINE_KEY");
const pipelineId = useKey("CNB_PIPELINE_ID");
const pipelineDockerImage = useKey("CNB_PIPELINE_DOCKER_IMAGE");
const pipelineStatus = useKey("CNB_PIPELINE_STATUS");
const pipelineMaxRunTime = useKey("CNB_PIPELINE_MAX_RUN_TIME");
const runnerIp = useKey("CNB_RUNNER_IP");
const cpus = useKey("CNB_CPUS");
const memory = useKey("CNB_MEMORY");
const isRetry = useKey("CNB_IS_RETRY");
const huskySkipInstall = useKey("HUSKY_SKIP_INSTALL");
return {
/**
* @key CNB_BUILD_ID
* @description:当前构建的流水号,全局唯一
*/
buildId,
/**
* @key CNB_BUILD_WEB_URL
* @description:当前构建的日志地址
*/
buildWebUrl,
/**
* @key CNB_BUILD_START_TIME
* @description:当前构建的开始时间UTC 格式
*/
buildStartTime,
/**
* @key CNB_BUILD_USER
* @description:当前构建的触发者用户名
*/
buildUser,
/**
* @key CNB_BUILD_USER_NICKNAME
* @description:当前构建的触发者昵称
*/
buildUserNickname,
/**
* @key CNB_BUILD_USER_EMAIL
* @description:当前构建的触发者邮箱
*/
buildUserEmail,
/**
* @key CNB_BUILD_USER_ID
* @description:当前构建的触发者 id
*/
buildUserId,
/**
* @key CNB_BUILD_USER_NPC_SLUG
* @description:当前构建若为 NPC 触发,则为 NPC 所属仓库的路径
*/
buildUserNpcSlug,
/**
* @key CNB_BUILD_USER_NPC_NAME
* @description:当前构建若为 NPC 触发,则为 NPC 角色名
*/
buildUserNpcName,
/**
* @key CNB_BUILD_STAGE_NAME
* @description:当前构建的 stage 名称
*/
buildStageName,
/**
* @key CNB_BUILD_JOB_NAME
* @description:当前构建的 job 名称
*/
buildJobName,
/**
* @key CNB_BUILD_JOB_KEY
* @description:当前构建的 job key同 stage 下唯一
*/
buildJobKey,
/**
* @key CNB_BUILD_WORKSPACE
* @description:自定义 shell 脚本执行的工作空间根目录
*/
buildWorkspace,
/**
* @key CNB_BUILD_FAILED_MSG
* @description:流水线构建失败的错误信息
*/
buildFailedMsg,
/**
* @key CNB_BUILD_FAILED_STAGE_NAME
* @description:流水线构建失败的 stage 的名称
*/
buildFailedStageName,
/**
* @key CNB_PIPELINE_NAME
* @description:当前 pipeline 的 name
*/
pipelineName,
/**
* @key CNB_PIPELINE_KEY
* @description:当前 pipeline 的索引 key
*/
pipelineKey,
/**
* @key CNB_PIPELINE_ID
* @description:当前 pipeline 的 id
*/
pipelineId,
/**
* @key CNB_PIPELINE_DOCKER_IMAGE
* @description:当前 pipeline 所使用的 docker image
*/
pipelineDockerImage,
/**
* @key CNB_PIPELINE_STATUS
* @description:当前流水线的构建状态可能的值包括success、error、cancel
*/
pipelineStatus,
/**
* @key CNB_PIPELINE_MAX_RUN_TIME
* @description:流水线最大运行时间,单位为毫秒
*/
pipelineMaxRunTime,
/**
* @key CNB_RUNNER_IP
* @description:当前 pipeline 所在 Runner 的 ip
*/
runnerIp,
/**
* @key CNB_CPUS
* @description:当前构建流水线可以使用的最大 CPU 核数
*/
cpus,
/**
* @key CNB_MEMORY
* @description:当前构建流水线可以使用的最大内存大小,单位为 GiB
*/
memory,
/**
* @key CNB_IS_RETRY
* @description:当前构建是否由 rebuild 触发
*/
isRetry,
/**
* @key HUSKY_SKIP_INSTALL
* @description:兼容 ci 环境下 husky
*/
huskySkipInstall
};
}
// CNB_PULL_REQUEST false 对于由 pull_request、pull_request.update、pull_request.target 触发的构建,值为 true否则为 false
// CNB_PULL_REQUEST_LIKE false 对于由 合并类事件 触发的构建,值为 true否则为 false
// CNB_PULL_REQUEST_PROPOSER 对于由 合并类事件 触发的构建,值为提出 PR 者名称,否则为空字符串
// CNB_PULL_REQUEST_TITLE 对于由 合并类事件 触发的构建,值为提 PR 时候填写的标题,否则为空字符串
// CNB_PULL_REQUEST_BRANCH 对于由 合并类事件 触发的构建,值为发起 PR 的源分支名称,否则为空字符串
// CNB_PULL_REQUEST_SHA 对于由 合并类事件 触发的构建,值为当前 PR 源分支最新的提交 sha否则为空字符串
// CNB_PULL_REQUEST_TARGET_SHA 对于由 合并类事件 触发的构建,值为当前 PR 目标分支最新的提交 sha否则为空字符串
// CNB_PULL_REQUEST_MERGE_SHA 对于由 pull_request.merged 触发的构建,值为合并后的 sha对于 pull_request 等触发的构建,值为预合并后的 sha否则为空字符串
// CNB_PULL_REQUEST_SLUG 对于由 合并类事件 触发的构建,值为源仓库的仓库 slug如 group_slug/repo_name否则为空字符串
// CNB_PULL_REQUEST_ACTION 对于由 合并类事件 触发的构建可能的值有created(新建PR)、code_update(源分支push)、status_update(评审通过或CI状态变更),否则为空字符串
// CNB_PULL_REQUEST_ID 对于由 合并类事件 触发的构建,值为当前或者关联 PR 的全局唯一 id否则为空字符串
export const usePullRequestEnv = () => {
const pullRequest = useKey("CNB_PULL_REQUEST");
const pullRequestLike = useKey("CNB_PULL_REQUEST_LIKE");
const pullRequestProposer = useKey("CNB_PULL_REQUEST_PROPOSER");
const pullRequestTitle = useKey("CNB_PULL_REQUEST_TITLE");
const pullRequestBranch = useKey("CNB_PULL_REQUEST_BRANCH");
const pullRequestSha = useKey("CNB_PULL_REQUEST_SHA");
const pullRequestTargetSha = useKey("CNB_PULL_REQUEST_TARGET_SHA");
const pullRequestMergeSha = useKey("CNB_PULL_REQUEST_MERGE_SHA");
const pullRequestSlug = useKey("CNB_PULL_REQUEST_SLUG");
const pullRequestAction = useKey("CNB_PULL_REQUEST_ACTION");
const pullRequestId = useKey("CNB_PULL_REQUEST_ID");
return {
/**
* @key CNB_PULL_REQUEST
* @description:对于由 pull_request、pull_request.update、pull_request.target 触发的构建,值为 true否则为 false
*/
pullRequest,
/**
* @key CNB_PULL_REQUEST_LIKE
* @description:对于由 合并类事件 触发的构建,值为 true否则为 false
*/
pullRequestLike,
/**
* @key CNB_PULL_REQUEST_PROPOSER
* @description:对于由 合并类事件 触发的构建,值为提出 PR 者名称,否则为空字符串
*/
pullRequestProposer,
/**
* @key CNB_PULL_REQUEST_TITLE
* @description:对于由 合并类事件 触发的构建,值为提 PR 时候填写的标题,否则为空字符串
*/
pullRequestTitle,
/**
* @key CNB_PULL_REQUEST_BRANCH
* @description:对于由 合并类事件 触发的构建,值为发起 PR 的源分支名称,否则为空字符串
*/
pullRequestBranch,
/**
* @key CNB_PULL_REQUEST_SHA
* @description:对于由 合并类事件 触发的构建,值为当前 PR 源分支最新的提交 sha否则为空字符串
*/
pullRequestSha,
/**
* @key CNB_PULL_REQUEST_TARGET_SHA
* @description:对于由 合并类事件 触发的构建,值为当前 PR 目标分支最新的提交 sha否则为空字符串
*/
pullRequestTargetSha,
/**
* @key CNB_PULL_REQUEST_MERGE_SHA
* @description:对于由 pull_request.merged 触发的构建,值为合并后的 sha对于 pull_request 等触发的构建,值为预合并后的 sha否则为空字符串
*/
pullRequestMergeSha,
/**
* @key CNB_PULL_REQUEST_SLUG
* @description:对于由 合并类事件 触发的构建,值为源仓库的仓库 slug如 group_slug/repo_name否则为空字符串
*/
pullRequestSlug,
/**
* @key CNB_PULL_REQUEST_ACTION
* @description:对于由 合并类事件 触发的构建可能的值有created(新建PR)、code_update(源分支push)、status_update(评审通过或CI状态变更),否则为空字符串
*/
pullRequestAction,
/**
* @key CNB_PULL_REQUEST_ID
* @description:对于由 合并类事件 触发的构建,值为当前或者关联 PR 的全局唯一 id否则为空字符串
*/
pullRequestId
};
}
// CNB_REPO_SLUG kevision/dev-cnb 目标仓库路径,格式为 group_slug / repo_namegroup_slug / sub_gourp_slug /.../repo_name
// CNB_REPO_SLUG_LOWERCASE kevision/dev-cnb 目标仓库路径小写格式
// CNB_REPO_NAME dev-cnb 目标仓库名称
// CNB_REPO_NAME_LOWERCASE dev-cnb 目标仓库名称小写格式
// CNB_REPO_ID 2026263219584110592 目标仓库的 id
// CNB_REPO_URL_HTTPS 目标仓库 https 地址
export const useRepoInfoEnv = () => {
const repoSlug = useKey("CNB_REPO_SLUG");
const repoSlugLowercase = useKey("CNB_REPO_SLUG_LOWERCASE");
const repoName = useKey("CNB_REPO_NAME");
const repoNameLowercase = useKey("CNB_REPO_NAME_LOWERCASE");
const repoId = useKey("CNB_REPO_ID");
const repoUrlHttps = useKey("CNB_REPO_URL_HTTPS");
return {
/**
* @key CNB_REPO_SLUG
* @description:目标仓库路径,格式为 group_slug/repo_namegroup_slug/sub_group_slug/.../repo_name
*/
repoSlug,
/**
* @key CNB_REPO_SLUG_LOWERCASE
* @description:目标仓库路径小写格式
*/
repoSlugLowercase,
/**
* @key CNB_REPO_NAME
* @description:目标仓库名称
*/
repoName,
/**
* @key CNB_REPO_NAME_LOWERCASE
* @description:目标仓库名称小写格式
*/
repoNameLowercase,
/**
* @key CNB_REPO_ID
* @description:目标仓库的 id
*/
repoId,
/**
* @key CNB_REPO_URL_HTTPS
* @description:目标仓库 https 地址
*/
repoUrlHttps
};
}