From dd8da23fc33fbf371a4bc2c74937a0a244d9615d Mon Sep 17 00:00:00 2001 From: BobDu Date: Wed, 29 Jul 2026 18:15:05 +0800 Subject: [PATCH] docs: overhaul the documentation site and how it is published MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The site was published by building it in CI and pushing the output to the gh-pages branch with a third-party action, authenticated by a token stored in the GH_TOKEN repository secret. GitHub has since provided a first-party path — upload the build as an artifact and hand it to a deployment authorised through OIDC — which needs no stored token and commits no build output to a branch. Other jenkinsci repositories already publish this way, among them maven-hpi-plugin and wxwork-notification-plugin. npm ci replaces npm install so the tracked lock file is what actually gets installed, the trigger is narrowed to the paths that can change the built site rather than every push to main, and a fork skips the build since it has no Pages site to deploy to. bin/docs-release.sh goes with the old scheme; it was its manual half and has not worked since the VitePress migration moved the build output out of docs-dist/ in September 2022, and AGENTS.md already told contributors not to run local release scripts. Going over every page against the code and checking every link then turned up a fair amount that was simply broken. `[受限的 markdonw](#受限的 markdonw)` never rendered as a link at all: the anchor contains a space, so markdown-it left the whole thing as literal text, which is what the pipeline page has been showing in two of its tables. The target section does not live on that page either, and the word is misspelt. The same page had three anchors written in CamelCase, which never resolved because heading ids are lowercased, and two screenshots hosted in an Alibaba Cloud bucket that now answers 403; those two and three others are replaced by the screenshots this repository already ships. Its syntax block was missing `singleUrl`, `at` was documented as a List when it is a Set, the default title has been `Jenkins 构建通知` rather than `Jenkins 通知` for some time, and its copy of BtnLayoutEnum misspelt horizontal. The install link pointed at plugins.jenkins.io/dingtalk, which is a 404 — the plugin is published as dingding-notifications, as the badge on the home page already had it. An action card example still linked to the previous maintainer's personal site, also gone. The DTMD page had the robot send an insult; the code now says something civil, though the screenshot still shows the old exchange and wants retaking. Two of that page's three references were help-center links that now redirect to the help centre's front page. One example mentioned a twelve-digit number where a mobile has eleven. `环境变量` listed two of the eight variables the plugin injects, and none of the things that make them surprising: `PROJECT_*` is the project while `JOB_*` is the build, `EXECUTOR_NAME` and `EXECUTOR_MOBILE` are read before they are written so they can be overridden, and none of the eight exist in the `dingtalk` step, which `Freestyle 项目高级功能` implied they did. The security policy section warned that the keyword has to appear in the message, when the plugin appends it for you. Nothing documented the raw mode at all, so `自定义消息` is a new page: what the built-in message contains, what disabling it costs (no buttons, MARKDOWN only, hence no tappable mention on mobile), and that the title stays out of your hands. `快速开始` gained the six notice occasions and the boundary of the three security policies, since only two of them need anything on the Jenkins side. The site itself declared `lang="en-US"` while being entirely in Chinese, had no search, and set `lastUpdatedText` without enabling `lastUpdated`; enabling it is why the checkout now needs the full history. The theme's remaining English labels are translated, the logo that was sitting unreferenced in assets/ is now the home page's, and the home page uses the hero layout. Public files move to `docs/public`, VitePress's default, so the explicit `vite.publicDir` can go. CONTRIBUTING told contributors to install yarn although the repository tracks package-lock.json and CI runs npm ci, and pointed at two jenkins-zh.cn articles whose domain no longer resolves and at the retired Confluence wiki. Publishing from main requires the repository's Pages source to be set to GitHub Actions; afterwards the gh-pages branch and the GH_TOKEN secret can both go away. Signed-off-by: BobDu --- .github/workflows/doc.yml | 48 ++++++++-- AGENTS.md | 13 ++- CONTRIBUTING.md | 33 +++++-- bin/docs-release.sh | 28 ------ docs/.vitepress/config.js | 59 ++++++++++-- docs/advance/custom-message.md | 73 +++++++++++++++ docs/advance/markdown.md | 4 +- docs/advance/user-property.md | 7 +- .../{dtmt-example.jpg => dtmd-example.jpg} | Bin docs/examples/action-card.md | 4 +- docs/examples/dtmd.md | 18 ++-- docs/examples/freestyle-advanced.md | 14 ++- docs/examples/link.md | 4 +- docs/examples/markdown.md | 2 +- docs/guide/environment-variables.md | 88 +++++++++++++++++- docs/guide/freestyle.md | 3 + docs/guide/getting-started.md | 61 +++++++++--- docs/guide/pipeline.md | 38 ++++---- docs/index.md | 39 ++++++-- docs/{assets => public}/dingtalk-logo.png | Bin .../favicion.ico => public/favicon.ico} | Bin package.json | 3 +- readme.md | 11 +++ 23 files changed, 424 insertions(+), 126 deletions(-) delete mode 100644 bin/docs-release.sh create mode 100644 docs/advance/custom-message.md rename docs/assets/{dtmt-example.jpg => dtmd-example.jpg} (100%) rename docs/{assets => public}/dingtalk-logo.png (100%) rename docs/{.vitepress/public/favicion.ico => public/favicon.ico} (100%) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index bdf92409..b16ffeef 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -4,23 +4,59 @@ on: push: branches: - main + paths: + - docs/** + - package.json + - package-lock.json + - .github/workflows/doc.yml + workflow_dispatch: + +# Grant GITHUB_TOKEN the permissions required to make a Pages deployment. +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and +# the latest queued one. In-progress runs are not cancelled, so a deployment always completes. +concurrency: + group: pages + cancel-in-progress: false jobs: - deploy: + build: + # A fork has no Pages site to deploy to. + if: github.repository_owner == 'jenkinsci' runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + with: + # the lastUpdated option reads each page's git history + fetch-depth: 0 - uses: actions/setup-node@v7 with: node-version: 22 cache: npm - - run: npm install + - run: npm ci - name: Build run: npm run docs:build - - name: Deploy - uses: peaceiris/actions-gh-pages@v4 + - name: Setup Pages + uses: actions/configure-pages@v6 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v5 with: - github_token: ${{ secrets.GH_TOKEN }} - publish_dir: docs/.vitepress/dist + path: docs/.vitepress/dist + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy + id: deployment + uses: actions/deploy-pages@v5 diff --git a/AGENTS.md b/AGENTS.md index 32915750..cff80d53 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,6 @@ - `src/main/java` and `src/main/resources` contain the Jenkins plugin source and resources. - `src/test/java` holds JUnit 5 tests. - `docs/` contains the VitePress documentation site. -- `bin/` includes helper scripts such as `docs-release.sh`. ## Key Classes - `io.jenkins.plugins.DingTalkRunListener`: listens to build lifecycle events and triggers notifications. @@ -23,10 +22,10 @@ ## Build, Test, and Development Commands - `mvn hpi:run` runs the plugin in a local Jenkins for development (use the Maven tool window in IntelliJ as noted in `CONTRIBUTING.md`). - `mvn test` runs the JUnit 5 test suite. -- `yarn` installs documentation dependencies for the `docs/` site. -- `yarn docs:dev` starts the VitePress docs dev server. -- `yarn docs:build` builds the static docs site. -- `yarn docs:serve` serves the built docs locally on port 5173. +- `npm ci` installs documentation dependencies for the `docs/` site. +- `npm run docs:dev` starts the VitePress docs dev server. +- `npm run docs:build` builds the static docs site. +- `npm run docs:serve` serves the built docs locally on port 5173. ## Coding Style & Naming Conventions - Java code follows Google Java Style; use your IDE formatter with the Google style XML. @@ -68,8 +67,8 @@ - Documentation releases are triggered via GitHub Actions; do not run local release scripts. ## Docs Flow -- Edit content under `docs/` and preview with `yarn docs:dev`. -- Build the static site with `yarn docs:build` and verify locally using `yarn docs:serve`. +- Edit content under `docs/` and preview with `npm run docs:dev`. +- Build the static site with `npm run docs:build` and verify locally using `npm run docs:serve`. - Use the GitHub Actions workflow to publish docs when changes are ready. ## Lessons Learned (Jelly & Jenkins UI) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87b207d1..7238e9d3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,8 +4,20 @@ ## 开发服务 -在 `IDEA` 右侧 `maven` 控制面板中添加 `hpi:run` 到启动配置: -![启动配置](./docs/assets/contribuiting-config.png) +命令行启动一个带本插件的本地 Jenkins: + +```shell +mvn hpi:run +``` + +跑测试: + +```shell +mvn verify +``` + +`IDEA` 下也可以在右侧 `maven` 控制面板中把 `hpi:run` 添加到启动配置: +![启动配置](./docs/assets/contribuiting-config.png) ## 开发约定 @@ -15,15 +27,18 @@ ## 参考文档 -1. [Plugin tutorial](https://wiki.jenkins.io/display/JENKINS/Plugin+tutorial#Plugintutorial-SettingUpEnvironment) -2. [Jenkins 插件开发之旅:两天内从 idea 到发布(上篇)](https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-06-jenkins-plugin-develop-within-two-days-part01/) -3. [Jenkins 插件开发之旅:两天内从 idea 到发布(下篇)](https://jenkins-zh.github.io/wechat/articles/2019/05/2019-05-08-jenkins-plugin-develop-within-two-days-part02/) +1. [Jenkins 插件开发教程](https://www.jenkins.io/doc/developer/tutorial/) +2. [Jenkins 插件开发文档](https://www.jenkins.io/doc/developer/plugin-development/) --- ## 文档服务 -1. 安装 node.js 环境 -2. 安装 yarn 包管理器 -3. 在项目根目录执行 `yarn` 安装依赖 -4. 执行 `yarn docs:dev` 启动文档开发环境 \ No newline at end of file +文档站用 [VitePress](https://vitepress.dev/) 构建,源文件在 `docs/` 下。 + +1. 安装 Node.js +2. 在项目根目录执行 `npm ci` 安装依赖 +3. 执行 `npm run docs:dev` 启动文档开发环境 +4. `npm run docs:build` 构建静态站点,`npm run docs:serve` 预览构建结果 + +推送到 `main` 后由 GitHub Actions 自动发布,不需要手动执行发布脚本。 diff --git a/bin/docs-release.sh b/bin/docs-release.sh deleted file mode 100644 index 7525fe9e..00000000 --- a/bin/docs-release.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env sh - -# 确保脚本抛出遇到的错误 -set -e - -# 更新依赖 -npm install - -# 生成静态文件 -npm run docs:build - -# 进入生成的文件夹 -cd docs-dist - -# 如果是发布到自定义域名 -# echo 'www.example.com' > CNAME - -git init -git add -A -git commit -m 'update docs' - -# 如果发布到 https://.github.io -# git push -f git@github.com:/.github.io.git master - -# 如果发布到 https://.github.io/ -git push -f git@github.com:jenkinsci/dingtalk-plugin.git master:gh-pages - -cd .. diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 5c0d151e..6dc3354a 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -1,11 +1,15 @@ -import path from 'path' import { defineConfig } from 'vitepress' export default defineConfig({ base: '/dingtalk-plugin/', + lang: 'zh-CN', title: '钉钉机器人插件', description: '在 Jenkins 中使用钉钉机器人发送消息', - head: [['link', { rel: 'icon', href: '/dingtalk-plugin/favicion.ico' }]], + head: [['link', { rel: 'icon', href: '/dingtalk-plugin/favicon.ico' }]], + lastUpdated: true, + sitemap: { + hostname: 'https://jenkinsci.github.io/dingtalk-plugin/' + }, vue: { template: { compilerOptions: { @@ -13,18 +17,49 @@ export default defineConfig({ } } }, - vite: { - build: { - emptyOutDir: true - }, - publicDir: path.resolve(__dirname, 'public') - }, themeConfig: { - lastUpdatedText: 'Updated Date', + logo: '/dingtalk-logo.png', + outline: [2, 3], + outlineTitle: '本页目录', + lastUpdatedText: '最后更新', + returnToTopLabel: '回到顶部', + sidebarMenuLabel: '目录', + darkModeSwitchLabel: '外观', + docFooter: { + prev: '上一页', + next: '下一页' + }, + search: { + provider: 'local', + options: { + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + noResultsText: '无法找到相关结果', + resetButtonTitle: '清除查询条件', + displayDetails: '显示详细列表', + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭' + } + } + } + } + }, + socialLinks: [ + { + icon: 'github', + link: 'https://github.com/jenkinsci/dingtalk-plugin' + } + ], editLink: { pattern: 'https://github.com/jenkinsci/dingtalk-plugin/edit/main/docs/:path', - text: 'Edit this page on GitHub' + text: '在 GitHub 上编辑此页' }, nav: [ { @@ -61,6 +96,10 @@ export default defineConfig({ text: '用户属性扩展', link: '/advance/user-property' }, + { + text: '自定义消息', + link: '/advance/custom-message' + }, { text: '@ 人', link: '/advance/at-mention' diff --git a/docs/advance/custom-message.md b/docs/advance/custom-message.md new file mode 100644 index 00000000..5a5723b6 --- /dev/null +++ b/docs/advance/custom-message.md @@ -0,0 +1,73 @@ +# 自定义消息 + +项目级配置里有两个都能写内容的输入框,区别是**在内置消息之上追加**还是**把内置消息整个换掉**: + +| 配置项 | 是否勾选 `禁用内置消息` | 效果 | +|----------|----------------|-------------------------------| +| `自定义内容` | 不勾选 | 内置消息照发,你写的内容追加在最后 | +| `自定义消息` | 勾选 | 内置消息完全不发,只发你写的内容 | + +两个框都在项目配置的 `钉钉配置` 里,勾选机器人后点 `advanced` 展开。 + +## 内置消息长什么样 + +不勾 `禁用内置消息` 时,插件发的是这样一条 `ACTION_CARD`: + +```markdown +# [项目名](项目地址) +--- +- 任务:[#42](本次构建地址) +- 状态:成功 +- 持续时间:1 min 20 sec +- 执行人:张三 + +这里是你在「自定义内容」里写的东西 +``` + +外加『更改记录』『控制台』两个按钮。 + +## 禁用内置消息之后 + +勾上 `禁用内置消息`,上面那些就全没了,只剩你在 `自定义消息` 里写的内容。想保留项目名、状态之类的信息, +自己用[环境变量](../guide/environment-variables.md)拼: + +```markdown +# ${PROJECT_NAME} ${JOB_STATUS} + +- 构建:[${JOB_NAME}](${JOB_URL}) +- 耗时:${JOB_DURATION} +- 触发人:${EXECUTOR_NAME} + +> 分支 ${GIT_BRANCH},提交 ${GIT_COMMIT} +``` + +有几件事跟着一起变了,配之前先知道: + +- **按钮没有了。**『更改记录』『控制台』两个默认按钮只属于内置消息,自定义消息发的是 `MARKDOWN` + 类型,这个类型不支持按钮。想留住这两个入口就在正文里写成链接: + `[更改记录](${JOB_URL}changes)`、`[控制台](${JOB_URL}console)`。 +- **消息类型固定是 `MARKDOWN`**,目前不能选。所以 `@` 在手机端不可点击,详见 [@ 人](./at-mention.md)。 +- **标题不受这里控制。** 钉钉在会话列表里透出的那行字始终是 `项目名 + 状态`,例如 `my-job 成功` + (用关键词安全策略的话后面还会自动拼上关键词),改不了。正文里的 `# 一级标题` 是消息内部的标题, + 两回事。 +- **`通知人` 依然生效。** 里面配的 `@` 会追加到消息末尾,除非正文里已经写过同样的 `@`。 + +## 关于换行 + +`自定义消息` 和 `自定义内容` 都是多行文本框,直接按回车换行就行。 + +::: tip + +钉钉的 markdown 只支持一个子集,能用哪些语法见 [Markdown 语法](./markdown.md)。 + +::: + +## 只想给某几种结果换内容 + +`自定义消息` 是整个机器人配置共用的,不区分构建结果。想让成功和失败发不一样的东西,两个办法: + +- 同一个机器人在正文里用 `${JOB_STATUS}` 把状态带出来,内容本身保持通用 +- 在系统设置里配两个机器人(webhook 可以填同一个群),项目里就会出现两条独立配置, + 各自勾不同的 `通知时机`、写不同的 `自定义消息` + +需要完全自由的控制流就别用项目级配置了,改用 [pipeline 的 `dingtalk` 步骤](../guide/pipeline.md)。 diff --git a/docs/advance/markdown.md b/docs/advance/markdown.md index cbfe6fe8..eea7758f 100644 --- a/docs/advance/markdown.md +++ b/docs/advance/markdown.md @@ -1,5 +1,7 @@ # Markdown -官方文档 https://open.dingtalk.com/document/orgapp/enterprise-internal-robots-send-markdown-messages#title-w87-omz-3es + +钉钉官方文档:[企业内部机器人发送 markdown 消息](https://open.dingtalk.com/document/orgapp/enterprise-internal-robots-send-markdown-messages#title-w87-omz-3es) + ## 钉钉支持的语法 目前只支持 md 语法的子集,具体支持的元素如下: diff --git a/docs/advance/user-property.md b/docs/advance/user-property.md index 18f37ae3..ce38cd60 100644 --- a/docs/advance/user-property.md +++ b/docs/advance/user-property.md @@ -31,4 +31,9 @@ ![user-detail](../assets/user-detail.jpg) -::: \ No newline at end of file +::: + +## 拿不到真实用户的场景 + +定时构建、webhook 触发这类没有登录用户的构建,这里配的属性用不上。可以改用 +`EXECUTOR_NAME` / `EXECUTOR_MOBILE` 环境变量直接指定,见[环境变量](../guide/environment-variables.md)。 diff --git a/docs/assets/dtmt-example.jpg b/docs/assets/dtmd-example.jpg similarity index 100% rename from docs/assets/dtmt-example.jpg rename to docs/assets/dtmd-example.jpg diff --git a/docs/examples/action-card.md b/docs/examples/action-card.md index 08547156..2a600bfb 100644 --- a/docs/examples/action-card.md +++ b/docs/examples/action-card.md @@ -41,7 +41,7 @@ pipeline { ```groovy singleTitle: '查看更多', -singleUrl: 'https://liuweigl.github.io/dingtalk-plugin/' +singleUrl: 'https://jenkinsci.github.io/dingtalk-plugin/' ``` :::details 查看结果 @@ -84,7 +84,7 @@ singleUrl: 'https://liuweigl.github.io/dingtalk-plugin/' :::details 查看结果 -![action-card-at-all-example](../assets/action-card-btn-layout-example.jpg) +![action-card-btn-layout-example](../assets/action-card-btn-layout-example.jpg) ::: diff --git a/docs/examples/dtmd.md b/docs/examples/dtmd.md index 18b7f6ab..0af8e682 100644 --- a/docs/examples/dtmd.md +++ b/docs/examples/dtmd.md @@ -1,16 +1,12 @@ # DTMD 协议的消息 -关于 DTMD 协议的消息,可以参考钉钉官方文档 资料较少 - -[如何通过钉钉链接发送消息给机器人](https://dingtalk.com/qidian/help-detail-1060976699.html) - -[dtmd介绍](https://www.dingtalk.com/qidian/help-detail-1066741046.html) - -[dtmd协议只能在markdown actioncard feedcard 消息类型中使用](https://open.dingtalk.com/document/orgapp/dingtalk-chatbot-for-one-on-one-query) +`dtmd` 是钉钉的消息链接协议,用它可以在消息里放一个链接,点击后由用户向机器人发一条消息回去。 +钉钉侧关于它的公开资料不多。 ::: warning -`dtmd` 协议只能在markdown、actioncard、feedcard 消息类型中使用 +`dtmd` 协议只能在 markdown、actionCard、feedCard 消息类型中使用,见 +[官方文档](https://open.dingtalk.com/document/orgapp/dingtalk-chatbot-for-one-on-one-query)。 ::: @@ -32,7 +28,7 @@ pipeline { text: [ '# DTMD 消息', '- [点我](dtmd://dingtalkclient/sendMessage?content=你好)', - '- [再点](dtmd://dingtalkclient/sendMessage?content=傻逼)' + '- [再点](dtmd://dingtalkclient/sendMessage?content=收到)' ] ) } @@ -45,6 +41,8 @@ pipeline { :::details 查看结果 -![dtmt-example](../assets/dtmt-example.jpg) +点击消息里的链接,钉钉会以你的身份向机器人发出对应内容: + +![dtmd-example](../assets/dtmd-example.jpg) ::: diff --git a/docs/examples/freestyle-advanced.md b/docs/examples/freestyle-advanced.md index 212b6f6c..f8648488 100644 --- a/docs/examples/freestyle-advanced.md +++ b/docs/examples/freestyle-advanced.md @@ -30,8 +30,18 @@ ::: tip -`通知人` 多个值需要换行添加 +`通知人` 可以填多个手机号,换行或英文逗号分隔都行,也支持写 `${EXECUTOR_MOBILE}` 这样的环境变量。 -`自定义内容` 支持 markdown 语法与环境变量,基本与 pipeline 模式保持一致 +`自定义内容` 支持[受限的 markdown 语法](../advance/markdown.md)与[环境变量](../guide/environment-variables.md)。 + +勾上 `禁用内置消息` 就不再发插件封装好的那条消息,只发 `自定义消息` 里写的内容, +两者的区别见[自定义消息](../advance/custom-message.md)。 + +::: + +::: warning + +`PROJECT_NAME`、`JOB_STATUS` 这类由插件补充的环境变量只在这里生效,pipeline 的 `dingtalk` +步骤里取不到,别照搬。 ::: diff --git a/docs/examples/link.md b/docs/examples/link.md index ddf5dc56..cfa754ff 100644 --- a/docs/examples/link.md +++ b/docs/examples/link.md @@ -19,8 +19,8 @@ pipeline { '测试链接类型的消息', '分行显示,哈哈哈哈' ], - messageUrl: 'http://www.baidu.com', - picUrl: 'https://www.picdiet.com/img/photographer_compressed.jpg' + messageUrl: 'https://jenkinsci.github.io/dingtalk-plugin/', + picUrl: 'https://raw.githubusercontent.com/jenkinsci/dingtalk-plugin/main/jenkins-logo.png' ) } } diff --git a/docs/examples/markdown.md b/docs/examples/markdown.md index be8af0da..37bae946 100644 --- a/docs/examples/markdown.md +++ b/docs/examples/markdown.md @@ -29,7 +29,7 @@ pipeline { '- 门泊东吴万里船' ], at: [ - '185166001234' + '18516601234' ] ) } diff --git a/docs/guide/environment-variables.md b/docs/guide/environment-variables.md index 63d875f0..8f7e25ba 100644 --- a/docs/guide/environment-variables.md +++ b/docs/guide/environment-variables.md @@ -1,12 +1,90 @@ # 环境变量 +插件在发送内置通知前,会往构建的环境变量里补充下面这些变量,可以直接在 `自定义内容`、`自定义消息` +和 `通知人` 里用 `${变量名}` 引用。构建自身的环境变量(`BUILD_NUMBER`、`GIT_COMMIT` 等)同样可以用。 + ## 环境变量列表 -| 变量 | 说明 | -|-----------------|---------------------| -| EXECUTOR_NAME | 构建人姓名 | -| EXECUTOR_MOBILE | 构建人手机号,会被添加到 `@` 列表 | +| 变量 | 说明 | +|-----------------|---------------------------------------------| +| EXECUTOR_NAME | 构建人姓名 | +| EXECUTOR_MOBILE | 构建人手机号,会被添加到 `@` 列表 | +| PROJECT_NAME | 项目名称,包含文件夹层级,例如 `folder » my-job` | +| PROJECT_URL | 项目地址 | +| JOB_NAME | **本次构建**的名称,默认是 `#42` 这样的构建号 | +| JOB_URL | **本次构建**的地址 | +| JOB_DURATION | 构建耗时,例如 `1 min 20 sec` | +| JOB_STATUS | 本次通知对应的构建状态:开始 / 成功 / 失败 / 取消 / 不稳定 / 未构建 | + +::: warning + +注意 `PROJECT_` 和 `JOB_` 的分工和字面意思不太一样:`PROJECT_*` 指的是**项目**,`JOB_*` 指的是**本次构建**。 + +::: + +::: tip + +`PROJECT_URL` 与 `JOB_URL` 依赖系统设置里的 Jenkins URL。没配的话构建日志里会提示 +`Please set jenkins Root URL in [ System Configuration >> System >> Jenkins Location >> Jenkins URL ]`, +并且 `JOB_URL` 会是空字符串、`PROJECT_URL` 退化成不带域名的相对路径。 + +::: + +## 覆盖构建人信息 + +`EXECUTOR_NAME` 与 `EXECUTOR_MOBILE` 是**可以被覆盖的**:插件先看构建环境里有没有同名变量, +有就用你给的值,没有才去取触发构建的 Jenkins 用户信息。 + +所以定时构建、webhook 触发这类拿不到真实用户的场景,可以自己把人塞进去: + +```groovy +pipeline { + agent any + environment { + EXECUTOR_NAME = '张三' + EXECUTOR_MOBILE = '13800138000' + } + stages { + stage('build') { + steps { + echo '构建人信息会带到通知里' + } + } + } +} +``` + +::: warning + +pipeline 里 `environment` 的值是随构建执行逐步收集的,所以这种覆盖只对**构建结束**时的那条通知生效, +`构建启动时` 那条仍然用 Jenkins 用户信息。想让两条都生效,改用构建参数或全局环境变量。 + +::: + +正常情况下应该走 [用户属性扩展](../advance/user-property.md),由 Jenkins 用户自己维护手机号。 + +## 生效范围 + +::: warning + +上面这些变量**只对内置通知和项目级配置生效**,在 pipeline 的 `dingtalk` 步骤里取不到。 + +::: + +`dingtalk` 步骤拿到的是构建自身的环境变量,插件补充的这 8 个变量是发送内置通知时才写进去的。 +在步骤里想要类似的内容,用 Jenkins 自带的变量或 Groovy 表达式自己拼,例如 +`currentBuild.result`、`currentBuild.durationString`、`env.BUILD_URL`。 + +步骤的这些参数支持环境变量展开:`robot`、`title`、`text`、`messageUrl`、`picUrl`、 +`singleTitle`、`singleUrl`、`at`,以及 `btns` 里每一项的 `title` 和 `actionUrl`。 ## 支持自定义环境变量的内容 -![img.png](../assets/freestyle-environment-variables-block.png) +![支持环境变量的配置项](../assets/freestyle-environment-variables-block.png) + +`通知人` 也支持环境变量,而且一行可以写多个手机号——换行和英文逗号都能用来分隔: + +``` +${EXECUTOR_MOBILE} +13800138000,13900139000 +``` diff --git a/docs/guide/freestyle.md b/docs/guide/freestyle.md index 5c356aec..5a297759 100644 --- a/docs/guide/freestyle.md +++ b/docs/guide/freestyle.md @@ -9,3 +9,6 @@ ![freestyle-simple-example](../assets/freestyle-simple-example.png) ::: + +想改通知时机、指定 `@` 的人或者自己写消息内容,点机器人后面的 `advanced` 展开, +见 [Freestyle 项目高级功能](../examples/freestyle-advanced.md)。 diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 749533f8..692f3d18 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -12,11 +12,11 @@ 如果 jenkins 更新中心地址(升级站点)不是官方的,可能无法获取最新的版本(第三方镜像有延迟) -请切回官方镜像源:https://updates.jenkins.io/update-center.json +请切回官方镜像源: ## 安装插件 -在 `Manage Plugins` 安装 [DingTalk](https://plugins.jenkins.io/dingtalk/) +在 `Manage Plugins` 安装 [DingTalk](https://plugins.jenkins.io/dingding-notifications) ## 机器人配置 @@ -32,7 +32,40 @@ ::: tip -推荐使用 `加密` 模式的安全策略,并测试配置是否正确 +推荐使用 `加签` 模式的安全策略,并测试配置是否正确 + +::: + +## 通知时机 + +`通知时机` 决定哪些构建结果会触发通知,可以在系统设置里设默认值,也可以在每个项目里单独勾选。 + +| 选项 | 触发条件 | +|---------|-------------------------------------------------| +| 构建启动时 | 构建开始时立即发送,与最终结果无关 | +| 构建成功时 | 构建结果为 `SUCCESS` | +| 构建失败时 | 构建结果为 `FAILURE` | +| 构建中断时 | 构建结果为 `ABORTED`,例如被人手动停止 | +| 构建不稳定时 | 构建结果为 `UNSTABLE`,通常是测试失败但构建本身没报错 | +| 未构建时 | 构建结果为 `NOT_BUILT`,例如 pipeline 阶段被跳过 | + +一次构建最多产生两条通知:`构建启动时` 一条,结束时按结果再匹配一条。都不勾选就不会发送任何内容。 + +## 安全策略 + +钉钉侧有三种安全方式,但**只有前两种需要在 Jenkins 里填东西**: + +| 钉钉侧的安全方式 | Jenkins 侧要不要填 | 说明 | +|----------|---------------|---------------------------------| +| 自定义关键词 | 要,填 `自定义关键词` | 多个关键词用逗号隔开 | +| 加签 | 要,填 `加签密钥` | 推荐这种,填钉钉给的 `SEC` 开头的密钥即可 | +| IP 白名单 | **不用填** | 把 Jenkins 的出口 IP 配到钉钉机器人里就行 | + +::: tip + +用关键词模式时不需要自己在消息内容里写关键词——插件会把这里配的关键词自动拼到消息上 +(`TEXT` 类型拼在正文末尾,其余类型拼在标题末尾)。代价是关键词会出现在收到的消息里, +而且填了多个的话是整串一起拼上去的,所以关键词建议只填一个、且选一个不影响阅读的词。 ::: @@ -41,11 +74,17 @@ 钉钉机器人分为 **企业内部机器人** 与 **自定义机器人** 两种: - **自定义机器人**:在钉钉群内创建后会生成 Webhook 地址。可在钉钉侧选择安全方式(关键词/加签/IP 白名单)。 - - 关键词文档:https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-jk6-ksi-zur - - 加签文档:https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-7fs-kgs-36x - - IP 白名单文档:https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-hvj-mm1-5xu -- **企业内部机器人**:获取 Webhook 的方式不同,请参考官方 FAQ: - - https://open.dingtalk.com/document/development/faq-robot#ba79fa80c4c0g - -注意:只有 **自定义机器人** 需要在 Jenkins 的“安全设置”中配置关键词或加签密钥。 -如果使用 **IP 白名单** 方式,只需将 Jenkins 出口 IP 配置到钉钉机器人中,Jenkins 侧无需填写。 + - [关键词文档](https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-jk6-ksi-zur) + - [加签文档](https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-7fs-kgs-36x) + - [IP 白名单文档](https://open.dingtalk.com/document/dingstart/customize-robot-security-settings#title-hvj-mm1-5xu) +- **企业内部机器人**:获取 Webhook 的方式不同,请参考[官方 FAQ](https://open.dingtalk.com/document/development/faq-robot#ba79fa80c4c0g) + +只有 **自定义机器人** 才有关键词和加签这两种安全方式,也就是说上面那张表只对自定义机器人有意义; +用 **企业内部机器人** 时,Jenkins 侧的安全策略留空即可。 + +## 接下来 + +- [在 freestyle 项目中使用](./freestyle.md) +- [在 pipeline 中使用](./pipeline.md) +- [让通知 @ 到人](../advance/at-mention.md) +- [完全自定义消息内容](../advance/custom-message.md) diff --git a/docs/guide/pipeline.md b/docs/guide/pipeline.md index 57ef76bf..2a80ff17 100644 --- a/docs/guide/pipeline.md +++ b/docs/guide/pipeline.md @@ -16,6 +16,7 @@ dingtalk( messageUrl: '', picUrl: '', singleTitle: '', + singleUrl: '', btns: [], btnLayout: '', hideAvatar: false @@ -27,12 +28,12 @@ dingtalk( ### 通用的参数 -| 参数 | 类型 | 说明 | -|-------|:---------------------------:|------------| -| robot | String | 机器人 id | -| type | [MsgTypeEnum](#MsgTypeEnum) | 消息类型 | -| at | List\ | 需要 @ 的手机号码 | -| atAll | boolean | 是否 @ 全部 | +| 参数 | 类型 | 说明 | +|-------|:---------------------------:|------------------| +| robot | String | 机器人 id | +| type | [MsgTypeEnum](#msgtypeenum) | 消息类型 | +| at | Set\ | 需要 @ 的手机号码,重复的会去重 | +| atAll | boolean | 是否 @ 全部 | ::: warning @@ -95,15 +96,15 @@ public enum MsgTypeEnum { | 参数 | 类型 | 说明 | |-------|:--------------:|------------------------------------------| | title | String | [首屏会话](#首屏会话) 透出的展示内容 | -| text | List\ | 消息内容,支持 [受限的 markdonw](#受限的 markdonw) 语法 | +| text | List\ | 消息内容,支持[受限的 markdown 语法](../advance/markdown.md) | ### ACTION_CARD 类型的消息 | 参数 | 类型 | 说明 | |------------|:-------------------------------:|------------------------------------------| | title | String | [首屏会话](#首屏会话) 透出的展示内容 | -| text | List\ | 消息内容,支持 [受限的 markdonw](#受限的 markdonw) 语法 | -| btnLayout | [BtnLayoutEnum](#BtnLayoutEnum) | 按钮的排列方式 | +| text | List\ | 消息内容,支持[受限的 markdown 语法](../advance/markdown.md) | +| btnLayout | [BtnLayoutEnum](#btnlayoutenum) | 按钮的排列方式 | | hideAvatar | boolean | 是否隐藏发消息者头像 | ### BtnLayoutEnum @@ -113,17 +114,16 @@ public enum MsgTypeEnum { public enum BtnLayoutEnum { /** - * horizotal:水平排列 + * horizontal:水平排列 */ H, /** * vertical:垂直排列 */ - V; + V } - ``` #### 整体跳转 @@ -137,7 +137,7 @@ public enum BtnLayoutEnum { | 参数 | 类型 | 说明 | |------|:---------------------------------:|--------| -| btns | List<[ButtonModel](#ButtonModel)> | 自定义按钮组 | +| btns | List<[ButtonModel](#buttonmodel)> | 自定义按钮组 | ### ButtonModel @@ -162,7 +162,7 @@ public class ButtonModel { ### title 参数 -当参数为空时,默认会使用 _Jenkins 通知_ +当参数为空时,默认会使用 _Jenkins 构建通知_ ### ACTION_CARD 类型的消息 @@ -174,7 +174,7 @@ public class ButtonModel { :::details 点击查看 -![text](https://img.alicdn.com/tfs/TB1jFpqaRxRMKJjy0FdXXaifFXa-497-133.png) +![text](../assets/text-example.jpg) ::: @@ -182,7 +182,7 @@ public class ButtonModel { :::details 点击查看 -![link](https://ding-doc.oss-cn-beijing.aliyuncs.com/images/0.0.239/1570679827267-6243216b-d1c3-48b7-9b1e-0f0b4211b50b.png) +![link](../assets/link-example.jpg) ::: @@ -190,7 +190,7 @@ public class ButtonModel { :::details 点击查看 -![markdown](https://img.alicdn.com/tfs/TB1yL3taUgQMeJjy0FeXXXOEVXa-492-380.png) +![markdown](../assets/markdown-example.jpg) ::: @@ -198,7 +198,7 @@ public class ButtonModel { :::details 点击查看 -![actionCard](https://img.alicdn.com/tfs/TB1nhWCiBfH8KJjy1XbXXbLdXXa-547-379.png) +![actionCard](../assets/action-card-default-example.jpg) ::: @@ -206,7 +206,7 @@ public class ButtonModel { :::details 点击查看 -![actionCard](https://ding-doc.oss-cn-beijing.aliyuncs.com/images/0.0.239/1570679939723-c1fb7861-5bcb-4c30-9e1b-033932f6b72f.png) +![actionCard](../assets/action-card-custom-btns-example.jpg) ::: diff --git a/docs/index.md b/docs/index.md index 0627a7e8..041f758d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,13 +1,32 @@ -# 介绍 +--- +layout: home -[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/dingding-notifications.svg?label=Version)](https://plugins.jenkins.io/dingding-notifications) - -[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/dingding-notifications.svg?label=Installs&color=green)](https://plugins.jenkins.io/dingding-notifications) +hero: + name: 钉钉机器人插件 + text: 在 Jenkins 中发送钉钉通知 + tagline: 构建开始、成功、失败都能推送到钉钉群,freestyle 与 pipeline 都可用 + image: + src: /dingtalk-logo.png + alt: 钉钉 + actions: + - theme: brand + text: 快速开始 + link: /guide/getting-started + - theme: alt + text: 在 pipeline 中使用 + link: /guide/pipeline + - theme: alt + text: GitHub + link: https://github.com/jenkinsci/dingtalk-plugin -在 Jenkins 中使用钉钉机器人发送消息 +features: + - title: 简单配置即可用 + details: 在系统设置里添加机器人、在项目里勾选,不写一行代码就能收到构建通知。 + - title: 支持所有类型的项目 + details: freestyle 项目勾选即用,pipeline 用 dingtalk 步骤按需发送。 + - title: 支持多种消息类型 + details: TEXT、LINK、MARKDOWN、ACTION_CARD 四种类型,支持 @ 人、自定义按钮与自定义内容。 +--- -## 特性 - -1. 简单配置即可用 -2. 支持所有类型的项目 -3. 支持多种消息类型 +[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/dingding-notifications.svg?label=Version)](https://plugins.jenkins.io/dingding-notifications) +[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/dingding-notifications.svg?label=Installs&color=green)](https://plugins.jenkins.io/dingding-notifications) diff --git a/docs/assets/dingtalk-logo.png b/docs/public/dingtalk-logo.png similarity index 100% rename from docs/assets/dingtalk-logo.png rename to docs/public/dingtalk-logo.png diff --git a/docs/.vitepress/public/favicion.ico b/docs/public/favicon.ico similarity index 100% rename from docs/.vitepress/public/favicion.ico rename to docs/public/favicon.ico diff --git a/package.json b/package.json index 6a5b4301..7ced9d8d 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "scripts": { "docs:dev": "vitepress dev docs", "docs:build": "vitepress build docs", - "docs:serve": "vitepress serve docs --port 5173", - "docs:release": "sh ./bin/docs-release.sh" + "docs:serve": "vitepress serve docs --port 5173" }, "devDependencies": { "vitepress": "^1.6.3" diff --git a/readme.md b/readme.md index 67e821f8..a514a534 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,22 @@ # DingTalk 机器人通知 +[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/dingding-notifications.svg?label=Version)](https://plugins.jenkins.io/dingding-notifications) +[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/dingding-notifications.svg?label=Installs&color=green)](https://plugins.jenkins.io/dingding-notifications) ![机器人头像](jenkins-logo.png) +在 Jenkins 中用钉钉机器人发送构建通知。freestyle 项目勾选即用,pipeline 用 `dingtalk` 步骤按需发送; +支持 TEXT / LINK / MARKDOWN / ACTION_CARD 四种消息类型,以及 @ 人、自定义按钮和自定义消息内容。 + +安装:在 Jenkins 的 `Manage Plugins` 里搜索 DingTalk,或访问[插件市场页面](https://plugins.jenkins.io/dingding-notifications)。 +配置、参数和示例都在文档站。 # [💯 能看到吗?这是文档!!!](https://jenkinsci.github.io/dingtalk-plugin/) ## Contributing [🍻 Contributing](./CONTRIBUTING.md) + +## License + +[MIT](./LICENSE.txt)