You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by gi...@apache.org on 2021/10/02 10:17:36 UTC

[dolphinscheduler-website] branch asf-site updated: Automated deployment: d6ab5bac4757f677247b94ae3d1899b461724cae

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new ee8ccb4  Automated deployment: d6ab5bac4757f677247b94ae3d1899b461724cae
ee8ccb4 is described below

commit ee8ccb4e8494c005552f27f130560590f1d4f206
Author: github-actions[bot] <gi...@users.noreply.github.com>
AuthorDate: Sat Oct 2 10:17:29 2021 +0000

    Automated deployment: d6ab5bac4757f677247b94ae3d1899b461724cae
---
 .../00282F58-D216-470A-A65D-90EE09C76DED.jpeg      | Bin 0 -> 114187 bytes
 ...3F0CE-18FE-4163-951A-4E0734A42EC2_4_5005_c.jpeg | Bin 0 -> 20639 bytes
 .../1989B620-63EC-45C8-B148-22CD5F2AB528.jpeg      | Bin 0 -> 117358 bytes
 .../29CAB894-5281-4740-8E39-897E96571D6A.jpeg      | Bin 0 -> 112774 bytes
 .../3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg      | Bin 0 -> 119138 bytes
 ...2B6A2-67C8-4EAD-BE7A-992D0AE90CD1_4_5005_c.jpeg | Bin 0 -> 20602 bytes
 .../51656174-4F3A-4A73-94FA-7E12D5B6FF27.jpeg      | Bin 0 -> 126402 bytes
 .../6A1478C7-3824-47F5-9E48-5BC04FB20B3E.jpeg      | Bin 0 -> 79799 bytes
 ...15483-ABF1-44C1-AC6F-CDED1623CC07_4_5005_c.jpeg | Bin 0 -> 36405 bytes
 .../902CAC66-44A6-457E-BF87-534010FE6585.jpeg      | Bin 0 -> 115655 bytes
 .../962BFAD9-5695-4369-B2D5-F4185C229CCB.jpeg      | Bin 0 -> 114854 bytes
 .../B5B15323-7379-4332-AEAC-7E70DBE2F924.jpeg      | Bin 0 -> 99007 bytes
 .../BFE0DB23-148B-4D0E-8C4D-C7DB51570593.jpeg      | Bin 0 -> 112625 bytes
 .../CB12C170-A17C-4C1A-8078-2CC67B8BAB31.jpeg      | Bin 0 -> 101443 bytes
 .../D48B0EAD-D0A0-40D3-AD19-0A19F83DD39E.jpeg      | Bin 0 -> 105586 bytes
 .../F595066F-EE0B-4086-AD92-5BAF081792F9.jpeg      | Bin 0 -> 123397 bytes
 img/cicd_workflow/feature_release.json             |   1 +
 img/cicd_workflow/packaging.json                   |   1 +
 img/cicd_workflow/rollback.json                    |   1 +
 zh-cn/blog/cicd_workflow.html                      | 258 +++++++++++++++++++++
 zh-cn/blog/cicd_workflow.json                      |   6 +
 21 files changed, 267 insertions(+)

diff --git a/img/cicd_workflow/00282F58-D216-470A-A65D-90EE09C76DED.jpeg b/img/cicd_workflow/00282F58-D216-470A-A65D-90EE09C76DED.jpeg
new file mode 100644
index 0000000..99b37b0
Binary files /dev/null and b/img/cicd_workflow/00282F58-D216-470A-A65D-90EE09C76DED.jpeg differ
diff --git a/img/cicd_workflow/12D3F0CE-18FE-4163-951A-4E0734A42EC2_4_5005_c.jpeg b/img/cicd_workflow/12D3F0CE-18FE-4163-951A-4E0734A42EC2_4_5005_c.jpeg
new file mode 100644
index 0000000..7fe3185
Binary files /dev/null and b/img/cicd_workflow/12D3F0CE-18FE-4163-951A-4E0734A42EC2_4_5005_c.jpeg differ
diff --git a/img/cicd_workflow/1989B620-63EC-45C8-B148-22CD5F2AB528.jpeg b/img/cicd_workflow/1989B620-63EC-45C8-B148-22CD5F2AB528.jpeg
new file mode 100644
index 0000000..7867dd6
Binary files /dev/null and b/img/cicd_workflow/1989B620-63EC-45C8-B148-22CD5F2AB528.jpeg differ
diff --git a/img/cicd_workflow/29CAB894-5281-4740-8E39-897E96571D6A.jpeg b/img/cicd_workflow/29CAB894-5281-4740-8E39-897E96571D6A.jpeg
new file mode 100644
index 0000000..d8f39b5
Binary files /dev/null and b/img/cicd_workflow/29CAB894-5281-4740-8E39-897E96571D6A.jpeg differ
diff --git a/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg b/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg
new file mode 100644
index 0000000..ef17b85
Binary files /dev/null and b/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg differ
diff --git a/img/cicd_workflow/5162B6A2-67C8-4EAD-BE7A-992D0AE90CD1_4_5005_c.jpeg b/img/cicd_workflow/5162B6A2-67C8-4EAD-BE7A-992D0AE90CD1_4_5005_c.jpeg
new file mode 100644
index 0000000..a783161
Binary files /dev/null and b/img/cicd_workflow/5162B6A2-67C8-4EAD-BE7A-992D0AE90CD1_4_5005_c.jpeg differ
diff --git a/img/cicd_workflow/51656174-4F3A-4A73-94FA-7E12D5B6FF27.jpeg b/img/cicd_workflow/51656174-4F3A-4A73-94FA-7E12D5B6FF27.jpeg
new file mode 100644
index 0000000..da1b53b
Binary files /dev/null and b/img/cicd_workflow/51656174-4F3A-4A73-94FA-7E12D5B6FF27.jpeg differ
diff --git a/img/cicd_workflow/6A1478C7-3824-47F5-9E48-5BC04FB20B3E.jpeg b/img/cicd_workflow/6A1478C7-3824-47F5-9E48-5BC04FB20B3E.jpeg
new file mode 100644
index 0000000..ea304bd
Binary files /dev/null and b/img/cicd_workflow/6A1478C7-3824-47F5-9E48-5BC04FB20B3E.jpeg differ
diff --git a/img/cicd_workflow/7A715483-ABF1-44C1-AC6F-CDED1623CC07_4_5005_c.jpeg b/img/cicd_workflow/7A715483-ABF1-44C1-AC6F-CDED1623CC07_4_5005_c.jpeg
new file mode 100644
index 0000000..7d60793
Binary files /dev/null and b/img/cicd_workflow/7A715483-ABF1-44C1-AC6F-CDED1623CC07_4_5005_c.jpeg differ
diff --git a/img/cicd_workflow/902CAC66-44A6-457E-BF87-534010FE6585.jpeg b/img/cicd_workflow/902CAC66-44A6-457E-BF87-534010FE6585.jpeg
new file mode 100644
index 0000000..83222b3
Binary files /dev/null and b/img/cicd_workflow/902CAC66-44A6-457E-BF87-534010FE6585.jpeg differ
diff --git a/img/cicd_workflow/962BFAD9-5695-4369-B2D5-F4185C229CCB.jpeg b/img/cicd_workflow/962BFAD9-5695-4369-B2D5-F4185C229CCB.jpeg
new file mode 100644
index 0000000..dd7b5d1
Binary files /dev/null and b/img/cicd_workflow/962BFAD9-5695-4369-B2D5-F4185C229CCB.jpeg differ
diff --git a/img/cicd_workflow/B5B15323-7379-4332-AEAC-7E70DBE2F924.jpeg b/img/cicd_workflow/B5B15323-7379-4332-AEAC-7E70DBE2F924.jpeg
new file mode 100644
index 0000000..b14320e
Binary files /dev/null and b/img/cicd_workflow/B5B15323-7379-4332-AEAC-7E70DBE2F924.jpeg differ
diff --git a/img/cicd_workflow/BFE0DB23-148B-4D0E-8C4D-C7DB51570593.jpeg b/img/cicd_workflow/BFE0DB23-148B-4D0E-8C4D-C7DB51570593.jpeg
new file mode 100644
index 0000000..e557c58
Binary files /dev/null and b/img/cicd_workflow/BFE0DB23-148B-4D0E-8C4D-C7DB51570593.jpeg differ
diff --git a/img/cicd_workflow/CB12C170-A17C-4C1A-8078-2CC67B8BAB31.jpeg b/img/cicd_workflow/CB12C170-A17C-4C1A-8078-2CC67B8BAB31.jpeg
new file mode 100644
index 0000000..369a22d
Binary files /dev/null and b/img/cicd_workflow/CB12C170-A17C-4C1A-8078-2CC67B8BAB31.jpeg differ
diff --git a/img/cicd_workflow/D48B0EAD-D0A0-40D3-AD19-0A19F83DD39E.jpeg b/img/cicd_workflow/D48B0EAD-D0A0-40D3-AD19-0A19F83DD39E.jpeg
new file mode 100644
index 0000000..fa47e8c
Binary files /dev/null and b/img/cicd_workflow/D48B0EAD-D0A0-40D3-AD19-0A19F83DD39E.jpeg differ
diff --git a/img/cicd_workflow/F595066F-EE0B-4086-AD92-5BAF081792F9.jpeg b/img/cicd_workflow/F595066F-EE0B-4086-AD92-5BAF081792F9.jpeg
new file mode 100644
index 0000000..50d0b31
Binary files /dev/null and b/img/cicd_workflow/F595066F-EE0B-4086-AD92-5BAF081792F9.jpeg differ
diff --git a/img/cicd_workflow/feature_release.json b/img/cicd_workflow/feature_release.json
new file mode 100644
index 0000000..614a780
--- /dev/null
+++ b/img/cicd_workflow/feature_release.json
@@ -0,0 +1 @@
+[{"processDefinitionConnects":"[{\"endPointSourceId\":\"tasks-41733\",\"endPointTargetId\":\"tasks-74247\"},{\"endPointSourceId\":\"tasks-71427\",\"endPointTargetId\":\"tasks-41733\"}]","processDefinitionJson":"{\"tenantId\":18,\"globalParams\":[{\"prop\":\"port\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"8098\"},{\"prop\":\"keyword\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"snapshot\"},{\"prop\":\"java8_path\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"/Librar [...]
\ No newline at end of file
diff --git a/img/cicd_workflow/packaging.json b/img/cicd_workflow/packaging.json
new file mode 100644
index 0000000..6849b9f
--- /dev/null
+++ b/img/cicd_workflow/packaging.json
@@ -0,0 +1 @@
+[{"processDefinitionConnects":"[{\"endPointSourceId\":\"tasks-93001\",\"endPointTargetId\":\"tasks-28221\"},{\"endPointSourceId\":\"tasks-28221\",\"endPointTargetId\":\"tasks-87137\"},{\"endPointSourceId\":\"tasks-87137\",\"endPointTargetId\":\"tasks-73462\"},{\"endPointSourceId\":\"tasks-73462\",\"endPointTargetId\":\"tasks-60945\"},{\"endPointSourceId\":\"tasks-60945\",\"endPointTargetId\":\"tasks-51828\"}]","processDefinitionJson":"{\"tenantId\":18,\"globalParams\":[{\"prop\":\"port\" [...]
\ No newline at end of file
diff --git a/img/cicd_workflow/rollback.json b/img/cicd_workflow/rollback.json
new file mode 100644
index 0000000..eedfe9c
--- /dev/null
+++ b/img/cicd_workflow/rollback.json
@@ -0,0 +1 @@
+[{"processDefinitionConnects":"[{\"endPointSourceId\":\"tasks-71510\",\"endPointTargetId\":\"tasks-24315\"},{\"endPointSourceId\":\"tasks-34109\",\"endPointTargetId\":\"tasks-71510\"}]","processDefinitionJson":"{\"tenantId\":18,\"globalParams\":[{\"prop\":\"port\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"8098\"},{\"prop\":\"keyword\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"release\"},{\"prop\":\"java8_path\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"/Library [...]
\ No newline at end of file
diff --git a/zh-cn/blog/cicd_workflow.html b/zh-cn/blog/cicd_workflow.html
new file mode 100644
index 0000000..a8f13a3
--- /dev/null
+++ b/zh-cn/blog/cicd_workflow.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+  <meta name="keywords" content="cicd_workflow">
+  <meta name="description" content="cicd_workflow">
+  <title>cicd_workflow</title>
+  <link rel="shortcut icon" href="/img/favicon.ico">
+  <link rel="stylesheet" href="/build/vendor.e328afe.css">
+  <link rel="stylesheet" href="/build/blog.md.fd8b187.css">
+</head>
+<body>
+  <div id="root"><div class="blog-detail-page" data-reactroot=""><header class="header-container header-container-dark"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="/img/hlogo_white.svg"/></a><div class="search search-dark"><span class="icon-search"></span></div><span class="language-switch language-switch-dark">En</span><div class="header-menu"><img class="header-menu-toggle" src="/img/system/menu_white.png"/><div><ul class="ant-menu whiteClass ant-menu-li [...]
+<h3>CI/CD 流程介绍</h3>
+<p>CI/CD中包含一系列步骤,来自动化我们开发阶段的软件交付过程,使其可以频繁地输送准确的代码。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题。</p>
+<p>这里的CI 指持续集成,这个过程是自动化的,以确保团队能够以可靠和可重复的方式构建、测试和打包他们的应用程序。 CI 有助于简化代码更改流程,从而增加开发人员进行更改和改进软件的时间。</p>
+<p>CD 指持续交付/持续部署。持续交付代表将完成的代码自动交付到测试和开发等环境中。 CD 为将代码交付到这些环境提供了一种自动化且一致的方式。持续部署是持续交付的下一步。通过自动化测试的每个更改都会自动投入生产环境中,从而在生产环境下部署。</p>
+<p>这个针对项目的CI/CD工作流主要有三个:打包(packaging),回滚(roll back),特性发布(feature release)。</p>
+<p>打包阶段的主要内容是检查本地代码库是否为最新版本,后进行构建,测试,部署到模拟环境中。若打包顺利完成,本地会产生一个新的版本,并且可以在模拟环境中检查此新版本。</p>
+<p>回滚的目的是显示已有的发布版本,调用其中一个选定的版本,将其部署到生产环境。特性发布的内容与回滚大体相似,但不同的是,在这个工作流中,显示已有的特性发布版本,再调用其中一个并部署到生产环境。</p>
+<h3>基于 DS 实现 CI/CD pipeline 实例</h3>
+<p>基于现有的ds功能,我们找到一个小型项目当作此次尝试的范例。被选中的项目<a href="https://github.com/jonashackt/spring-boot-vuejs">spring-boot-vuejs</a> 具有前端和后端,可以较为直观的看到部署的结果,它的CI/CD流程也比较简明。这个实例中,我们采用的部署形式是本地部署/单机部署,不考虑到多台机器或者集群的影响。在为项目工作流配置完全局变量和本地变量后,便可以使其上线运行,完成的工作流如下。</p>
+<h5>Packaging</h5>
+<p>这个工作流共包含6个shell节点,用于CI/CD流程中的代码获取,构建,测试,打包,预发布(staging)。详见导出的<a href="/img/cicd_workflow/feature_release.json">工作流文件</a></p>
+<p><img src="/img/cicd_workflow/7A715483-ABF1-44C1-AC6F-CDED1623CC07_4_5005_c.jpeg" alt="avatar"></p>
+<ul>
+<li>节点1: check repo
+这个节点的目的是检查本地是否已经有最新的代码版本,分别通过git clone和git pull获取代码库和更新。环节的开始和结束,均会在日志中有提醒。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-comment"># Check Java version, Maven version and Git Branch</span>
+<span class="hljs-built_in">echo</span> Show supporting info
+java -version
+mvn --version
+<span class="hljs-comment"># choose a local directory to store this project</span>
+<span class="hljs-comment"># cd /opt/repo</span>
+
+<span class="hljs-built_in">echo</span> Start of repo checkout/update
+<span class="hljs-comment"># Check if project&#x27;s repo is under the chosen directory. </span>
+<span class="hljs-comment"># If available, pull the latest version, if not, clone</span>
+DIR=<span class="hljs-string">&quot;<span class="hljs-variable">${project_folder}</span>&quot;</span>
+<span class="hljs-keyword">if</span> [ -d <span class="hljs-string">&quot;<span class="hljs-variable">$DIR</span>&quot;</span> ]; <span class="hljs-keyword">then</span>
+  <span class="hljs-comment">### Pull latest if $DIR exists ###</span>
+  <span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;Pass: <span class="hljs-variable">${DIR}</span> exist&quot;</span>
+  <span class="hljs-built_in">cd</span> <span class="hljs-variable">$DIR</span>
+  git status
+  git pull origin master
+  <span class="hljs-built_in">echo</span> spring-boot-vuejs
+<span class="hljs-keyword">else</span>
+  <span class="hljs-comment">### Clone if $DIR does NOT exist ###</span>
+  <span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;Error: <span class="hljs-variable">${DIR}</span> not found. Clone repo&quot;</span>
+  git <span class="hljs-built_in">clone</span> https://github.com/jonashackt/spring-boot-vuejs
+  <span class="hljs-built_in">cd</span> spring-boot-vuejs
+<span class="hljs-keyword">fi</span>
+<span class="hljs-built_in">echo</span> End of repo checkout/update
+</code></pre>
+<p>如果节点运行成功,本地已存在目标代码库,此时可以执行git pull (前提保证本地更新已经提交) 。</p>
+<p><img src="/img/cicd_workflow/6A1478C7-3824-47F5-9E48-5BC04FB20B3E.jpeg" alt="avatar"></p>
+<ul>
+<li>节点2: build with java8
+这个节点基于项目使用java的maven框架,进行构建。因为此实例使用的java版本为8和16。以本地默认java版本java8执行命令。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span> 
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+JAVA_HOME=<span class="hljs-variable">${java8_path}</span>
+java -version
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+npm config <span class="hljs-built_in">set</span> registry http://registry.npmjs.org   
+mvn -B install --no-transfer-progress 
+</code></pre>
+<p>如果节点运行成功,日志中会出现“BUILD SUCCESS”,显示构建完成并且成功。</p>
+<p><img src="/img/cicd_workflow/D48B0EAD-D0A0-40D3-AD19-0A19F83DD39E.jpeg" alt="avatar"></p>
+<ul>
+<li>节点3: test with java8
+这个节点在同一个java版本下运行单元测试。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span> 
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+mvn -B verify --no-transfer-progress 
+</code></pre>
+<p>如果节点运行成功,日志中会出现“BUILD SUCCESS”,显示测试成功。</p>
+<p><img src="/img/cicd_workflow/CB12C170-A17C-4C1A-8078-2CC67B8BAB31.jpeg" alt="avatar"></p>
+<ul>
+<li>节点4: build with java16
+这个节点基于项目使用java的maven框架,进行构建。因为已经用java8进行了构建,所以这里更换为java16后执行构建命令。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span> 
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+java -version
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+JAVA_HOME=<span class="hljs-variable">${java16_path}</span>
+<span class="hljs-built_in">export</span> JAVA_HOME;
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+npm config <span class="hljs-built_in">set</span> registry http://registry.npmjs.org   
+mvn -B install --no-transfer-progress 
+</code></pre>
+<p>如果节点运行成功,日志中会出现”BUILD SUCCESS“,显示构建成功。</p>
+<p><img src="/img/cicd_workflow/29CAB894-5281-4740-8E39-897E96571D6A.jpeg" alt="avatar"></p>
+<ul>
+<li>节点5: test with java16
+这个节点在同一个java版本下运行单元测试。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span> 
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+mvn -B verify --no-transfer-progress 
+</code></pre>
+<p>如果节点运行成功,日志中会出现”BUILD SUCCESS“,显示测试成功。</p>
+<p><img src="/img/cicd_workflow/B5B15323-7379-4332-AEAC-7E70DBE2F924.jpeg" alt="avatar"></p>
+<ul>
+<li>节点6: staging
+这个节点在项目预发布的模拟环境中部署,本地部署到端口localhost:5000。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span> 
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+JAVA_HOME=<span class="hljs-variable">${java8_path}</span>
+<span class="hljs-built_in">export</span> JAVA_HOME;
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+<span class="hljs-built_in">echo</span> START
+nohup java -Djava.security.egd=file:/dev/./urandom -jar ./backend/target/backend-0.0.3-SNAPSHOT.jar --server.port=<span class="hljs-variable">${staging_port}</span> &gt; buildres_staging.txt 2&gt;&amp;1 &amp;
+<span class="hljs-built_in">echo</span> END
+</code></pre>
+<p>如果节点运行成功,因为使用nohup命令,部署至本地端口的命令在后台进行,日志中会出现“START”和“END”代表此命令的执行情况。日志显示如下</p>
+<p><img src="/img/cicd_workflow/1989B620-63EC-45C8-B148-22CD5F2AB528.jpeg" alt="avatar"></p>
+<p>同时,因为staging_port变量在此处被设置为localhost:5000,所以在本地也可以看到部署完成的页面如下</p>
+<p><img src="/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg" alt="avatar"></p>
+<h5>Rollback</h5>
+<p>这个工作流共包含三个shell节点,用于完成项目版本回滚,也相当于CI/CD流程中的生产部署环节。详见导出的<a href="/img/cicd_workflow/rollback.json">工作流文件</a></p>
+<p><img src="/img/cicd_workflow/12D3F0CE-18FE-4163-951A-4E0734A42EC2_4_5005_c.jpeg" alt="avatar"></p>
+<ul>
+<li>节点1: kill process on port
+这个节点用于关闭要部署的端口的现有进程,为节点3作准备。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+<span class="hljs-keyword">if</span> [[ $(lsof -ti:<span class="hljs-variable">${port_number}</span> | wc -l) -gt 0 ]]; 
+	<span class="hljs-keyword">then</span> 
+    	<span class="hljs-built_in">echo</span> process found
+        sudo <span class="hljs-built_in">kill</span> -9 $(lsof -ti:<span class="hljs-variable">${port_number}</span>); 
+    <span class="hljs-keyword">fi</span>
+</code></pre>
+<p>如果节点运行成功,要检查的端口的确有进程,日志中会显示如下图“process found”,之后这些进程会被关闭。</p>
+<p><img src="/img/cicd_workflow/962BFAD9-5695-4369-B2D5-F4185C229CCB.jpeg" alt=""></p>
+<ul>
+<li>节点2: display available version
+这个节点用于展示本地所有可以被调用的发布版本。假定所有的发布版本都遵循命名格式backend-X.0.0-RELEASE.jar,那么所有包含关键字“RELEASE ”的版本都会被筛选并显示出来,供下一步使用。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+<span class="hljs-comment"># see previous releases</span>
+find /opt/repo/spring-boot-vuejs/backend/target -iname <span class="hljs-string">&#x27;*${keyword}*&#x27;</span>
+</code></pre>
+<p>如果节点运行成功,本地所有发布版本都会被列举出来,以供选择调用。</p>
+<p><img src="/img/cicd_workflow/51656174-4F3A-4A73-94FA-7E12D5B6FF27.jpeg" alt=""></p>
+<ul>
+<li>节点3: roll back
+这个节点用于选定回滚的目标版本,并且本地部署到端口。部署成功则可以在本地8098端口显示页面。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+JAVA_HOME=<span class="hljs-variable">${java8_path}</span>
+<span class="hljs-built_in">export</span> JAVA_HOME;
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+<span class="hljs-comment"># fill in desired version to roll back to previous release</span>
+<span class="hljs-built_in">echo</span> START
+nohup java -Djava.security.egd=file:/dev/./urandom -jar ./backend/target/backend-1.0.0-RELEASE.jar --server.port=<span class="hljs-variable">${port_number}</span> &gt; buildres_production.txt 2&gt;&amp;1 &amp;
+<span class="hljs-built_in">echo</span> END
+</code></pre>
+<p>如果节点运行成功,部署至本地端口的nohup命令在后台进行,日志中出现“START”和“END”代表此命令的执行情况。日志显示如下</p>
+<p><img src="/img/cicd_workflow/902CAC66-44A6-457E-BF87-534010FE6585.jpeg" alt=""></p>
+<p>同时,因为port_number变量在此处被设置为localhost:8098,所以在本地也可以看到部署完成的页面如下</p>
+<p><img src="/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg" alt=""></p>
+<h5>Feature Release</h5>
+<p>这个工作流共包含三个shell节点,用于完成项目版本回滚,也相当于CI/CD流程中的生产部署环节。详见导出的<a href="/img/cicd_workflow/feature_release.json">工作流文件</a></p>
+<p><img src="/img/cicd_workflow/5162B6A2-67C8-4EAD-BE7A-992D0AE90CD1_4_5005_c.jpeg" alt="avatar"></p>
+<ul>
+<li>节点1: kill process on port
+这个节点用于关闭要部署的端口的现有进程,为节点3作准备。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+<span class="hljs-keyword">if</span> [[ $(lsof -ti:<span class="hljs-variable">${port_number}</span> | wc -l) -gt 0 ]]; 
+	<span class="hljs-keyword">then</span> 
+    	<span class="hljs-built_in">echo</span> process found
+        sudo <span class="hljs-built_in">kill</span> -9 $(lsof -ti:<span class="hljs-variable">${port_number}</span>); 
+    <span class="hljs-keyword">fi</span>
+</code></pre>
+<p>如果要检查的端口的确有进程,日志中会显示如下图“process found”,之后这些进程会被关闭。</p>
+<p><img src="/img/cicd_workflow/00282F58-D216-470A-A65D-90EE09C76DED.jpeg" alt=""></p>
+<ul>
+<li>节点2: display available version
+这个节点用于展示本地所有可以被调用的特性发布版本。假定所有的特性发布版本都遵循命名格式backend-0.0.1-SNAPSHOT.jar,那么所有包含关键字“SNAPSHOT”的版本都会被筛选并显示出来,供下一步使用。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+<span class="hljs-comment"># see previous releases</span>
+find /opt/repo/spring-boot-vuejs/backend/target -iname <span class="hljs-string">&#x27;*${keyword}*&#x27;</span>
+</code></pre>
+<p>如果节点运行成功,本地所有特性发布版本都会被列举出来,以供选择调用。</p>
+<p><img src="/img/cicd_workflow/F595066F-EE0B-4086-AD92-5BAF081792F9.jpeg" alt=""></p>
+<ul>
+<li>节点3: release
+这个节点用于选定特性发布的目标版本,并且本地部署到端口。部署成功则可以在本地8098端口显示页面。</li>
+</ul>
+<pre><code class="language-sh"><span class="hljs-built_in">pwd</span>
+<span class="hljs-built_in">cd</span> <span class="hljs-variable">${project_folder}</span>
+
+JAVA_HOME=<span class="hljs-variable">${java8_path}</span>
+<span class="hljs-built_in">export</span> JAVA_HOME;
+<span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
+
+<span class="hljs-comment"># fill in desired version to roll back to previous release</span>
+<span class="hljs-built_in">echo</span> START
+nohup java -Djava.security.egd=file:/dev/./urandom -jar ./backend/target/backend-0.0.3-SNAPSHOT.jar --server.port=<span class="hljs-variable">${port_number}</span> &gt; buildres_production.txt 2&gt;&amp;1 &amp;
+<span class="hljs-built_in">echo</span> END
+</code></pre>
+<p>如果节点运行成功,部署至本地端口的nohup命令在后台进行,日志中出现“START”和“END”代表此命令的执行情况。日志显示如下</p>
+<p><img src="/img/cicd_workflow/BFE0DB23-148B-4D0E-8C4D-C7DB51570593.jpeg" alt=""></p>
+<p>同时,因为port_number变量在此处被设置为localhost:8098,所以在本地也可以看到部署完成的页面如下</p>
+<p><img src="/img/cicd_workflow/3AB6D6CE-CDB2-451E-9524-BF2224C947C0.jpeg" alt=""></p>
+<h3>使用DS构建工作流不足之处</h3>
+<h5>项目中觉得使用ds来构建ci/cd 工作流不方便的地方:</h5>
+<p>目前DS没有对于工作流或者节点的版本管理,例如不能给一个工作流的当前版本take snapshot,以便后续需要时使用。现在需要通过GitHub、Gitlab或者其他版本管理平台,才能完成例如将单个节点回滚到历史版本的任务。如果用户从DAG中删除一个节点或节点中的任务,并重新部署它,那么与该任务相关的元数据(metadata)就会失去。</p>
+<p>在单机部署时,工作流中所有节点并不处在同一个独立的虚拟环境里。每个节点都指向一个/tmp/dolphinscheduler/exec/process/下的不同路径,如果需要获取之前节点的信息,需要指定一个文件夹存储项目的源代码,每次进入文件夹来获取代码。但这也可以通过设置全局变量来解决。</p>
+<h5>与现有的CI/CD工具相比</h5>
+<p>对于***本地部署***的ds来说,虚拟环境完全依赖本机的环境。例如在这次的工作流中,需要提前在本地设置好需要的java版本和maven 版本,虚拟环境中的相应命令才能执行。然而在Github Actions中,运行工作流的环境可以通过yaml文件内的设置,直接拉取对应的Docker image镜像而生成,独立于本地环境。</p>
+<p>与Github Actions相比,ds需要手动上线和启动CI/CD工作流,不能用类似on:[push] 这种GitHub event作为触发机制。</p>
+</section><footer class="footer-container"><div class="footer-body"><div><h3>联系我们</h3><h4>有问题需要反馈?请通过以下方式联系我们。</h4></div><div class="contact-container"><ul><li><img class="img-base" src="/img/emailgray.png"/><img class="img-change" src="/img/emailblue.png"/><a href="/zh-cn/community/development/subscribe.html"><p>邮件列表</p></a></li><li><img class="img-base" src="/img/twittergray.png"/><img class="img-change" src="/img/twitterblue.png"/><a href="https://twitter.com/dolphinschedule"><p>Twitt [...]
+  <script src="//cdn.jsdelivr.net/npm/react@15.6.2/dist/react-with-addons.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/react-dom@15.6.2/dist/react-dom.min.js"></script>
+  <script>window.rootPath = '';</script>
+  <script src="/build/vendor.e2c05dc.js"></script>
+  <script src="/build/blog.md.79dd3d0.js"></script>
+  <script>
+    var _hmt = _hmt || [];
+    (function() {
+      var hm = document.createElement("script");
+      hm.src = "https://hm.baidu.com/hm.js?4e7b4b400dd31fa015018a435c64d06f";
+      var s = document.getElementsByTagName("script")[0];
+      s.parentNode.insertBefore(hm, s);
+    })();
+  </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/zh-cn/blog/cicd_workflow.json b/zh-cn/blog/cicd_workflow.json
new file mode 100644
index 0000000..0f2e707
--- /dev/null
+++ b/zh-cn/blog/cicd_workflow.json
@@ -0,0 +1,6 @@
+{
+  "filename": "cicd_workflow.md",
+  "__html": "<h1>用DolphinScheduler建立java项目的CI/CD工作流</h1>\n<h3>CI/CD 流程介绍</h3>\n<p>CI/CD中包含一系列步骤,来自动化我们开发阶段的软件交付过程,使其可以频繁地输送准确的代码。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题。</p>\n<p>这里的CI 指持续集成,这个过程是自动化的,以确保团队能够以可靠和可重复的方式构建、测试和打包他们的应用程序。 CI 有助于简化代码更改流程,从而增加开发人员进行更改和改进软件的时间。</p>\n<p>CD 指持续交付/持续部署。持续交付代表将完成的代码自动交付到测试和开发等环境中。 CD 为将代码交付到这些环境提供了一种自动化且一致的方式。持续部署是持续交付的下一步。通过自动化测试的每个更改都会自动投�
 �生产环境中,从而在生产环境下部署。</p>\n<p>这个针对项目的CI/CD工作流主要有三个:打包(packaging),回滚(roll back),特性发布( [...]
+  "link": "/dist/zh-cn/blog/cicd_workflow.html",
+  "meta": {}
+}
\ No newline at end of file