index.json 828.8 KB
Newer Older
LinuxSuRen's avatar
LinuxSuRen 已提交
1
[
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2
    {
3
        "uri": "https://jenkins-zh.cn/about/sponsors-list/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
4 5 6 7 8
        "title": "社区捐助",
        "type": "about",
        "date": "2019-09-07 00:00:00 +0000 UTC",
        "tags": [],
        "description": "社区捐助",
9
        "content": " 社区得以持续、健康地发展,需要很多方面的支持,尤其对于社区的基础运营、活动组织上,资金和物资的捐助是非常重要的。\n用途 对于所收到的资金、物资捐助,我们都会用于社区基础设施(域名、服务器等)、线下活动、社区成员奖励。\n列表 为了对给予社区捐助的朋友们表示感谢,我们在此列出来:\n   捐助者 金额(单位:元) 日期 备注      geshujiang  100 2019-05-11 活动链接   霍格沃兹测试学院 10,000 2019-11-05 社区捐赠    资金去向    用途 金额 日期 申请人     阿里云服务器带宽充值 100 2019.10.24  linuxsuren    购买阿里云服务器 5,640 2019.11.8  linuxsuren    购买梯子帐号(一年) 276 2020.02.23  linuxsuren , yJunS , donhui , linan607     ",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
10 11 12 13 14
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
15
    {
16
        "uri": "https://jenkins-zh.cn/about/code-of-conduct/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
17
        "title": "行为规范",
LinuxSuRen's avatar
LinuxSuRen 已提交
18 19
        "type": "about",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
20 21
        "tags": [],
        "description": "行为规范",
LinuxSuRen's avatar
LinuxSuRen 已提交
22 23 24 25 26
        "content": " 留言 留言之前需要使用 GitHub 账号登陆。大家要注意文明用语,严禁攻击、诋毁、灌水、广告等无关的话。对于违反人,一经发现将会被拉入黑名单。\n提问 欢迎每一位朋友在这里提出与 Jenkins 或相关领域的技术问题,但是,在提问之前建议先在搜索引擎和本站中进行搜索。\n问题至少要包含如下部分:\n 场景以及问题是如何发生的,方便阅读的人复现 软件、环境相关版本信息 日志、截图等(建议使用附件的方式)  出于对回答问题者的尊重,请得到解决方案后及时表示感谢,或者从其他地方得到答案后添加相关链接以及说明。\nGitHub 请您使用同一个 GitHub 账号来与大家交流,不欢迎使用所谓的“小号”。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
27
    },
28 29 30 31 32 33 34 35 36 37 38 39 40
    {
        "uri": "https://jenkins-zh.cn/meeting/2020-03-04/",
        "title": "",
        "type": "meeting",
        "date": "2020-03-04 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " GSoC\n Jenkins 发行版(https://community.jenkins-zh.cn/t/jenkins/241) 有两个印度的学生有兴趣 每个人的配置保存到哪里?  官方 用户  https://github.com/jenkins-zh/jenkins-cli/pull/340/files  下次在线研讨会\n 时间,提前到八点半  修改社区的日历为:每周八点半,持续一个半小时  直播  对带宽+电脑资源要求比较高    ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
41 42 43 44 45 46 47 48 49 50 51 52 53
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/03/2020-03-02-good-to-great-with-devops/",
        "title": "DevOps 的出色表现",
        "type": "wechat",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": ["DevOps", "DevOps 状态", "DevOps 状态报告", "精英绩效", "DevOps 指标", "J 转换曲线"],
        "description": "重点介绍了 2019 年 DevOps 状态报告的一些发现,包括 DevOps 的出现和盛行",
        "content": " DevOps 不断发展,自从2009年提出此术语以来,DevOps 的状态每年都呈指数级增长。在2019年飞速发展的过程中,各种规模和形态的组织(从企业到初创公司)在 DevOps 方面都展现了极大的热情。每个组织都有其自己的 DevOps故事,其中一些故事尚未开始,一些故事还处于婴儿期,有些故事已经成熟,有些故事已经达到顶峰。 不同于其他故事,DevOps 故事源于不断改进。\n随着企业逐渐变得数字化和软件驱动,人们对 DevOps 旅程的本质和可能性有了更大的认识。不仅工程师或技术领导者,甚至商业领导者都对 DevOps 的概念、实践和应用非常感兴趣。对于实现商业成功的 DevOps 的需求已得到越来越广泛的接受。\n《 2019 年 DevOps 状态报告》作为大量在线资源的提供者之一,可用于解和学习 DevOps 如何塑造跨行业的软件交付。该报告极大地总结了软件交付的趋势和挑战,它可以帮助团队研究可用于提升软件交付能力并最终成就卓越。\n在此报告中,IT 性能称为软件交付能力,以区分软件交付工作与 IT 服务台和其他支撑功能。这是一个期待已久的可喜变化。我也喜欢的关键更改之一是增加了运营指标以完成软件交付周期。该报告重点介绍了五个被称为“软件交付和运营(SDO)性能指标”的度量或指标,它们侧重于系统级结果。这有助于避免软件度量标准的常见陷阱,后者常常使不同的功能相互冲突,并导致以牺牲总结果为代价的局部优化。\n该报告重点介绍了软件交付能力的四个方面,如下所示:\n 部署频率 – 对于您从事的主应用程序或服务,您的组织多久部署一次代码? 变更的前置时间 – 对于您从事的主应用程序或服务,您的变更前置时间是多少(即,从代码提交到成功在生产中运行的代码需要多长时间)? 恢复服务的时间 – 对于您正在使用的主应用程序或服务,发生服务事件(例如计划外中断或服务受损)时,恢复服务通常需要多长时间? 变更失败率 – 对于您使用的主应用程序或服务,导致服务质量下降或随后需要修复(例如,导致服务受损、服务中断,需要修改程序、回滚、向前修复、修补程序)的变更的百分比?  然后对这四个方面进行度量,以对四个类别的性能进行排名:精英、高级、中级和低级。下表(从报告中引用)指示了各个方面的详细信息。\n我强烈建议添加到此列表中的另一个方面是“团队敬业度指数”,即团队的快乐程度和参与度。我认为团队绩效与团队敬业度成正比。团队敬业度越高,即团队越快乐越敬业,他们产生的结果就越好。\n报告中的另一个主题是“ J 转换曲线”。下图突出显示了自动化如何帮助绩效低下的人员提升到中等性能水平,然后测试需求、技术负担和复杂性增加导致手动操作,从而导致进度变慢。这是一个有趣且值得注意的观察。它强调了自动化并不总是答案。如果您使错误的流程自动化,那么您得到的只是错误的结果,而且更快。\n无休止的改进、学习、共享和利用专业知识可将您带到高水平或精英绩效水平 – 将团队提升为精英绩效的旅程需要的不仅仅是工具。在各个级别(即团队级别、领导级别和赞助者级别)的坚持、恒心和毅力对于从低绩效水平或中绩效水平取得突破以发挥团队最大潜力至关重要。如果我们踏上精英绩效之旅,您会发现自动化、技术实践和持续改进计划是您旅途的催化剂。鉴于测试需求、技术债务和日益增加的复杂性将成为您的阻碍,我发现锚定和引擎(帆船回顾展)格式提供了一种快速而有趣的方法,可在一幅图片中(如下所示)可视化催化剂(引擎)和阻滞剂(锚定)。\n行业看到了更高的精英绩效 该报告证实,精英表演者的比例几乎增加了两倍,低表现者的比例下降了,中等表演者的比例上升了。要注意的一项主要观察结果是,从低性能到中性能再到高性能的移动不是单向的。当面对复杂性增加时,团队(从 J 曲线中突出显示)可以从高位降为中级,也可以从中级降为低级。总体而言,很高兴看到向上增加。\n前进之路 软件交付性能可以通过多种方式确定业务成果。 组织推动软件交付绩效的能力包括文化,技术实践,清晰的变更流程,持续交付和基于价值的成果。 这些功能并不是一蹴而就的,需要对组织 DNA 进行根本性的改变。\n根据我在不同行业和公司中工作的经验,我可以确认这些软件交付能力集群不是静态的。上面列出的任何功能的更改都会对软件交付能力产生影响,您可能会发现能力集群在两个方向上都从一个级别波动到另一个级别。关键是要保持专注并通过定期将其嵌入组织的工作方式中来维持它。\n",
        "auhtor": "Sandeep Joshi",
        "translator": "zhaoying818",
        "original": "https://dzone.com/articles/good-to-great-with-devops",
        "poster": "img1.png"
    },
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-28-t-mobile-and-jenkins-case-study/",
        "title": "T-Mobile 和 Jenkins 案例研究",
        "type": "wechat",
        "date": "2020-02-28 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "T-Mobile"],
        "description": "聊聊 POET Pipeline 对流水线的改变以及给您带来的巨大的价值",
        "content": " Jenkins 在 T-Mobile 节省数千小时和数百万美元 大多数人都知道 T-Mobile 是无线服务提供商。毕竟,我们拥有国际化的业务,并且是美国第三大移动运营商。但是我们还是一家技术公司,提供的新产品包括 TVision 家庭电视服务,T-Mobile Money 个人银行产品以及 SyncUp Drive 车辆监控和路边辅助设备。\n在幕后,T-Mobile 还是开源社区的领导者。我们已经在 GitHub 上共享了 35+ 个代码存储库(包括我们的 POET 流水线框架自动化库),以通过采用健壮和智能的做法来加快 CI/CD 周期,从而帮助其他组织支持内部和外部客户。\n我是 T-Mobile 系统可靠性工程(SRE)部门的高级系统可靠性工程师。我们的团队成功地将 POET 实施的第一阶段推广到了 30 多个团队。这是一个巨大的成功,并且计划使用结合在 Kubernetes 集群上运行的 Jenkins 和 CloudBees Core 的稳定、可靠的 CI/CD 流水线,将其扩展到我们的 350 个开发团队和 5,000 个活跃用户。\n更少的插件,更多的 Master 我们从构建简化的基于容器的流水线基础结构开始,该基础结构可以集中管理并易于适应开发方法。结果使我们的开发团队有更多的精力专注于开发和测试应用程序,而不是维护 Jenkins 环境。\n然后,我们将在 master 中使用的 Jenkins 插件的数量从 200 个减少到了 4 个。有超过 1,000 种此类附加组件,包括构建工具,测试实用程序和云集成资源。它们是扩展平台的绝佳方法,但它们也是 Jenkins 的致命弱点,因为它们可能引起冲突。\n接下来,我们从一个单一的 Master 给我们所有的 Jenkins slave 提供动力变成了多个 Master,现在拥有 30 个流水线引擎,每个引擎为大约 10 个团队提供动力。此设置减少了 CPU 负载和其他瓶颈,同时允许 T-Mobile 的 DevOps 团队继续享受水平扩展的优势。\n在两分钟内启动 Jenkins 流水线 这项工作的成果是,我的 SRE 团队现在可以在大约两分钟的时间内从 Docker 镜像启动 Jenkins 主机,对其进行测试并将其推广到我们的生产环境。然后,各个团队可以自定义其 CI/CD 流水线,以满足特定项目的需求。我们允许这些团队扩展平台,但我们将加载项列表限制为 16 个核心插件。这些插件是在 Docker 容器中预先配置的,每个团队都以相同的 CI/CD 流水线开始,然后可以在文件夹级别根据自己的喜好对其进行设置。\n这种简化且集中的方式来部署我们的流水线,使 SRE 团队能够将所有事情付诸行动,然后再加以解决。但这只是故事的一半。当我们的开发团队拥有简化的 CI/CD 流水线时,真正的魅力就会展现出来。他们不再需要担心底层的 Jenkins 技术,而可以将注意力转移到采用其解决方案上。\nPOET 流水线最大程度地减少了对 Jenkins Groovy 代码的需求,该代码繁琐,容易出错并且难以集成到第三方库中。相反,一切都从位于流水线源代码中的流水线定义文件开始,并创建步骤容器以执行构建,部署和其他流水线功能。\n我们在 POET 流水线中引入 40 个通用容器,因此我们的开发人员不必从头开始。当然,他们必须知道如何创建 Docker 容器以及如何编写 YAML 文件以扩展流水线功能。通过简化基础架构,减少插件数量并消除对 Groovy 的需求,我们使开发人员可以自由定义自己的流水线,而不必依赖集中的管理团队。\n我们的开发人员不再是基础架构工程师 为了进一步增强我们的开发人员的能力,我们编写了全面的 POET Pipeline 文档,包括易于理解的帮助文件,教程和视频,以进行自学成才和自助服务。这种宝贵的资源还释放了我们的流水线管理团队和开发人员的精力,使其可以专注于创新。\n本文档是我们采用的“以客户为中心”方法的一部分。我们将内部开发团队视为客户,而 POET Pipeline 是我们的产品。您能想象 T-Mobile 要求订户在每次通话时重建智能手机吗?还是让他们在发送短信之前与 CSR 对话?那我们为什么要要求我们的开发商兼任基础设施工程师呢?\n减少停机时间 除了使开发人员满意并简化管理任务之外,我们简化的 POET Pipeline 框架还大大减少了停机时间。我们的插件繁重的、单主机的 Jenkins 环境占用了 CPU 周期,引起了各种配置难题,并且不断下降。\n在任何给定的一周内,我们必须重新启动 Jenkins 两到三次。有时,我们的构建会对我们的环境造成很大的压力,以至于我们不得不在一夜之间重新启动它,并在团队无法工作时重置所有内容。借助 POET Pipeline,我们将停机时间减少到每年一次此类事件。\n扩大我们的成功 通过消除每个开发团队对流水线专家的需求,由于与 Jenkins 和 CloudBees Core 的合作,我们还节省了大量人工和成本。如果您将一个典型的工作年数定为 2,000 个小时,再乘以 350 个团队,那么您要计算的是数十万个小时和数千万美元。现在,我们可以将这些资源重新定向到构建收益产品中,从而更好地为 T-Mobile 的外部客户提供服务。\n这些数字很大,但不要让他们以为 POET 流水线不适合您。我们可能有数百个团队和数千名开发人员,但是 Jenkins 具有可扩展性,任何规模的组织都可以使用我们开发的工具。因此,我们选择与 GitHub 上的开源社区共享流水线。\n与世界一起创新 创新不是凭空发生的。通过将我们的代码发布给其他人使用和修改,我们正在帮助世界各地的开发人员将重点从管理流水线转移到构建更好的应用程序。反过来,我们将从更广泛的社区的智慧应用于我们的内部项目中受益。\n每个人都获得了一定的成果,但真正的赢家是 T-Mobile 的客户。他们可以期待提供新的和改进的产品,因为我们将花费更少的时间来管理流水线框架,而将更多的时间用于简化和改善生活的产品和服务上。\n",
        "auhtor": "Alyssa Tong and Ravi Sharma",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2020/02/10/t-mobile-case-study/",
        "poster": "t-mobile-and-jenkins.png"
    },
    {
        "uri": "https://jenkins-zh.cn/tutorial/management/agent/docker-jnlp/",
        "title": "基于 JNLP 协议的 Docker 代理节点",
        "type": "tutorial",
        "date": "2020-02-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "Jenkins 支持多种类型的代理节点,本篇教程介绍的是基于 JNLP 协议的 Docker 代理节点。\n步骤如下: 1. 在节点管理界面,新增一个代理节点;启动方式为:通过 Java Web 启动代理 2. 点击保存后,进入到该节点的状态页面 3. 参考下面的启动命令来启动 Docker 容器 * 注意替换 IP 为你的服务器地址,不能使用127.0.0.1或者 localhost * secret 可以从节点状态页面找到\ndocker run -u root -d --rm jenkins/slave:4.0.1-1-alpine java -jar /usr/share/jenkins/agent.jar -jnlpUrl http://192.168.31.239:8080/computer/jnlp/slave-agent.jnlp -secret ad36ea3aff1fea65a803f32e7020bd6c6b5866db9f587fb2079d308661691911 -workDir \u0026quot;/tmp\u0026quot;  如果希望了解更多这种代理节点的话,可以参考官方源码。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
80 81 82 83 84 85 86 87 88 89 90 91 92
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-24-jcli-v0.0.26/",
        "title": "Jenkins CLI 命令行 v0.0.26",
        "type": "wechat",
        "date": "2020-02-24 00:00:00 +0000 UTC",
        "tags": [],
        "description": "jcli-v0.0.26 发布",
        "content": " 本次版本发布,增加了两种包发行版:snapcraft、Chocolatey。snapcraft 是由 Ubuntu 提供的一个全新的 包管理器,它可以在 CentOS、Ubuntu、SUSE 等12种操作系统下使用。因此,Linux 用户可以更加方便地使用 jcli。 命令行自动补全的特性可以大幅提高用户的工作效率,除了 bash 的用户外,zsh 以及 powerShell 的用户,现在也可以使用 jcli 的命令补全特性了。\n🚀 功能  支持查看 jcli 的变更日志 (#328) @LinuxSuRen 支持根据父目录搜索任务 (#327) @LinuxSuRen 支持升级所有的插件 (#258) @yJunS 增加对 zsh 和 powerShell 的命令行补全的支持 (#296) @LinuxSuRen  🐛 缺陷修复  修复了无法启动非 LTS 的 Jenkins (#322) @LinuxSuRen 修复无法创建凭据的问题 (#325) @LinuxSuRen  📝 文档完善  增加对 snapcraft 的支持 (#321) @LinuxSuRen 增加对 Chocolatey 的支持 (#312) @LinuxSuRen 增加从 bintray 下载 jcli 的文档描述 (#299) @LinuxSuRen  👻 维护  在构建过程中,通过 GitHub Action 对临时文件的归档 (#333) @LinuxSuRen 升级依赖 github.com/spf13/cobra 从 0.0.5 到 0.0.6 (#332) @dependabot-preview 修复拼写错误 (#303) @afkbrb  🚦 测试  增加对交互式命令的测试用例 (#297) @LinuxSuRen  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "jenkins-cli.png"
    },
93 94 95 96 97 98 99 100 101 102 103 104 105
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-21-the-abc-of-devops-implementation-with-containerization-and-docker/",
        "title": "使用容器化和 Docker 实现 DevOps 的基础知识",
        "type": "wechat",
        "date": "2020-02-21 00:00:00 +0000 UTC",
        "tags": ["容器化", "Docker", "DevOps"],
        "description": "通过 Docker 和容器化,DevOps 可以更轻松、更快和更安全",
        "content": " DevOps 在 IT 行业中风靡一时。维基百科中阐述 DevOps 是将软件开发(Dev)和信息技术维护(Ops)结合在一起的一组实践,旨在缩短系统开发生命周期并提供高质量的持续交付。 DevOps 普及的主要原因是,它使企业可以比传统软件开发方法更快地开发和改进产品。\n随着我们工作环境的变化越来越快,对软件开发市场中的快速交付和修复的需求正在上升。 因此,对在短时间内生产高质量输出且有限的后期错误需求催生了 DevOps。\n你可能感兴趣:Docker 和 DevOps:开发有状态的应用程序并在 Docker 中进行部署\n正如我们已经讨论了转变为 DevOps 软件开发方式的重要性一样,我们现在将对话更改为容器化,这是一种易于使用的技术,经常被用来使 DevOps 的实现更流畅、更便捷。 容器化是一项使 DevOps 实践更容易遵循的技术。 但是容器化到底是什么? 让我们一探究竟!\n什么是容器化? 容器化是将应用程序及其所需的库、框架和配置文件打包在一起的过程,以便可以在各种计算环境中高效运行它。简单来说,容器化就是应用程序及其所需环境的封装。\n近来,它克服了运行虚拟机所带来的挑战,从而获得了广泛的关注。虚拟机模拟主机操作系统内部的整个操作系统,并且需要固定比例的硬件分配才能运行操作系统的所有进程。因此,由于很大的开销,这导致不必要的计算资源浪费。\n同时,设置虚拟机需要花费时间,在每个虚拟机中设置特定应用程序的过程也需要时间。这导致仅在设置环境时就花费了大量时间和精力。由开源项目 “Docker” 普及的容器化解决了这些问题,并且通过将所有必需的依赖项与软件一起打包在便携的镜像文件中,从而提高了可移植性。\n让我们更深入地研究容器化,它的好处、它的工作原理、选择容器化工具的方式以及它如何胜过虚拟机(VM)的使用。\n一些流行的容器提供程序如下:\n Linux 容器,例如 LXC 和 LCD Docker Windows Server 容器  什么是 Docker? Docker 已经成为 IT 行业中的一个流行术语。 Docker 可以定义为一个开源软件平台,它提供了一种在容器内构建、测试、保护和部署应用程序的简化方法。 Docker 鼓励软件开发人员与云、Linux 和 Windows 操作系统进行协作,以轻松、快速地交付服务。\nDocker 是提供容器化的平台。它允许将应用程序及其依赖项打包到一个容器中,从而有助于简化开发并加快软件的部署。它消除了在应该测试解决方案的每台机器上复制本地环境的需求,从而帮助实现了输出的最大化,从而节省了宝贵的时间和精力,而这些宝贵的时间和精力将用于进一步的开发。\nDockerfile 可以在工作人员之间快速传输和测试。 Docker 还简化了容器镜像管理的过程,并迅速改变了我们大规模开发和测试应用程序的方式。\n容器化——实现 DevOps Docker 已普及了容器化的概念。 Docker 容器中的应用程序具有能够在多种操作系统和云环境(例如 Amazon ECS 等)上运行的能力。没有技术或供应商局限。\n让我们了解使用容器化实现 DevOps 的需求。\n最初,所需的软件开发、测试、部署和监督是分阶段进行的,其中一个阶段的完成将导致另一个阶段的开始。\n像 AWS ECS 一样,DevOps 和 Docker 镜像管理技术使软件开发人员可以轻松地进行 IT 运营、共享软件以及彼此协作,并提高生产力。除了鼓励开发人员一起工作之外,他们还成功地消除了以前影响应用程序的不同工作环境之间的冲突。简单来说,容器是动态的,它使 IT 专业人员可以毫无复杂地构建、测试和部署流水线,同时弥合基础架构和操作系统发行版之间的鸿沟,从而形成 DevOps 的文化。\n软件开发人员可以通过以下方式从容器中受益:\n 可以更改容器的环境,以更好地进行生产部署。 快速启动并轻松访问操作系统资源。 与传统系统不同,它们为应用程序提供了足够的空间以适合一台机器。 为 DevOps 提供了敏捷性,可以帮助轻松地在多个框架之间切换。 有助于更有效地运行工作流程。  下面阐明了使用 Docker 成功实现容器化所要遵循的步骤:\n 开发人员应确保代码在存储库中,例如 Docker Hub。 该代码应正确编译。 确保正确打包。 确保满足所有插件要求和依赖项。 使用 Docker 创建容器镜像。 将其转移到您选择的任何环境。 为了易于部署,请使用 Rackspace、AWS 和 Azure 等云。  使用容器的好处 许多公司选择容器化来带来各种好处。以下列出了使用容器化技术将享受的优势:\n1. DevOps友好 容器化将应用程序及其环境依赖性打包在一起,以确保在一个环境中开发的应用程序可以在另一个环境中工作。这有助于开发人员和测试人员在应用程序上协同工作,这正是 DevOps 文化的全部内容。\n2. 多云平台 容器可以在 GCS、Amazon ECS(弹性容器服务)和 Amazon DevOps Server 等多个云平台上运行。\n3. 天生便携 容器易于携带。 容器镜像可以轻松部署到新系统,然后可以以文件形式共享。\n4. 更快的可伸缩性 由于将环境打包到隔离的容器中,因此可以更快地进行伸缩,这对于分布式应用程序非常有帮助。\n5. 无需单独的操作系统 在 VM 系统中,裸机服务器的主机操作系统与 VM 不同。相反,在容器中,Docker 镜像可以利用裸机物理服务器的主机 OS 的内核。 因此,容器比虚拟机具有更高的工作效率。\n6. 资源利用最大化 容器化可以最大程度地利用内存和 CPU 等计算资源,并且所使用的资源比 VM 少得多。\n7. 应用程序的快速更新 随着应用程序的快速更新,交付在更少的时间内发生,从而使该平台便于执行更多的系统开发。机器无需重新启动即可更改资源。\n借助容器的自动缩放,可以在考虑当前负载的情况下完成 CPU 使用率和机器内存优化。而且与虚拟机的扩展不同,无需重新启动计算机即可修改资源限制。\n8. 简化的安全更新 由于容器提供了进程隔离,因此维护应用程序的安全性变得更加方便。\n9. 物有所值 就支持单个基础结构上的多个容器而言,容器化是有利的。因此,尽管在工具、CPU、内存和存储上进行了投资,但对于许多企业而言,它仍然是一种经济高效的解决方案。\n具有实现容器的完整 DevOps 工作流程可以通过以下方式使软件开发团队受益:\n 它提供了在每个步骤中自动执行测试以检测错误的功能,因此最终产品中出现缺陷的机会更少。 更快、更方便地交付功能和更改。 该软件的性质比基于 VM 的解决方案更加用户友好。 可靠且多变的环境。 促进团队成员之间的协作和透明度。 本质上具有成本效益。 确保正确利用资源并减少浪费。  容器与虚拟机(VMS)之间的区别 虚拟机可以在主机上运行多个操作系统的多个实例,而不会出现重叠。主机系统允许 Guest OS 作为单个实体运行。Docker 容器不会像虚拟机那样给系统带来太多负担,因为运行OS需要额外的资源,这会降低计算机的效率。\nDocker 容器不会给系统增加负担,并且仅使用运行解决方案所需的最少资源,而无需模拟整个操作系统。由于运行 Docker 应用程序所需的资源较少,因此它可以允许大量应用程序在同一硬件上运行,从而降低了成本。\n但是,它减少了 VM 提供的隔离。它还增加了同质性,因为如果应用程序在一个系统上的 Docker 上运行,那么它也将在其他系统上的 Docker 上运行而不会出现任何故障。\n容器和 VM 都具有虚拟化机制。但是对于容器而言,会进行操作系统的虚拟化。在后者中,进行硬件虚拟化。\nVM 性能有限,而带有 Docker 的紧凑型和动态容器则性能更优。\nVM 需要更多内存,因此具有更多开销,与 Docker 容器相比,它们的计算量很大。\nDocker术语 以下是一些常用的 Docker 术语:\n 依赖 – 包含形成环境所需的库,框架和软件,可以模拟执行应用程序的介质。 容器镜像 – 一种软件包,提供创建容器所需的所有依赖关系和信息。 Docker Hub – 一个公共镜像托管注册表,您可以在其中上传镜像并对其进行处理。 Dockerfile – 包含有关如何构建 Docker 镜像的文本说明文件。 仓库 – 一种基于网络或基于 Internet 的服务,用于存储 Docker 镜像,有私有和公共的 Docker 仓库。 注册表 – 一种存储来自多个源的仓库的服务。它可以是公共的也可以是私人的。 Docker Compose – 一种工具,可帮助定义和运行多个容器 Docker 应用程序。 Docker Swarm – 为运行 Docker 而创建的机器集群。 Azure 容器注册表 – 用于存储 Docker 镜像的注册表提供程序 Orchestrator – 一种有助于简化集群和 Docker 主机管理的工具。 Docker 社区版(CE) – 为 Linux 和 Windows 容器提供开发环境的工具。 Docker 企业版(EE) – 用于 Linux 和 Windows 开发的另一套工具。  Docker 容器、镜像和注册表 使用 Docker 创建服务,然后将其打包到容器镜像中。Docker 镜像是服务及其依赖关系的虚拟表示。\n该镜像的实例用于创建一个容器,使其在 Docker 主机上运行。 然后将镜像存储在注册表中。需要一个注册表才能部署到生产协调器。Docker Hub 用于在框架级别将其存储在其公共注册表中。然后将镜像及其依赖项部署到自己选择的环境中。重要的是要注意,有些公司还提供私人注册表。\n商业组织还可以创建自己的私有注册表来存储 Docker 镜像。如果镜像是机密的,并且组织希望镜像与部署镜像的环境之间的延迟有限,则可以提供私人注册表。\nDocker 如何执行容器化? Docker 镜像容器或应用程序可以在 Windows 和 Linux 上本地运行。只需通过 Docker 引擎直接与操作系统交互,即可利用系统资源来实现。\n为了管理集群和组合,Docker 提供了 Docker Compose,它有助于运行多个容器应用程序而不会彼此重叠。开发人员还可以通过 Docker Swarm 模式将所有 Docker 主机连接到单个虚拟主机。之后,使用 Docker Swarm 将应用程序扩展到多个主机。\n多亏了 Docker 容器,开发人员可以访问容器的组件,例如应用程序和依赖项。开发人员还拥有该应用程序的框架。单个平台上并相互依赖的多个容器称为“部署清单”。但是,与此同时,专业人员可以更加注意选择合适的环境进行部署,扩展和监视。 Docker 有助于限制错误的机会,错误的机会可能在应用程序传输期间发生。\n本地部署完成后,它们将进一步发送到 Git 存储库之类的代码存储库。代码存储库中的 Dockerfile 用于构建持续集成(CI)流水线,以提取基础容器映像并构建 Docker 镜像。\n在 DevOps 机制中,开发人员致力于将文件传输到多个环境,而管理专业人员则负责管理环境以检查缺陷并将反馈发送给开发人员。\n面向未来的容器化战略 预测未来并根据项目需求做好可伸缩性的准备总是一个好主意。 随着时间的流逝,项目变得越来越复杂,因此有必要实施大规模的自动化并提供更快的交付。\n密集且复杂的容器化环境需要适当的处理。 在这种情况下,软件开发人员可以采用 PaaS 解决方案,以将更多精力放在编码上。 选择最方便的平台以提供更好和先进的服务时,有多种选择。因此,根据组织的应用程序确定正确的平台非常麻烦。\n为了方便您,我们在选择最佳的容器化平台之前已经列出了一些要考虑的参数:\n1. 灵活自然 为了获得平稳的性能,重要的是手动拾取一个平台,该平台可以根据需求的性质轻松地进行调整或更改,并且可以自动进行。\n2. 锁定级别 实际上,PaaS 解决方案供应商通常是专有的,因此倾向于将您锁定在一个基础架构中。\n3. 创新空间 选择一个平台,该平台应具有广泛的内置工具以及第三方集成技术,以鼓励开发人员为进一步的创新让路。\n4. 云支持选项 在选择正确的平台时,至关重要的是找到一个支持私有,公共和混合云部署的平台,以应对新变化。\n5. 定价模型 由于选择支持长期承诺的集装箱化平台是很自然的,因此了解提供哪种定价模式非常重要。有很多平台可以在不同的运营规模上提供不同的定价模型。\n6. 时间和精力 要记住的另一个关键方面是容器化不是一蹴而就的。专业人士需要花费时间来重组架构基础架构。应该鼓励他们运行微服务。\n为了从传统结构转变,需要将大型应用程序分解为较小的部分,再将这些部分进一步分布到多个连接的容器中。因此,建议聘请专家,他们会尽一切努力找到一种方便的解决方案来在单个平台上处理虚拟机和容器,因为使组织完全依赖于容器需要时间。\n7. 兼容旧版应用程序 当涉及现代化时,不应忽略旧式 IT 应用程序。在容器化的帮助下,IT 专业人员可以利用这些经典应用程序的收益,以适当地利用对旧框架的投资。\n8. 多应用程序管理 通过在容器平台上运行多个应用程序来充分利用容器化。以最低的成本投资新应用程序,并通过使其对当前和旧版应用程序友好而对每个平台进行修改。\n9. 安全性 由于容器化环境具有比传统环境更快的更改能力,因此它具有一些主要的安全风险。敏捷性可以通过提供快速访问来使开发人员受益。但是,如果不能确保所需的安全级别,它将失败。\n处理容器时遇到的一个主要问题是,处理由第三方或不受信任的来源打包的容器模板可能会带来很大的风险。因此,最好在使用之前验证公开可用的模板。\n组织需要增强和集成其安全流程,以无忧地开发和交付应用程序和服务。随着平台和应用程序的现代化,安全性应成为企业的首要任务。\n结论 为了与瞬息万变的 IT 行业保持同步,专业人员应该不断追求更好,因此,应利用市场上可用的新工具来增强安全性。\n这标志着第2部分的结论!在第3部分中,我们将讨论关键的 DevOps 工具和 DevOps 的实现策略。\n进一步阅读 Docker Swarm 的乐趣\n用于开发到部署的 Docker 命令\n",
        "auhtor": "Mitul Makadia",
        "translator": "zhaoying818",
        "original": "https://dzone.com/articles/the-abc-of-devops-implementation-with-containeriza",
        "poster": "12751943-abcs.jpg"
    },
106 107 108 109 110 111 112
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-18-google-summer-of-code-2019-report/",
        "title": "2019 年 Google 编程之夏活动报告",
        "type": "wechat",
        "date": "2020-02-18 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "gsoc2019", "gsoc", "community", "events"],
        "description": "主要介绍了 GSoC 2019 活动的几个课题并讲述了整个活动的组织过程",
113
        "content": " Google 编程之夏活动不仅仅是一个夏日的实习项目,对于组织和一些社区的成员来说,这个活动是他们一整年努力的成果。现在,在里斯本举行的 Devops World | Jenkins World 会议以及最后的回顾会议之后,我们宣布 GSoC 2019 正式画上结束的句号。首先我们感谢所有的参与者:学生们、导师们、主题专家、以及其他一些提出课题构想,参与学生选择,社区联系以及一些后期的讨论与回顾的贡献者们。Google 编程之夏活动是一个大型的活动,如果没有 Jenkins 社区的积极参与此次活动也就无法成行。\n在这篇博客里我们想要与各位分享这次活动的成果以及我们从这一年总结的一些经验。\n成果 今年成功完成了 5 个 GSoC 课题:角色策略插件性能优化,插件安装管理 CLI 工具/库,working-hours 插件 - UI 优化,具有 Kubernetes 功能的 Apache Kafka 远程处理,GitLab SCM 多分支流水线支持。我们会在后面的内容中讨论一下上面提到的这几个课题。\n项目细节 我们在 8 月底举行了最后一次 Jenkins 线上例会的演讲然后 Google 在 9 月 3 日发布了这些成果。最后的这些演讲内容可以从这里找到:第一部分,第二部分,第三部分。我们也在 DevOps World | Jenkins World 旧金山以及 DevOps World | Jenkins World 2019 里斯本会议中发布了2019 Jenkins GSoC 报告。\n在下面的章节中,我们对每一个项目做一个简单的总结,第三阶段编码演示文稿的链接以及最后的成品。\n角色策略插件性能优化 角色策略插件是 Jenkins 中最广泛被使用的认证插件之一,但因为其架构问题以及对项目角色的正则表达式检查使其没有因性能著称。Abhyudaya Sharma 与他的几位导师:Oleg Nenashev,Runze Xia,Supun Wanniarachchi 一起进行该项目。他为 Jenkins 插件创建了一个基于 JMH 的微基准测试框架,创建微基准测试然后在一些真实场景中得到了 3501% 的提升。然后他继续深入研究创建了一个基于目录的认证策略插件,当权限范围为目录时该插件为 Jenkins 实例提供了更佳的性能。在他的项目中 Abhyudaya 还修复了对 Jenkins 组策略的配置即代码的支持并为 JCasC 插件贡献了一些优化与修复的代码。 - 项目页面 - 发布的博客:Jenkins 微基准测试框架, 引入一个新的目录认证插件,角色策略插件性能优化 - 最终评估:幻灯片,视频 - 源码:角色策略插件,目录认证插件\n插件安装管理 CLI 工具/库 Natasha Stopa 正在研究一个新的插件管理 CLI 工具 ,该工具可以统一其他例如 Docker 镜像中的 install-plugin.sh 这样的工具。它还引入了许多新的特性比如 YAML 配置的格式支持,列出可用的升级以及安全性修复。这个新开发的工具最终可以取代刚才提到的的那个工具。Natasha 的导师:Kristin Whetstone,Jon Brohauge,Arnab Banerjee 与许多来自 Platform SIG和 JCasC 插件团队的贡献者们作为利益相关者和项目专家一同参与了这个课题。 - 项目页面 - 发布的博客:alpha 版本发布,第二阶段编码更新 - 最终评估:幻灯片,视频 - 源码:插件管理工具\nworking-hours 插件 - UI 优化 Jenkins UI 和前端框架在Jenkins项目中成为了一个共同的话题,特别是最近这几个月发布了新的 UX SIG 之后。Jack Shen 与他的导师 Jeff Pearce 正在探索一种新的途径来统一构建 Jenkins 的 Web UI。Jack 更新了运行时间插件 使用的 UI 控件是由标准的 React 库提供的。然后他将他的这些工作经验文档化并创建了使用基于 React UI 的插件模板 - 项目页面 - 发布的博客:working-hours 的 UI 更新,React 插件模板 - 最终评估:幻灯片,视频 - 源码:working-hours 插件,基于 React UI 的 Jenkins 插件模板\n具有 Kubernetes 功能的 Apache Kafka 远程处理 Long Le Vu Nguyen 正在为 Apache Kafka 远程插件扩展 Kubernetes 支持。他的导师 Andrey Falco和 Pham vu Tuan 是我们 GSoC 2018 的学生和插件发明者。在这个项目过程中 Long 添加了一个新的代理启动器,该启动器规定了在 Kubernetes 中的 Jenkins 节点使其让它们连接到 master 节点。他还为其创建了一个 Cloud API 接口以及一个新的 Helm 图表,该图表可以将 Jenkins 作为 Kubernetes 中的一个完整的系统,默认启用 Apache Kafka。所有这些特性都发布在了 Apache Kafka 远程插件 2.0 中。 - 项目页面 - Apache Kafka 远程插件 2.0 发布的博客 - 最终评估:幻灯片,视频 - 插件源码\nGitlab SCM 支持多分支流水线 Parichay Barpanda 正在开发具有多分支流水线任务以及基于文件夹组织支持的新的 GitLab 分支源码插件。他的导师是 Marky Jackson-Taulia,Justin Harringa,Zhao Xiaojie 和 Joseph Petersen。该插件扫描项目,并根据提供的的条件导入流水线任务。项目导入后,Jenkins 立即运行基于 Jenkinsfile 脚本的任务然后发送通知到 GitLab 流水线状态。该插件同样提供了 GitLab 服务器配置可以在系统配置或者通过 Jenkins 配置即代码进行配置(JCasC)。在 GitLab 分支源码 1.0 声明获取更多内容。 - 项目页面 - 第三阶段编码演示 - GitLab 分支源码插件,GitLab API 插件\n没有完成的项目 今年并非所有的项目都完成了。我们也在 Jenkins 流水线 artifact-promotion 插件和云特性的外部工作区管理插件进行了尝试,但不幸的是这两个项目都在第一阶段编码后即停止了。无论如何,我们在这些领域得到了许多经验与收获。(请参阅链接的 Jira ticket!)我们希望这些故事的某一点能够被 Jenkins 贡献者实现出来。或许 Google 编程之夏 2020 可以?\n以组织层面运营 GSoC 项目 这里有一些在我们组织 GSoC 前后的一些幕后的小故事跟大家分享。为了给即将涌入进来的学生们做好准备,我们更新了所有的 GSoC 页面,收录进去了我们这几年运营这个项目的所有知识。我们从 2018 年 10 月份开始准备,此时离项目开始还有很长一段时间。主要的目标是解决在 GSoC 2018 期间得到的一些反馈。\n课题构想。我们在 2018 年的最后一个月开始收集课题的构想。我们在 Google 文档准备了课题构想清单,并在文档的表格中追踪了每个课题的所有权情况。每个课题构想都在其 Google 文档中作进一步阐述。我们发现每个课题在定义阶段都非常的复杂,也许他们本身就太复杂了并且也应该完成不了。\n自从我们想让所有的课题构想都能用相同的方法编写成文档时,我们创建了一个模板来指导这些贡献者们。大多数课题构想的文档是由组织的管理员或者导师来编写的,但是偶尔也有一个学生提出一个极妙的点子。我们也在那个文档中获取了一些其他信息比如 GitHub 以及 Gitter 账号以及课题的潜在导师清单。我们将所有的课题文档放到了我们的网站上。\n导师与学生指导。我们更新了导师信息页面的一些细节是关于我们希望导师们在项目中做哪些事情,包括导师们工作的小时数,甚至我们有一部分专门写了避免利益冲突的内容,当招募了导师之后,我们引导他们访问导师信息页面。\n我们同样更新了学生信息页面。我们发现当每一位学生咨询我们相同的问题都是关于报名和参与项目时这个页面节省了我们很大一部分时间。我们只是把这些页面的链接发给他们而不是每次都要去解释这个项目。\n应用阶段。在 GSoC 正式开始的几周前,学生们就已经开始接触这个项目。这真的很振奋人心。一些学生甚至在项目官方开始之前就开始着手课题构想了。\n课题选择。这一年组织管理团队做了一些非常艰难的决定。面对众多的学生,导师和课题,我们必须要正确数量的并且尝试匹配最有可能成功的课题。我们尝试通知导师团队的同时也在寻求课题的数量,在截止时间之前得到所有导师们的回复是困难的。最终我们寻求的课题数量要少于我们可以添加进来的数量。当我们寻求课题时我们提交了两个数字:一个最小值一个最大值。GSoC 指南说明如下: - 最小值基于一些非常棒的课题数量,他们非常想要在一个夏天的时间内看到这些项目可以取得成功。 - 最大值是一些他们想要这一整个夏天可以指导的可信赖并且非常棒项目的数量。\n我们选择了最小数量的课题。所以我们必须做非常艰难的决定:我们必须在“很棒”与“可信赖”的原则之间进行选择。一些原则上来说,非常好的那一个,选择起来很简单,但是对其他的来说,这很困难。我们知道我们无法做到真正的完美,过往的经验中,我们也知道一些学生或者一些导师会因为一些不可控的生活琐事而无法完成整个项目,即使是一些出色的提案亦如是。所以我们必须做出最好的决定,要知道我们选择的一些项目可能不会完成。\n社区联系。我们发现社区联系阶段对于每一个课题的成功至关重要。社区联系有困难的课题通常来说不会做的很好。为了让学生们更好的融入进社区中,几乎所有的课题都在特别兴趣小组的指导下进行,这样可以与更多相关人士交流。\n沟通。每年我们都有学生通过个人社交工具与导师进行交流。学生们,如果你们正在读这篇文章,请不要给我们通过个人社交工具发送有关课题方面的内容,你不会收到任何额外的照顾。显然,开源化的目的是我们希望所有的讨论都是公开化的,所以学生们需要时刻牢记这一点。2019 年我们使用 Gitter 处理了最多的聊天信息,但是从一名管理员角度来说相比邮箱沟通来说这样有点太碎片化了。并且它很难去搜索消息。聊天室很方便毕竟消息集中一些,但是从一名管理员角度来说,缺少话题功能很难从 Gitter 获得概要信息。最近 Gitter 添加了话题功能(2019 年 11 月)但是在 Android 和 iOS 上并不能使用。在项目尾声我们使用 Zoom 会议并且我们发现使用它工作要比 Google 的 Hangouts 要容易一些。\n状态跟踪。另一个很麻烦的事情就是一旦开始后获取每一个课题运行的概况。我们扩展了 Google 表格的用途,在项目期间跟踪表单中的课题与参与者来为课题排名以及追踪课题各阶段的状态(社区联系,编码,等等。)。让这些表格持续更新是一件很有挑战性的工作,每一个课题包括了好几位参与者以及好几个链接。在这件事上消耗的时间让我们发现让这些表格保持更新,准确,完整有一点困难,直到编码阶段开始之前都是这样。\n或许一些状态跟踪工具可以帮上忙。我们使用 Jenkins Jira 来跟踪这些课题,每个阶段代表了一个独立的冲刺竞赛。这给成功的课题帮了大忙。在我们的组织里,我们尝试让每个人都在提前截止日的几天完成,因为我们知道会有一些意外因素比如停电,糟糕的天气(甚至在西雅图都有这事儿!),或者其他无法控制的事情,这些或多或少会影响课题数据的提交。我们同样想到截止日跟周末“撞车”的话人们会忘记这些事情,这同样也是危机所在。\n回顾。课题尾声,我们同样会举行一个回顾来为以后获取一些新的构想。你可以在这里找到这些笔记。我们已经处理了文档中最重要的一些评论以及明年课题的构想。\n奖励 去年,我们想要通过发送纪念品的方式感谢每一位在项目中参与的人。今年,我们收集了所有我们能找到的邮寄地址准备给每一位送上 Jenkins 15 周年纪念版 T 恤以及一些贴纸。这是一个非常棒的时刻。我也同样以个人名义感谢 Alyssa Tong 对我们 T 恤以及贴纸设计上的一些帮助。\n导师峰会 每年 Google 会邀请每个组织的两位或多位导师参加 Google 编程之夏导师峰会。这个活动中,数以百计的开源项目维护者以及导师们齐聚一堂对 GSoC,社区管理以及各种工具进行一些非正式会议。今年峰会在慕尼黑举办,Marky Jackson 和 Oleg Nenashev 作为代表参与了此次会议。 除了探讨课题和分享巧克力,我们在那里展示了 Jenkins,发表了简短的讲话以及主持了一个有关 GitHub 自动机器人的非正式会议,我们不能在那里拍摄团队照片,所以试着在这张照片里找到 Oleg 和 Marky 吧:\nDevOps World | Jenkins World 中的 GSoC 团队 一般来说我们使用 GSoC 组织的经费和差旅经费来赞助学生们的旅行以及主要跟 Jenkins 相关的活动。今年四名学生参加了在旧金山与里斯本的 DevOps World | Jenkins World 会议。这些学生在社区展位和贡献者峰会上展示了他们的课题,他们的作品在社区获得了非常多的关注! 非常感谢 Google 和 CloudBees 能让此次旅行能够成行。你可以在这里找到来自 Natasha Stopa 的报告,更多的旅行报告后期奉上。\n结论 今年,5 个课题成功完成。我们从其他参加的组织那里得到的消息也说明这是一个正常的数字。 早些时间更新 GSoC 页面为我们后期的工作节省了很多时间因为有人联系我们的时候我们不能每次都重复所有的信息。我们发现保持跟进所有的导师们,学生们,课题以及元信息是必须的但又耗时的工作。我们希望有一个工具用来帮我们做这些事情。协调会议以及提醒参与者截止日之前需要完成的工作也是 GSoC 组织工作的一方面,我们需要持续做这件事。 最后,我想再次感谢所有的参与者,没有你们我们不能做到这些。每年都有一些做的很棒工作以及为 Jenkins 社区贡献一些很棒作品的学生给我们留下了很深刻的印象。\nGSoC 2020? 是的,会有 Google 编程之夏 2020 这个活动的!我们计划参加也在寻找课题构想,导师以及学生。Jenkins GSoC 页面已经更新了,我们邀请每一个人明年都能参与进来。 - 活动主页面 - GSoC 2020 课题构想 - GSoC 2020 导师招募与课题构想收集 - 学生与导师信息页面\n",
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
        "auhtor": "Martin d'Anjou,Jeff Pearce,Oleg Nenashev,Marky Jackson",
        "translator": "0N0thing",
        "original": "https://jenkins.io/blog/2020/01/29/gsoc-report/#google-summer-of-code-2019-report",
        "poster": "cover.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-17-happy-second-birthday-jenkins-x/",
        "title": "Happy Second Birthday Jenkins X!",
        "type": "wechat",
        "date": "2020-02-17 00:00:00 +0000 UTC",
        "tags": ["jenkins-x", "ci", "cd"],
        "description": "Jenkins X 2019 年终回顾",
        "content": " 始于 2019 年初的 Jenkins X 项目在去年的1月14号庆祝了它的第一个生日,这对任何开源项目来说都是一件大事,我们刚刚又庆祝了它的第二个生日。\nJenkins X 的两周年! Jenkins X 已经从一个关于 CI/CD 如何在云原生世界中被重新设计的愿景,进化到了一个快速发展、创新并迅速成熟的开源项目。\nJenkins X 是为了帮助开发者们能够快速的将代码发布到 Kubernetes 上而创建的。从一开始,Jenkins X 就致力于改善开发者的开发体验。使用一个命令行工具,开发者就能构建 Kubernetes 集群,部署流水线,创建应用,新建 Github 仓库,将应用推送至 Github 仓库,新建 Pull Request,构建容器,在 Kubernetes 中运行该容器并最终合并到产品中。为了做到这些,Jenkins X 对一系列同类最佳开源工具进行了自动化安装与配置,并且自动化了所有流水线的生成。Jenkins X 还通过测试、过渡和生产环境对应用程序的升级进行了自动化改造,使开发人员能够获取大量到的变更反馈。例如,Jenkins X 的预览环境容许快速与及早的反馈,这样开发者便能在自动构建的环境中查看应用的实际功能。我们发现,由 Jenkins X 在流水线中自动创建的预览环境在开发者中十分流行,因为他们能够在将代码合并到 master 分支之前查看变更情况。\nJenkins X 本身是功能专一的,但是却极易拓展。Jenkins X 是为实现 DevOps 最佳实践而创建的,旨在跨团队的可重复、可管理的方式中,能够完成大量分布式微服务的部署工作。Jenkins X 促进了大量已被检验的最佳实践,如基于主干的开发和 GitOps。为了让您能够快速上手与使用,Jenkins X 提供了许多快速入门的例子。\n属于 Jenkins X 的 2019 高光时刻 2019 年 2 月:Tekton 的崛起! 在 2018 年的后半年,Jenkins X 开始了一趟提供 Serverless Jenkins 与仅在需要时运行流水线引擎的旅程。这种流水线引擎基于 knative build-pipeline 项目,该项目进化成为了受到 Jenkins 和 Jenkins X 社区众多帮助与热爱的 Tekton 。Jenkins X 项目在 2019 的 2 月完成了与 Tekton 的初次集成。Tekton 是一个强大和灵活的 Kubernetes 原生开源框架,用于创建 CI/CD 流水线、管理制品和渐进部署。\n2019 年 3 月:Jenkins X 加入了持续交付基金会! Jenkins X 加入了 Continuous Delivery Foundation (CDF),与 Jenkins、Spinnaker 和 Tekton 一起作为创始项目。加入一个专注于持续交付的中立供应商基金会对于 Jenkins X 社区意义重大。\n2019 年 6 月:Lighthouse 项目 当 Jenkins X 开始它的 serverless jenkins 旅程时,它选择了使用 Prow,一个用于 Github 事件和 ChatOps 的事件处理器。Prow 被 Kubernetes 项目用于构建所有的仓库,除此以外,它还包含了一个强大的 webhook 事件处理器。Prow 已久经考验,但它却严重的依赖于 Github,并且难以拓展至其他的 SCM 提供商上。 在 2019 年 6 月末,一项轻量级、可拓展至 Prow 的项目开始了,它叫做 Lighthouse。Lighthouse 跟 Prow 支持同样的插件(因此你仍然可以通过 ChatOps 请求各种各样的东西)和配置 —— 这使得 Prow 和 Lighthouse 间的迁移变得极其容易。\n2019 年 6 月:Jenkins X Boot! 我们在整个六月都十分的忙碌 —— 暑期到来前一个疯狂的活动爆发期。Jenkins X 用户面临的一个常见问题便是在不同的 Kubernetes 集群上安装 Jenkins X 。按照正确的顺序安装服务和确保 DNS 和 Secrets 正确性的工作是因供应商的不同而完全不同,有时也因集群的不同而不同。我们意识到,要简化安装,我们确实需要一个流水线,虽然这听起来有点像一个电影情节,但运行 Jenkins X 流水线来安装 jx 确实是最好的选择。jx boot 命令使用本地 jx 二进制文件解释引导流水线。jx boot 命令也可以用于更新你的集群。\n2019 年 7 月:一个新的 Logo! 作为转移到 CDF 的一部分,Jenkins X 项目利用这个机会重新设计了它的标志。一个机器人就代表了 Jenkins X 在 Kubernetes 上提供自动化 CI/CD 的能力等等!\n2019 年的后半年:聚焦于稳定性和可靠性 Jenkins X 项目与很多不同的组件和活动部件一起进展的很快。不幸的是,这一快速的发展招致了一些不稳定性和导致了严重 issue 的增长,这些问题有可能破坏我们已经在 Jenkins X 上所做的所有杰出工作。于是,社区一直在努力提高稳定性和解决显著的 issue —— 下图展示了去年 issue 数量的走势,可以看出,在最后6个月内,创造的 issue 数量有一个显著的下降趋势。\nCloudBees 还通过引入 CloudBees Jenkins X 发行版帮助了这项工作,该发行版增加了围绕稳定配置和部署的测试,并且在每月定期发布。\n2019 年 10 月:Jenkins X Steering Committee 成立会议 Jenkins X Bootstrap Steering Committee 的任务是组织其向选举制 Steering Committee 的过渡工作,并确定 Steering Committee 在指导 Jenkins X 项目方面将承担的责任。\n2019 年 12 月:第一个 Jenkins X Outreachy 学员 Neha Gupta 正在向 Jenkins X 中添加对 Kustomize 的支持以确保 Kubernetes 本机配置管理功能的实现,同时将在 2019 年 12 月到 2020 年 3 月期间参与 Outreachy。我们欢迎 Neha 在 Jenkins X 上所做的工作,并且期待着我们能在持续培养的文化基础上再接再厉!\nJenkins X 在产品中的使用 尝试 Jenkins X 最简单的方法无疑是使用由 Jenkins X 驱动的 CloudBees CI/CD,它通过方便易用的 SaaS 提供 Jenkins X 。无需设置集群,无需安装 Jenkins X,这些它都已经为你完成了!目前,由 Jenkins X 驱动的 CloudBees CI/CD 已经可供预览。在这里注册试试新的 Jenkins X Saas 吧!\n下一步? Jenkins X 项目将鼓励社区参与到更多的创新活动中。同时,有很多不错的想法也将继续扩展的我们的故事,比如:集成渐进式交付(A/B 测试、Canary 和 Blue/Green 部署)、持续化验证以及更多的平台支持。我们也期待着在 Jenkins X 的 CloudBees UI 中能涌现出更多更棒的新特性。\n敬请期待 Jenkins X 将在 2020 年带来的更多令人振奋的新公告吧!\nJenkins\nJenkins 中文社区链接\n",
        "auhtor": "Rob Davies",
        "translator": "XiongKezhi",
        "original": "https://jenkins-x.io/blog/2020/01/14/happy-second-birthday/",
        "poster": "./2020-02-17-happy-second-birthday-jenkins-x/7TH_BIRTHDAY.png"
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-14-devops-trends-to-watch-for-in-2020/",
        "title": "展望 2020 年 DevOps 的发展趋势",
        "type": "wechat",
        "date": "2020-02-14 00:00:00 +0000 UTC",
        "tags": ["DevOps"],
        "description": "本文展望了 2020 年 DevOps 领域的发展趋势",
        "content": " Netscape 的创始人 Marc Andreessen 很久之前就谈到过软件是如何吞噬整个世界的。他还说过,当今,每一家公司都可谓是软件公司,它们已经做好准备来接管广阔的经济领域。在 2020 年,您会清晰地看到 DevOps 持续不断的更新是如何改变交付方式的,将软件交付到几乎是无限的市场中。在这个技术竞争激烈的世界中,DevOps 已成为蓬勃发展的必需品了。\n导引 虽然每个企业对 DevOps 有着不同的理解,但我们仍然可以将 DevOps 定义为一个团队为了将其工程能力提升到新的高度而采用的一种心态。DevOps 的主要目的是消除工程实践上的障碍,重点是那些存在于想法和实践之间的文化障碍,从而使软件的交付过程变的更好、更快、更廉价和更安全。\n无论您怎样称呼 DevOps,它最终都应该归结为自动化,而自动化反过来又应该有助于公司的快速发展、快速交付、快速失败、快速恢复以及快速学习。\n从 SDLC(System Development Life Cycle,系统生命周期)模型的出现到今天,情况已经发生了巨大的变化。在 2009 年,DevOps 诞生了,它倡导文化的转型和一些将所有事物都视为代码的技术原则。随后出现了诸如 CI/CD 之类的理念,但是,软件曾经是作为一个巨大的单体被编写的,这个转变过程带来了许多挑战。\n因此,在 2011 年引入了微服务架构,它提倡细粒度和松耦合的组件划分方式,其中每个组件都承担特定的职责。\n遵循这种松耦合、微服务架构而编写的应用程序被称为云原生应用。当前,众多企业根据其业务需求和目标,正在从虚拟机过渡到 Kubernetes 和 Serverless。\n根据 Kelly Shortridge 和 Nicole Forsgren 博士在 Black Hat USA 2019 上发布的幻灯片,在与 DevOps 行业中卓越的实践者进行对标时,有四个因素特别关键,分别是:\n 变更前置时间 发布频率 恢复时长 变更失败率  在本文中,我们将会了解到 DevOps 在未来的发展趋势。\n云原生将成为必然 Diamanti 对 500 多位 IT 主管进行了调查。结果表明,从所有方面来看,容器技术已经远远超出了预期,它在一年内迅速成熟,并从开发者试验转向了生产环境。云原生技术将会上升到一个新的高度,尤其是对 Kubernetes 的采用。云原生为公司提供了更大的优势,使其以更快的速度将产品推向市场。\n什么是云原生 采用云原生意味着更好的创新、更先进的转型以及更丰富的客户体验。如我在的另一篇文章“ Cloud-Native DevOps”中所述,云原生从根本上促进了云自动化,这里指的是云计算服务的安装、配置和监控的自动化管理,它是关于使用技术在恰当的时间为您的云计算资源做出更可靠的业务决策。\n根据 Oracle 对云原生未来的预测,到 2025 年将有 80% 的 IT 企业会把业务迁移到云。CNCF 的调查结果显示,在生产环境中使用云原生技术的企业数量已经增长超过了 200%。\n去年,作为云服务提供商的 Cloud Foundry Foundation 开源平台的执行董事 Abby Kearns 在 2018 年 LinuxCon + ContainerCon + CloudOpen China( LC3)上发表了主题演讲,对云原生及其未来做了更加深入的阐释。\nKearns 说:“云原生技术和云原生应用正在增长,在接下来的 18 个月中,组织正在编写和使用的云原生应用的数量将会增加 100%。” 她补充道:“这意味着您不能再仅限于投资 IT,更需要投资云和云技术。(引自 Abby Kearns 的主题演讲塑造云原生未来)\n美国空军是她在演讲中所举的最好的例子之一,她在演讲中谈到了他们已经变得多么敏捷,并且采用了前沿技术和云原生原则。美国空军已经实施了敏捷实践,现在正在利用云技术开发在多云上运行的应用程序。\n容器注册服务将呈上升趋势 这一点本来可以包含在云原生部分中。尽管如此,我认为这仍需要特别注意,因为大多数软件公司现在都沉迷于容器注册服务,这些容器注册服务可以帮助开发人员存储、管理制品及其所有依赖,以便实现软件开发生命周期的平稳进行。\n就像在版本控制系统(例如 Git)中管理应用程序的源代码一样,管理 Docker 镜像也至关重要。 Docker 提供了类似的管理镜像的功能,这些镜像可以在开发者本地主机上甚至在远程容器注册服务(Docker Hub)上得到管理。\n但是,有时这些镜像容易出现许多与安全性相关的问题,并且黑客可以轻松访问它们。因此,现代公司需要一种安全可靠的方式来通过注册服务管理镜像。\n对于使用容器化应用和微服务架构的 DevOps 团队而言,容器注册服务已成为了必须具备的条件。随着 Docker 和云原生应用程序的日益普及,容器镜像像管理已成为现代软件开发的重要组成部分。容器注册服务简单的说就是镜像仓库的集合,这些仓库主要用于存储容器镜像。\n最近在圣地亚哥举行的 KubeCon 会议上,JFrog 宣布了自己的容器注册服务。基于 Artifactory 的强大功能,JFrog Container Registry 是市场上经过严酷考验的免费容器注册服务。它是可扩展的、混合的、具有 Artifactory 的精美用户界面并由 Artifactory 提供技术支持。\n目前市场上其他著名的容器注册服务包括:\n Amazon Elastic Container Registry (ECR) Dockerhub JFrog Container Registry Azure Container Registry Google Container Registry  私有容器注册服务允许公司实施自己对容器的管理方式,包括策略、安全、访问控制等。容器注册服务应具有的功能包括完全混合云、Docker 注册服务、Helm 注册服务、通用仓库、远程仓库、虚拟存储库以及丰富的元数据。\n哪里需要用到容器注册服务? 有几个原因可以说明容器注册服务的必要性:\n 随着云原生的发展,我们看到企业级的数字化转型正在进行,使用的工具有 Kubernetes、Docker、Artifactory、Helm 和 Istio 等。全世界都在迅速向容器注册技术过渡,这正是容器化应用快速、安全交付的未来。\n 混合云争日趋激烈,大多数云提供商都为它们的服务提供了免费的注册服务,因为它们知道注册服务的重要性。\n Docker 容器往往会占用大量存储空间,并且需要来回转移。这意味着高昂的存储成本,有时安全性也可能成为一个问题。结果,我们看到一些公司除了使用 Docker 外也使用 Artifactory,并且也使用其他的免费工具来管理容器。很高兴看到 JFrog 现在拥有自己的容器注册服务:)\n 注册服务可以充当远程、虚拟的容器仓库,其中包含丰富的元数据,这是 DevOps 中的要素之一。\n 可以获得关于制品的宝贵见解。\n  Go 和 DevOps 会一起繁荣 尽管 Go 已经有些影响力,但它将对 DevOps 社区产生了更大的影响。大多数 DevOps 工具,例如 Kubernetes、Helm、Docker、etcd、Istio 等都是用 Go 编写的。 Kubernetes 的创造者 Joe Beda 曾写过为什么 Kubernetes 是用 Go 编写的。\n由于 Go 可以静态编译成独立的二进制文件,因此非常适合在您无法安装或不想安装依赖项的环境中使用。无需设置整个环境,这可以让您比使用其他编程语言更快地完成工作。\nJFrog 在最近于伦敦和圣地亚哥举行的 GopherCon 会议上对 1000 多名开发人员进行了调查,以便更好地了解 Go 社区和对 Go module 的总体看法。\n他们发现了什么?\n Go 开发人员投入程度很高 超过 82% 的 Go 开发人员使用可以使能 Go module 的 Go 版本,并且现在或预期在 2020 年中期使用该功能的人数也几乎达到了相同的比例。 Go module 的使用率很高 Go 在各行各业中得到了广泛使用 选择 Go module 很困难  另外,请看一下我的另一篇文章,其中讨论了 为什么 Go 对于 DevOps 如此适合。\n安全性将成为更高的优先事项 在软件开发生命周期中,安全性变的比以往任何时候都更为重要。安全性变成了每个人的责任,而不仅仅是安全专家。\n尽管 DevSecOps 一词似乎只是另外一个流行词汇,但仍要更加重视安全性。 DevSecOps 在组织内创建安全意识和共享的知识库,以加强软件开发过程中的安全性。今年早些时候,Capital One 漏洞使云安全成为一个令人关注的话题,因此重点是保护公有云中的数据。\n三星 Note 7 的灾难在很大程度上解释了为什么安全性在流程开始时以及开发生命周期的每个阶段都如此重要。专家推测,Note 7 手机的问题之一涉及其电池管理系统。该系统监控电流并在电池充满时停止充电过程。系统中的故障导致电池过度充电、变得不稳定并最终爆炸。\n此故障修复使三星损失了近 170 亿美元。如果较早发现此问题,他们可以节省很多钱以及品牌的声誉。\n要发展一种策略和方法以使组织中的安全性成为必须,请考虑以下几点:\n 从小处着手,从一开始就在开发生命周期的每个阶段都部署安全检查点。 对于开发人员,将安全性作为他们工作的一部分,并作为其绩效评估的一部分。 开发和运营团队都需要将安全等同于质量。 不要将 DevOps 和安全性分开,彻底地结合它们,使其成为您的工程团队的口头禅。  许多公司将采用混沌工程原理来检查系统的稳定性和可靠性,并检查安全的程度。故意破坏系统可以帮助您发现更大的错误,并确保黑客不会在系统中发现任何漏洞。这也将帮助组织先于客户发现错误。DevSecOps 目的是不断地使您的系统比以往更加健壮。\n开源将超越边界 开源给开发人员带来的优势和灵活性已引起越来越多的关注。 Synopsys 在最近进行的一项调查中发现,开放源代码正在发展中,几乎 70% 的公司组织正在为开源项目做贡献或拥有开源项目。\n为什么要开源?\n开源软件非常有助于开发人员个人提高技能。开源为开发人员提供了以下途径:\n 学习解决问题的新技术和有效方法。 在项目上进行协作并获得经验。 贡献于开源项目会产生一种归属感,它将使您成为有着相同目标和观念的大型社区的一部分。  在最近的印度开源 2019 大会上,我们对近 300 名开源专业人士进行了调查,以下是当我们询问他们喜欢开源软件的原因时的回应。定制化是大多数人喜欢开源软件的事实。\nCB Insights 的最新研究估计,开源服务行业在 2019 年将超过 170 亿美元,并且在 2022 年有望达到近 330 亿美元。\n微软、谷歌、英特尔和 Facebook 等大型巨头(它们不是开源公司)正在积极地为 GitHub 上的各种项目做出贡献。Google 的员工在 2018 年提供了 5500 次贡献,其中许多贡献已经帮助了较小的独立项目。\n对于 Google 的开源软件项目,如 Kubernetes,Istio 和 Knative 的支持有很多,需求很高。随着公司赞助的项目越来越受欢迎,独立开发人员将继续做出贡献。这表明巨人应该挺身而出,帮助开源社区发展。\n例如,Microsoft 的 Visual Studio Code 项目总共有超过 19000 个贡献者。在成千上万开发人员的参与下,这些技术巨头从免费的开发人员输入和直接的用户反馈中受益。这使组织可以更快地构建更好的软件。开源技术无疑已经成为主流,并且拥有光明的未来。\nCloud Native Foundation 生态系统主管 Cheryl Hung 在最近的欧洲 Linux Foundation 开源峰会上的演讲中明确指出,大型公司正在致力于开源项目。特别是 Kubernetes,它创建了一个庞大的社区。\nServerless 仍然是个新事物,但却有着光明的未来 毫秒级的部署是未来的趋势,许多公司已经在最大程度上利用 Serverless 架构。Serverless 市场预计到 2021 年将达到 77 亿美元。根据 RightScale 的 2018 年度云状态报告,Serverless 是当今增长最快的云服务模型,年增长率为 75%,并有望在 2020 年超过预期。\n当前的 Serverless 选则包括:\n AWS Lambda Microsoft Azure Google Cloud Platform IBM Bluemix/OpenWhisk  为什么开发者更喜欢 Serverless:\n 使开发者更有生产力 部署速度更快 扩展能力更强 用户体验更好 费用和基础设施问题更少  2017 年 5 月,微软首席执行官 Satya Nadella 指出 Serverless 的潜力及其改变云计算机制的能力。\n他说:“但是,我认为将彻底改变我们对逻辑的看法的一件事是 Serverless \u0026hellip; 因此,Serverless 将在根本上改变不仅是后端计算的经济价值,而且它将成为未来分布式计算的核心。”\n乐高的 Serverless 之旅 乐高 的 Serverless 之旅将向您展示如何从一小步开始并取得巨大成功。黑色星期五和网络星期一的灾难使他们转向了 Serverless 。 乐高拥有一个包含 Oracle ATG 的旧系统,其中八台服务器与同一个数据库进行通信,而 SAP 则在后端支持 TAX 系统。\n上述旧版系统参加了每年的黑色星期五和网络星期一的活动,当系统无法控制夜间高峰时,这变成了一场灾难。结果,发生了一系列事件,其中 TAX 系统先关闭,这又使 SAP 宕机,结果整个乐高电子商务平台停顿了 2 个小时,这使他们蒙受了巨大损失。\n此事件使他们想到了 Serverless,为什么?\n灾难发生后,乐高团队决定迁移到云中,拥有一个简单的 API,将 Lambda 置于其后,然后使用它。这是乐高转向 Serverless 的第一步。这也促使他们也转向了微服务架构,甚至转向了 DevOps 和自动化。\n乐高团队一开始只用单个 Lambda 来计算营业税,现在已经全部使用了 Lambda。\n整个话题都在这里。\n数字化转型将为他人树立榜样 我们将会看到有许多组织摆脱他们的舒适区,并尝试新技术,甚至医疗、金融机构、政府等传统行业也将通过采用云原生和 DevOps 实践来实现数字化转型,从而得到整体大幅改善。让我们看看一些近期有趣的案例研究。\n快递服务公司联邦快递是如何找到实现数字化转型方式的?联邦快递没有足够的 IT 专业人员来使用现代 Cloud-Native 和 DevOps 流程,但并它并没有止步于此。 联邦快递知道其工程师人才库中缺乏合适技能的问题,因此首席信息主管 Rob Carte 找到了解决方案。联邦快递成了一所大学,开始教自己的工程师先进的计算机技能和现代的软件开发方式。\n为此,创建团队并将其命名为 The Cloud Dojo。 Dojo 由一个跨职能的团队组成的,这个团队由专业云开发人员、安全专家和运营专家共同组成,并聚集到一个位置。其目的是培训团队,使其将传统工程与现代云实践,包括 DevOps、云原生、重写旧应用程序以在云中运行和自动化相结合。这个称为 Cloud Dojo 的土著团队已经重新培训了 2500 多名软件程序员。\n迄今为止,联邦快递已经为云化重写了 200 多个生产级的应用程序,以及 300 多个应用程序可供使用。因此联邦快递的 Cloud Dojo 团队获得了 2019 CIO 100 奖。阅读整个故事和联邦快递的首席信息主管 Carter 的提示。\nBox 的数字化转型之路 几年前,在 Box 公司,要花六个月的时间来构建新的微服务,快进到今天,则只需要几天。他们如何设法加快速度?有两个关键因素使之成为可能:\n Kubernetes 技术 DevOps 实践  Box 成立于 2005 年,是一个单体的 PHP 应用程序,随着时间的推移已经发展到数百万行代码。应用程序的整体性导致他们建立了非常紧密耦合的设计。这导致他们无法按照自己想要的速度进行创新。应用程序一部分中的错误将导致他们回滚整个应用程序。\n如此多的工程师使用数百万行代码在同一个代码库上工作,错误并不少见。越来越难及时的发布功能,甚至无法修复错误。因此,他们寻找解决方案,并决定采用微服务方法。但是后来他们又开始面临另外一些问题,这些问题随着 Kubernetes 的采用得到了解决。\n请观看 Box 高级工程经理 Kunal Parmar 的完整视频讲座。\n多云将蓬勃发展到新的高度 多云将蓬勃发展,大多数企业都有混合云策略。许多应用程序被编写为在本地和非本地运行,并可能在多个公有云环境中运行。谷歌的云服务平台 Anthos 证明了多云对于软件公司来说是灵活且经济高效的。\nAzure 和 AWS 作为该领域的领导者将决定多云的未来。\n根据最近的 RightScale 2019 云状态报告,可以看到 84% 的企业具有多云策略。\n多云与当今不断增长的市场趋势高度相关。根据 IDC 最近的一项名为多云世界中的云遣返加速的调查,多云最能描述当今的云现实。\n尽管有关云成本优化和供应商锁定的讨论很多,但多云在这里解决了一些关键性问题,例如:避免供应商锁定、成本优化、安全性、数据主权和减少停机时间等。\n拥抱 DevOps 只是对话的开始,还有很长的路要走。公司的数量每天都在增加,因此对云的依赖使 DevOps 市场成为一个很大的市场。Allied Market Research估计,到 2023 年,全球 DevOps 市场将以 18.7% 的复合年增长率达到 94 亿美元。 DevOps 将开发和运营整合在一起,为团队提供了更高的信心和自由度,使其能够以更快的速度和质量进行交付。\nDevOps 尚未完成增长,它日新月异,发展前景广阔。我们都知道,根据 Forrester 的说法,2018 年是企业 DevOps 年。实施 DevOps 实践的企业从故障中恢复的速度提高了 24 倍,并且在补救安全问题上花费的时间减少了 50%,事实证明,DevOps 可以带来更快乐、更投入的团队。\n我希望这些 DevOps 趋势可以使您对市场的发展方向以及如何为敏捷和快速发布做好准备。\n进一步阅读 Container Registries — A Battle Royale\nWhy the World Is Shifting Towards a Cloud-Native Approach\n",
        "auhtor": "Pavan Belagatti",
        "translator": "anxk",
        "original": "https://dzone.com/articles/devops-trends-to-watch-for-in-2020#",
        "poster": "cover.jpg"
    },
145 146 147 148 149 150 151
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-12-a-new-chapter-for-kohsuke/",
        "title": "Jenkins 创始人 Kohsuke 的新篇章",
        "type": "wechat",
        "date": "2020-02-12 00:00:00 +0000 UTC",
        "tags": ["社区", "治理", "公告"],
        "description": "Jenkins 创始人 Kohsuke 即将退出 Jenkins,并投身于一个新的创业公司 Launchable ",
152
        "content": "2020 年对我来说将是转变的一年。在 1 月底,我将正式退出 Jenkins,将我在 CloudBees 的角色转换为顾问,并将注意力转向我的新创业公司。这篇文章的其余部分将结合这种过渡的背景,如果您没有与我紧密合作,这可能会令您惊讶。\nJenkins 之旅充满神奇,而且从未间断。我非常喜欢这一切,尤其是与造就 Jenkins 如今成就的世界各地的用户会面与交流。作为项目的创建者,在某个时候,我开始想如何将火炬传递给下一任领导者,如何使人们继续推动它前进。如今,由于有了 CloudBees 和社区,新一代的才华横溢、有才干的领导者正在热情地推动事情向前发展,这真令人高兴。例如,新选举的董事会成员和Jenkins X 的伙伴们。这些新人带来了新的文化和新的代码,并且总的来说,这产生了积极的影响,使 Jenkins 不再局限于我所谈论的局部最优方法,他们得到我所有的支持和尊重。实际上,我最近与 Jenkins 的关系更多的是象征意义,有点像日本的天皇或英国的皇后,这就是为什么此公告对 Jenkins 的前进动力几乎没有实际影响的原因。\n几年前,我曾经觉得如果我退出的话,天就会塌下来。在 2019 年的某个时刻,我突然发现我没有这种感觉了。这种转变是渐进的、稳定的,所以我不确定自己何时跨过的这道门槛,但是在 2019 年,我显然处于另一端。这样我才知道自己终于可以结束我的这一篇章。回首与 Jenkins 在一起 15 年,与 CloudBees 合作 9 年,这真是很长的一段时间。\n我希望您会想知道我的新篇章是什么。我将与我的老伙伴 Harpreet Singh 创办一家新的创业公司,即 Launchable。自从在 Sun Microsystems 和 JavaEE 工作以来,我就认识他,他是我在 CloudBees 领域的合伙人,从头开始建立 Jenkins 业务。他去 Atlassian 经营 BitBucket 业务已有一段时间,但是现在他和我又回到了一起。许多 CloudBees 人投资了 Launchable,包括 Sacha Labourey、Bob Bickel 和 John Vrionis。\n通过 Jenkins 和 CloudBees ,我得以推动软件开发中自动化的发展。这种自动化产生了大量数据,但我们并未使用这些数据来改善我们的生活,这确实是一个浪费的金矿。Launchable 正在努力利用这些信息来提高开发人员的生产力。我写了一篇单独的博客文章,以讨论有关我的想法的更多信息。\n最后,即使离开 CloudBees 不再作为其一名全职员工,也并没有完全离开,我将继续作为 CloudBees 的顾问,我仍然在情感和财务上都对 CloudBees 进行了大量投资。我仍然是狂热的粉丝,我会继续为他们加油,只不过是在默默观望。Jenkins 也一样,我仍然在董事会中,以确保连续性。我仍在持续交付基金会的技术监督委员会任职,虽然我的主席任期将于 3 月届满。\n对于本篇章所给予的宝贵机会和特权,我深表感谢。我周围有许多出色的、鼓舞人心和才华横溢的人,从他们那里学到很多东西。我只能希望我能够产生积极的影响,并回馈他们。 我不会说出名字,但您知道您是谁,我们会保持联系。\n对我来说,今年将是令人兴奋一年。 超越无限!!\n",
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
        "auhtor": "kohsuke",
        "translator": "zhaoying818",
        "original": "https://jenkins.io/blog/2020/01/23/a-new-chapter-for-kohsuke/",
        "poster": "thanks-kohsuke.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/02/2020-02-10-websocket/",
        "title": "WebSocket",
        "type": "wechat",
        "date": "2020-02-10 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "WebSocket"],
        "description": "谈谈 Jenkins 对 WebSocket 的实验性支持",
        "content": "我很高兴地提出报告,JEP-222 从 Jenkins 每周更新版开始落地。此改进为 Jenkins 带来了实验性的 WebSocket 支持,可在连接入站代理程序或运行 CLI 时使用。WebSocket 协议允许通过 HTTP(S)端口进行双向交互式通信.\n尽管 Jenkins 的许多用户都可以受益,但实现该系统对 CloudBees 尤为重要,因为 现代云平台上的 CloudBees Core(即在 Kubernetes 上运行)如何配置网络。当管理员希望将入站(以前称为“JNLP”)外部代理连接到 Jenkins 主服务器(例如在集群外部运行并使用代理服务包装器的 Windows 虚拟机)时,到目前为止,唯一的选择是使用特殊的 TCP 端口。需要使用低级网络配置将此端口开放给外部流量。例如,nginx 入口控制器的用户将需要为集群中的每个 Jenkins 服务代理一个单独的外部端口。有关此操作的说明很复杂,很难调试。\n使用 WebSocket,现在可以在存在反向代理的情况下更简单地连接入站代理:如果 HTTP(S)端口已在提供流量,则大多数代理将允许 WebSocket 连接而无需其他配置。可以在代理配置中启用 WebSocket 模式,并且即将推出 Kubernetes 插件中对基于 Pod 的代理的支持。您将需要一个4.0 或更高版本的代理,该代理版本以常规方式与 Jenkins 捆绑在一起(带有该版本的 Docker 镜像即将发布)。\nJenkins 的另一个对反向代理用户造成麻烦的部分是 CLI。除了端口 22 上的 SSH 协议(这又是从外部打开的麻烦)之外,CLI 还具有使用 HTTP(S)传输的功能.不幸的是,用于实现混淆某些技巧的技巧并不十分可移植。Jenkins 2.217 提供了一个新的 webSocket CLI 模式,该模式避免了这些问题。再次说明,您将需要下载新版本的 jenkins-cli.jar 才能使用此模式。\n已经针对 Kubernetes 实现示例(包括 OpenShift)对 WebSocket 代码进行了测试,但是很可能仍然存在一些 bugs 和局限性,并且尚未测试重构建负载下代理的可伸缩性。暂时将此功能视为 Beta 版,并让我们了解其工作原理!\n",
        "auhtor": "Jesse Glick",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2020/02/02/web-socket/",
        "poster": "cover.jpg"
    },
171
    {
172
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/01/2020-01-10-the-complete-ci-cd-collection-tutorials/",
173 174 175 176 177 178 179 180 181 182 183
        "title": "完整的 CI/CD 集合[教程]",
        "type": "wechat",
        "date": "2020-01-10 00:00:00 +0000 UTC",
        "tags": ["CI/CD", "Blog"],
        "description": "我们收集了完整的 CI/CD 关于教程、工具、最佳实践的博客,分享 CI/CD 的那些事儿",
        "content": " 什么是 CI/CD?  什么是 CI/CD?作者:Izzy Azeri-让我们看一下 CI 和 CD,这是所有 DevOps 商店的基本基石,并看看如何利用这些概念来帮助更好地交付下一个项目。 什么是持续集成和持续交付?作者:Arnab Roy—我们深入探讨了 DevOps 环境的两个基本要素。 什么是持续交付?好处和最佳实践,作者:ATC 团队-看看持续交付如何适合 DevOps 流水线,它与持续部署有何不同以及一些最佳实践。 持续集成与持续交付,作者:Rebecca Pruess—持续集成和交付是最常见的 DevOps 术语中的两个。但是,从字面上和您的业务来讲,它们是什么意思? 持续交付与持续部署与持续集成之间的差异(以及如何最佳利用它们),作者:Angela Stringfellow—所有这些持续概念之间的真正区别是什么?从 DevOps 专家那里了解有关此内容的更多信息,以充分利用 CI 和 CD。 持续集成和工作流程简介,作者:Rekha Sree—所有这些持续概念之间的真正区别是什么?从 DevOps 专家那里了解有关此内容的更多信息,以充分利用 CI 和 CD。  CI/CD 入门  了解如何从头开始建立 CI/CD 流水线,作者:Samarpit Tuli—作为现代 DevOps 流程的基础,理解 CI/CD 并学习如何从头开始建立流水线非常重要。 持续输送流水线的各个阶段,作者:Pavan Belagatti—使用 CD 流水线是采用敏捷和 DevOps 的重要组成部分,这将提高组织的整体生产力。 AWS 提供的安全且可扩展的 CI/CD 流水线,作者:Chandani Patel—Amazon 和 DevOps 与许多工具和流程紧密结合,可实现高效的 CI/CD 流水线。 使用 Visual Studio 建立 CI/CD 流水线,作者:Mohamed Radwan—了解如何在 Visual Studio Team Services 中设置 CI/CD 流水线以自动执行代码的构建,测试和部署。 Kubernetes、Jenkins、Spinnaker 的 CI/CD,作者:Arvind Rajpurohit 和 Karan Patil—这是一个新工具,可以帮助您将新的构建不断地部署到 Kubernetes 集群。 使持续交付到数据库,作者:Matt Hilbert—无需使用不熟悉的流程和强制执行的策略将其添加到您现有的基础架构中,而是可以将数据库 CD 与现有系统一起实施。 用 Git 和 Jenkins 建立一个持续交付流水线,作者:Lyndsey Padget—了解如何利用 Git 的强大功能和简单性与 Jenkins 建立自动持续交付流水线。 使用 Jenkins、Helm、Kubernetes 轻松自动化 CI/CD 流水线,作者:Eldad Assis—了解如何使用 Jenkins、Helm、Kubernetes 设置工作流以自动化 CI/CD 流水线,以快速轻松地进行部署。 使用 Hashicorp Terraform 和 Jenkins 的不可变基础架构 CI/CD,作者:Radhakrishnan Rk—这篇内容广泛的文章应该会留下一些关于创建基础设施的问题没有得到解答。  CI/CD 工具和技术  20 种最佳持续集成工具:优化 CI/CD 流程的指南,作者:Ben Patterson—CI/CD 流水线是创建可靠的 DevOps 流程的关键,该流程可将稳定的产品更快地推向市场。 CI/CD 工具的淘汰:Jenkins vs、TeamCity vs、Bamboo,作者:Ben Putano—看看 DevOps 的三个顶级 CI/CD 工具-Jenkins、TeamCity、Bamboo-为您提供做出选择的建议。 我应该使用哪种 CI/CD 工具,作者:Anita Buehrle—了解典型的自动化 CI/CD 部署流水线的组件以及为什么需要它。 适用于 DevOps 和持续交付的最佳自动化测试工具(前 10 名),作者:Lavanya C—检查这些自动化测试工具,以在软件开发生命周期中实现持续交付。 前 8 个持续集成工具,作者:Vladimir Pecanac—如果您未来使用 C/I,Vladimir Pecanac 很好地概述了您的组织应考虑使用的 8 种持续集成工具。 Ansible 安装 CI/CD 工具:您需要知道的一切,作者:Evgeny Mekhanikov—了解如何使用 IT 自动化工具 Ansible 为 CI/CD 流水线设置工具。 Kubernetes 的 11 种持续交付工具(第 1 部分),作者:Anita Buehrle—一旦您的 Kubernetes 应用程序启动并运行,您将需要为 CI/CD 流水线构建其余部分。  CI/CD 最佳实践和关注点  CI 失败的 5 大原因,作者:Shashikant Jagtap—使用质量低下的服务器会浪费每个人的时间,因为构建时间太长,无法完成,从而导致测试结果断断续续,并使工程师感到沮丧。 降低持续交付速度的 6 个常见挑战,作者:Ben Putano—按照以下步骤进行持续交付和高质量代码,克服障碍并加速您的成功。 2019 年学习 Jenkins 和 CI/CD 的 5 门课程,作者:Javin Paul—查看这些免费课程,以帮助您了解有关使用 DevOps 工具 Jenkins 的更多信息。 CD/CI 成功所需的基本方法,作者:Ben Putano—如果您希望开始使用 CI/CD 流水线,则需要掌握一些基础知识。这篇文章将帮助您。 选择 CI 平台时应考虑的 10 件事,作者:Pavan Belagatti—持续集成是采用 DevOps 的第一步。选择 CI 平台时,请牢记这十个因素。 持续集成第 3 部分:最佳做法,作者:Deepak Karanth 和 RJ Williams—本文介绍了持续集成的最佳实践,以及采用 DevOps 原则(如自动部署等)的提示和预防措施。  ",
        "auhtor": "Andre Lee-Moye",
        "translator": "wenjunzhangp",
        "original": "https://dzone.com/articles/the-complete-cicd-collection-tutorials",
        "poster": "12682719-befunky-photo-2.jpg"
    },
184
    {
185
        "uri": "https://jenkins-zh.cn/meeting/2020-01-08/",
186 187 188 189 190 191 192 193 194 195 196
        "title": "",
        "type": "meeting",
        "date": "2020-01-08 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 线下活动\n 北京 其他城市  GSoC\n Jenkins 发行版(https://community.jenkins-zh.cn/t/jenkins/241)  论坛\n 自动同步博客文章   ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
197
    {
198
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/12/2019-12-31-implement-cicd-for-multibranch-pipeline-in-jenkins/",
199 200 201 202 203 204 205 206 207 208 209
        "title": "使用 Jenkins 实现 CI/CD 多分支流水线",
        "type": "wechat",
        "date": "2019-12-31 00:00:00 +0000 UTC",
        "tags": ["jenkins", "multi-branch"],
        "description": "基于 Jenkins 多分支流水线任务类型创建 CI/CD 多分支流水线",
        "content": " 简介 Jenkins 是一个持续集成服务器,用于从版本控制系统(VCS)中获取最新代码,然后对其进行构建、测试并将结果通知给开发人员。除了作为一个持续集成(CI)服务器之外,Jenkins 还可以做很多其它的事情。最初它被称为 Hudson,是川口耕介(Kohsuke Kawaguchi)基于 Java 编写的一个开源项目,因此,在安装和运行 Jenkins 之前,首先需要安装 Java 8。\n多分支流水线是 Jenkins 中的一种流水线类型,它允许您在 Jenkinsfile 的帮助下为源码管理(SCM)库中的每个分支自动地创建一支流水线。\n什么是 Jenkinsfile Jenkinsfile 是一个文本文件,被用来定义一个 Jenkins 流水线。在 Jenkinsfile 中可以使用领域特定语言(DSL)编写运行 Jenkins 流水线所需要的步骤,从而将流水线实现为代码。\n来自 Jenkins 的定义 使用多分支流水线,您可以为同一项目的不同分支实现不同的 Jenkinsfile,Jenkins 将会自动发现、管理和执行那些分支中包含 Jenkinsfile 的流水线。\n创建一个简单多分支流水线任务的步骤  点击 Jenkins 工作台左上角的 New Item 选项:   在 Enter an item name 中填入任务名,向下滚动,然后选择 Multibranch Pipeline,最后点击 OK 按钮:   填写任务描述(可选)。\n 添加一个分支源(例如:GitHub)并且填写代码仓库的位置。\n 选择 Add 按钮添加凭证并点击 Jenkins。\n 键入 GitHub 用户名、密码、ID 和描述。\n 从下拉菜单中选择凭证:\n   点击 Save 保存该多分支流水线任务。\n Jenkins 会自动扫描指定的仓库并为 Organization 文件夹添加索引。Organization 文件夹使得 Jenkins 能够监视整个 GitHub Organization 或 Bitbucket Team/Project,并自动为包含分支的仓库创建新的多分支流水线,然后拉取包括 Jenkinsfile 在内的源码:\n   当前,这项功能仅适用于 GitHub 和 Bitbucket 中的仓库,分别由 GitHub Organization Folder 和 Bitbucket Branch Source 这两个插件提供。\n 一旦任务被成功创建,构建将会被自动触发:\n  配置 Webhooks  我们需要配置 Jenkins 服务器以便与我们的 GitHub 仓库通信,为此,我们要获取 Jenkins 的 Hook URL。\n 导航到 Manage Jenkins 页面,然后选择 Configure System。\n 找到 GitHub 插件配置部分,然后点击 Advanced 按钮。\n 选择 Specify another hook URL for GitHub configuration:\n   将文本框中的 URL 复制出来。\n 单击 Save,返回到 Jenkins 工作台。\n 打开浏览器,导航到 GitHub 选项卡,然后选择您的 GitHub 仓库。\n 单击 Settings,导航到仓库设置:\n   点击 Webhooks 部分。\n 点击 Add Webhook 按钮,然后将 Hook URL 粘贴在 Playload URL 中。\n 确保 Webhook 触发器已选中 Just the push event 选项。\n   点击击 Add webhook,就会把此 webhook 添加到您的仓库。\n 正确添加 Webhook 后,您将会看到带有绿勾的 Webhook:\n   返回到仓库,然后切换到对应分支并更新任何文件。在此,我们更新 README.md 文件。\n 现在将会看到 Jenkins 任务被自动触发:\n   流水线执行完成后,可以通过点击 Build History 下的构建号来验证执行过的构建。\n 点击构建号,然后选择 Console Output,您便可以看到每个构建步骤的输出日志:\n  进一步阅读 Learn How to Set Up a CI/CD Pipeline From Scratch\nAPI Builder: A Simple CI/CD Implementation – Part 1\n",
        "auhtor": "Krishna Prasad Kalakodimi",
        "translator": "anxk",
        "original": "https://dzone.com/articles/implement-ci-for-multibranch-pipeline-in-jenkins",
        "poster": "cover.jpg"
    },
210
    {
211
        "uri": "https://jenkins-zh.cn/wechat/articles/2020/01/2020-01-13-welcome-to-the-matrix/",
212 213 214 215 216 217 218 219 220 221 222
        "title": "欢迎使用流水线指令-矩阵",
        "type": "wechat",
        "date": "2019-12-29 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "pipeline"],
        "description": "介绍了声明式流水线中 `matrix` 指令的使用方法,并介绍了 `matrix` 指令在pipeline中的句式",
        "content": " 我经常发现自己需要在一堆不同的配置上执行相同的操作。到目前为止,意味着我需要在流水线上的同一阶段制作多个副本。当我需要修改时,必须在整个流水线的多个地方做相同的修改。对于一个更大型的流水线来说,即便维护很少的配置也会变得困难。 声明式流水线1.5.0-beta1(可以从Jenkins 实验性更新中心获取)添加了一个新的 matrix 部分,该部分能让我一次指定一个阶段列表,然后在多个配置上并行运行同一列表。让我们来看一看!\n单一配置流水线 开始我会使用一个带有构建和测试阶段的简单流水线。我使用 echo 步骤作为构建和测试行为的占位符。\nJenkinsfile\npipeline { agent none stages { stage('BuildAndTest') { agent any stages { stage('Build') { steps { echo 'Do Build' } } stage('Test') { steps { echo 'Do Test' } } } } } }  多平台与浏览器的流水线 我更喜欢在多系统以及浏览器结合的情况下执行我的构建和测试。新的 metrix 指令能让我定义一个 axes 的集合。每个 axis 有一个 name 以及包含了一个或多个 values 的列表。当流水线运行的时候,Jenkins 会将这些托管过来并将每个“轴”上所有可能值的组合运行在我的阶段内。一个“矩阵”上所有的元素都是并行运行的(只受限于可用的节点数量)。 我的“矩阵”有两个“轴”: PLATFORM 和 BROWSER 。PLATFORM 有三个值 BROWSER 有四个值,所以我的阶段会运行12个不同的组合。我已经修改了我的 echo 步骤用来使用每个元素中“轴”的值。\nJenkinsfile\npipeline { agent none stages { stage('BuildAndTest') { matrix { agent any axes { axis { name 'PLATFORM' values 'linux', 'windows', 'mac' } axis { name 'BROWSER' values 'firefox', 'chrome', 'safari', 'edge' } } stages { stage('Build') { steps { echo \u0026quot;Do Build for ${PLATFORM} - ${BROWSER}\u0026quot; } } stage('Test') { steps { echo \u0026quot;Do Test for ${PLATFORM} - ${BROWSER}\u0026quot; } } } } } } }  日志输出(部分内容)\n... [Pipeline] stage [Pipeline] { (BuildAndTest) [Pipeline] parallel [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'edge') (hide) [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'edge') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'edge') ... Do Build for linux - safari Do Build for linux - firefox Do Build for windows - firefox Do Test for linux - firefox Do Build for mac - firefox Do Build for linux - chrome Do Test for windows - firefox ...  排除无效的组合 现在我已经创建一个基本的“矩阵”了,我注意到我有一些无效的组合。 Edge 浏览器只在 Windows 系统上运行以及没有 Linux 版本的 Safari。 我可以使用 exclude 命令去掉我的“矩阵”中无效的元素。每个 exclude 含有一个或多个带有 name 和 values 的 axis 指令。一个 exclude 中的 axis 指令会生成一组组合(类似于生成“矩阵”中的元素)。“矩阵”中的元素匹配一个 exclude 中所有需要从“矩阵”中移出的值。如果我有不止一个 exclude 指令,每个都将分别评估来移除元素。 当需要处理一个长的排除列表时,我可以使用 notValues 而不是 values 去指定“轴”中我们不想排除的值。是的,这有点双重否定的意思,所以会有一点困惑。我只会在我真正想用的时候才会用它。 下面的流水线示例,我排除了 linux, safari 的组合同样我排除了除了 windows 之外的其他平台 和 edge 浏览器的组合。 重要 本流水线使用两个“轴”,但是没有使用 axis 指令数量的限制。 同样,在这个流水线里每个 exclude 指定这两个“轴”的值,但是这不是必须的。如果我们想只在“linux”元素中运行,我们需要使用以下的 exclude :\nexclude { axis { name 'PLATFORM' notValues 'linux' } }  pipeline { agent none stages { stage('BuildAndTest') { matrix { agent any axes { axis { name 'PLATFORM' values 'linux', 'windows', 'mac' } axis { name 'BROWSER' values 'firefox', 'chrome', 'safari', 'edge' } } excludes { exclude { axis { name 'PLATFORM' values 'linux' } axis { name 'BROWSER' values 'safari' } } exclude { axis { name 'PLATFORM' notValues 'windows' } axis { name 'BROWSER' values 'edge' } } } stages { stage('Build') { steps { echo \u0026quot;Do Build for ${PLATFORM} - ${BROWSER}\u0026quot; } } stage('Test') { steps { echo \u0026quot;Do Test for ${PLATFORM} - ${BROWSER}\u0026quot; } } } } } } }  日志输出(部分内容)\n... [Pipeline] stage [Pipeline] { (BuildAndTest) [Pipeline] parallel [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'edge') ... Do Build for linux - firefox ...  运行时控制元素行为 在 matrix 指令中同样我可以添加“每个-元素”指令。这些相同的指令我可以添加到一个 stage 中让我可以控制“矩阵”中每一个元素的行为。这些指令可以从它们的元素的“轴”中获取值作为输入,允许我自定义每一个元素的行为以匹配它的“轴”的值。 在我的 Jenkins 服务器中我已经配置了各个节点并为各个节点配置了系统名称的标签(“linux-agent”,“windows-agent”,和“mac-agent” )。为了在正确的操作系统上运行“矩阵”中的元素,我配置了 Groovy 字符模板为元素配置标签。\nmatrix { axes { ... } excludes { ... } agent { label \u0026quot;${PLATFORM}-agent\u0026quot; } stages { ... } // ... }  有时我通过 Jenkins 的网页手动运行流水线任务。当我这样做时,我能够只选择一个运行的平台。 axis 和 exclude 指令定义了一个组成“矩阵”的一组静态的元素。这一组合的集合在运行开始之前就被创建出来,也早于任何的参数获取。也就意味着我不能在任务已经开始后从“矩阵”上添加或者移除元素。 另一方面,“每个-元素”指令,在运行时会被评估。我可以使用“每个-元素” metrix 中的 when 指令来控制“矩阵”中哪个元素会被执行。我添加了一个带有平台列表的 choice 字段,以及在 when 指令添加了判断,这样会确定是所有的平台都执行还是只执行我指定的平台的元素。\npipeline { parameters { choice(name: 'PLATFORM_FILTER', choices: ['all', 'linux', 'windows', 'mac'], description: 'Run on specific platform') } agent none stages { stage('BuildAndTest') { matrix { agent { label \u0026quot;${PLATFORM}-agent\u0026quot; } when { anyOf { expression { params.PLATFORM_FILTER == 'all' } expression { params.PLATFORM_FILTER == env.PLATFORM } } } axes { axis { name 'PLATFORM' values 'linux', 'windows', 'mac' } axis { name 'BROWSER' values 'firefox', 'chrome', 'safari', 'edge' } } excludes { exclude { axis { name 'PLATFORM' values 'linux' } axis { name 'BROWSER' values 'safari' } } exclude { axis { name 'PLATFORM' notValues 'windows' } axis { name 'BROWSER' values 'edge' } } } stages { stage('Build') { steps { echo \u0026quot;Do Build for ${PLATFORM} - ${BROWSER}\u0026quot; } } stage('Test') { steps { echo \u0026quot;Do Test for ${PLATFORM} - ${BROWSER}\u0026quot; } } } } } } }  如果我从 Jenkins 的 UI 页面上运行流水线设置 PLATFORM_FILTER 字段为 mac ,我会得到如下的输出:\n日志输出(部分内容 - PLATFORM_FILTER = \u0026lsquo;mac\u0026rsquo;)\n... [Pipeline] stage [Pipeline] { (BuildAndTest) [Pipeline] parallel [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'firefox') [Pipeline] { (Branch: Matrix - OS = 'linux', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'chrome') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'mac', BROWSER = 'safari') [Pipeline] { (Branch: Matrix - OS = 'windows', BROWSER = 'edge') ... Stage \u0026quot;Matrix - OS = 'linux', BROWSER = 'chrome'\u0026quot; skipped due to when conditional Stage \u0026quot;Matrix - OS = 'linux', BROWSER = 'firefox'\u0026quot; skipped due to when conditional ... Do Build for mac - firefox Do Build for mac - chrome Do Build for mac - safari ... Stage \u0026quot;Matrix - OS = 'windows', BROWSER = 'chrome'\u0026quot; skipped due to when conditional Stage \u0026quot;Matrix - OS = 'windows', BROWSER = 'edge'\u0026quot; skipped due to when conditional ... Do Test for mac - safari Do Test for mac - firefox Do Test for mac - chrome  重要 在DevOps World | Jenkins World 2019 “声明式流水线2019:知识点,技巧,以及接下来的事情”中与我一起参与。我会回顾过去的一年有哪些加入到了流水线(包括“矩阵”)以及探讨一些关于流水线下一步走向的想法。\n结论 这篇博客里面,我们已经看到了怎样使用 matrix 指令来构成简洁但又强大的声明式流水线。同样的一个不带有 matrix 的流水线会容易一些,但会消耗更多的时间同样也会更难理解和维护。\n链接  Jenkins 实验性更新中心 使用 Jenkins 实验性更新中心  ",
        "auhtor": "Liam Newman",
        "translator": "0N0thing",
        "original": "https://jenkins.io/blog/2019/11/22/welcome-to-the-matrix/",
        "poster": "cover.jpg"
    },
223
    {
224
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/12/2019-12-26-jcli-v0.0.24/",
225 226 227 228 229
        "title": "Jenkins CLI 命令行 v0.0.24",
        "type": "wechat",
        "date": "2019-12-26 00:00:00 +0000 UTC",
        "tags": [],
        "description": "jcli-v0.0.24 发布",
230
        "content": " 本次发布,主要增加了 jcli 对凭据、计算节点的管理能力,以及通过 jcli 启动 jenkins.war。 对于部分子命令,还可以通过参数 --doctor 来实现错误诊断。\n部分数据指标 * 测试覆盖率:87.1% * 下载量:2.8k+ * 贡献者:9\n更多内容,请参考官方文档\n🚀 功能  增加对配置即代码插件的支持 (#265) @LinuxSuRen 为 jcli 增加 Docker 镜像 (#260) @LinuxSuRen 增加 Jenkins 的 go 语言客户端的文档 (#256) @1179325921 支持获取 Jenkins 的唯一标识信息 (#292) @LinuxSuRen 支持在命令行中设置 Jenkins 连接地址 (#291) @LinuxSuRen 支持通过管理员为 Jenkins 的其他用户创建令牌 (#289) @LinuxSuRen 支持创建 JNLP 类型的计算节点 (#290) @LinuxSuRen 改进命令行的数据输出 (#285) @LinuxSuRen 增强 Jenkins 任务的搜索功能 (#284) @LinuxSuRen 增加搜索 Jenkins 任务以及文件夹 (#281) @LinuxSuRen 为 casc 命令增加诊断功能 (#280) @LinuxSuRen 增加计算节点的子命令 (#278) @LinuxSuRen 支持对 Jenkins 凭据的管理 (#266) @LinuxSuRen 支持发布插件的子命令 (#276) @LinuxSuRen 增加命令行输出中对配色的支持 (#273) @LinuxSuRen 支持同时取消队列中的多个任务 (#274) @LinuxSuRen 支持在启动 jenkins.war 时传递系统配置 (#275) @LinuxSuRen 支持通过 docker 的方式下载最新开发版本的 jcli (#267) @LinuxSuRen 支持启动 Jenkins (#262) @LinuxSuRen 支持列出 Jenkins 的计算节点 (#259) @LinuxSuRen  🐛 缺陷修复  修复 PO 文件中的拼写错误 (#282) @anxk 修复了当没有配置文件时命令崩溃的问题 (#269) @LinuxSuRen 修复由 lgtm.com 发现的告警 (#293) @LinuxSuRen 修复由于代码重构导致的 bash 下的命令行无法自动补全 (#294) @LinuxSuRen  📝 文档完善  增加对开发环境要求的描述 (#263) @yJunS 增加下载 jcli 的其他方式的描述 (#264) @LinuxSuRen  👻 维护  移除 markdown 模板中的链接 (#271) @LinuxSuRen 优化 jcli 的开发版 docker 镜像,使得更小 (#268) @LinuxSuRen 增加拉取镜像数量的徽章 (#261) @LinuxSuRen 把 github.com/onsi/ginkgo 从 1.10.3 升级到 1.11.0 (#288) @dependabot-preview 把 github.com/onsi/gomega 从 1.7.1 升级到 1.8.1 (#287) @dependabot-preview 把 github.com/AlecAivazis/survey/v2 从 2.0.4 升级到 2.0.5 (#270) @dependabot-preview  🚦 测试  为 open 子命令增加测试用例 (#272) @LinuxSuRen  ",
231 232 233 234 235
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "jenkins-cli.png"
    },
236
    {
237
        "uri": "https://jenkins-zh.cn/meeting/2019-12-25/",
238 239 240 241 242 243 244 245 246 247 248
        "title": "",
        "type": "meeting",
        "date": "2019-12-25 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 论坛\n 邮箱没有配置好(网络超时,怀疑是由于网络代理设置的有问题) 给管理更多的管理权限  依赖邮箱的配置  把论坛的版本调整为正式版 @yJunS  介绍 Jenkins 容器发行版\n 尝试提一个 proposal 到 GSOC(https://jenkins.io/sigs/gsoc/) Jenkins 发行版的定制  jenkins+2.190.3+localization-zh-cn+++ http://custom.jenkins-zh.cn?version=2.190.3\u0026amp;plugin=localization-zh-cn   增加文章作者(译者)的统计\n 增加例会参加成员的统计\n 定期的网络研讨会(https://community.jenkins-zh.cn/t/jenkins/149)\n 媒体情况统计\n 论坛 公众号  文章翻译 https://github.com/jenkins-infra/wechat/pull/282\n  ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
249
    {
250
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/12/2019-12-23-generic-webhook-trigger-plugin/",
251 252 253 254
        "title": "Webhook 通用触发插件",
        "type": "wechat",
        "date": "2019-12-23 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "Webhook"],
255
        "description": "介绍通用 Webhook 触发插件,使用 Webhook 插件构建 Jenkins 自动化服务",
256 257 258 259 260 261
        "content": " 这篇文章将介绍我在 Jenkins 上遇到的一些常见问题,以及如何通过开发通用 Webhook 触发插件来解决这些问题。\n问题 在使用 Jenkins 工作时,我经常遇到同样的问题:\n 代码重复和安全性-每个仓库中的 Jenkinsfiles。 分支不是功能-master 上的参数化任务通常会混合与不同功能相关的参数。 记录不良的触发器插件-记录正常服务但记录不佳的使用插件  代码重复和安全性 每个 Git 仓库中都有 Jenkinsfiles,使开发人员可以使这些文件分开。开发人员 push 他们的项目,并且很难维护共享代码的模式。\n我几乎用共享库解决了代码重复问题,但是它不允许我设置必须遵循的严格模式。任何开发人员仍然可以决定不调用共享库提供的功能。\n还允许开发人员运行 Jenkinsfiles 中的任何代码的安全性方面。例如,开发人员可能会打印从凭据收集的密码。让开发人员在 Jenkins 节点上执行任何代码对我来说似乎不合适。\n分支不是功能 在 Bitbucket 中有项目,每个项目都有 git 仓库的集合。像这样:\n PROJ_1  REPO_1 REPO_2  PROJ_2  REPO_3   让我们考虑一下我们要为这些仓库提供的一些功能:\n pull request 验证 构建快照(如果需要的话,也可以预发布) 构建发布  如果开发人员习惯于在 Bitbucket 中像这样组织仓库,我们是否应该在 Jenkins 中以同样的方式组织它们?而且,如果他们浏览 Jenkins,是否不应该为每种功能(例如 pull-request,snapshot 和 release)找到一份构建任务?每个具有仅与该功能相关的参数的任务。我认同!像这样:\n / - Jenkins root  /PROJ_1 - 一个文件夹,列出 git 仓库。  /PROJ_1/REPO_1 - 一个文件夹,列出与该仓库相关的任务。 /PROJ_1/REPO_1/release - 一份构建任务,执行发布。 /PROJ_1/REPO_1/snapshot - 一份构建任务,执行快照发布。 /PROJ_1/REPO_1/pull-request - 一份构建任务,验证 pull-request。   …​  在此示例中,snapshot 和 release 任务都可以在同一 git 分支上工作。不同之处在于它们提供的功能。它们的参数可以很好地记录下来,因为您不必混合与发行版和快照相关的参数。使用多分支流水线插件无法做到这一点,在多分支流水线插件中,您将参数指定为每个分支的 properties。\n文献资料 Webhooks 通常在提供它们的服务中有据可查。例如:\n Bitbucket Cloud Bitbucket Server GitHub GitLab Gogs 和 Gitea Assembla Jira  令我困扰的是,即使我理解了这些 webhooks,我也无法使用它们。因为我需要在所使用的插件中进行开发,以便提供从 Webhook 到构建的任何值。从 PR 到实际发布,该过程可能需要几个月的时间。这样简单的事情实际上应该不是问题。\n解决方案 我的解决方案几乎可以追溯到基本知识:我们有一个自动化服务(Jenkins),我们想在外部 Webhooks 上触发它。我们想从该 Webhook 收集信息并将其提供给我们的构建。为了支持它,我创建了通用 Webhook 触发器插件。\n仓库中提供了最新文档,并且有一个完整的示例,其中使用 configuration-as-code 实现了 GitLab。在这里查看仓库。\n代码重复和安全性 我制定了所有开发人员都必须遵循的约定。而不是让开发人员从 Jenkinsfiles 显式调用基础结构。遵循一些规则,例如:\n 所有的 git 仓库都应该从仓库的根开始构建。 如果包含 gradlew  使用 ./gradlew build 完成构建 使用 ./gradlew release 完成发布 \u0026hellip;\u0026hellip;等等  如果包含 package.json  使用 npm run build 完成构建 使用 npm run release 完成发布 \u0026hellip;\u0026hellip;等等   有了这些规则,流水线就可以完全通用,并且在仓库中不需要 Jenkinsfiles。由于某些原因,某些 git 仓库可能需要禁用测试用例。这可以通过允许仓库添加一个特殊文件,也就是 jenkins-settings.json 来解决,让基础架构发现其内容并对其采取行动。\n即使没有执行 CI,这也可以帮助开发人员。当他们克隆一个新的,未知的仓库时,他们将知道可以发出哪些命令及其语义。\n分支不是功能 我实现:\n Jenkins 任务配置-使用任务 DSL。 Jenkins 的构建过程-使用 Pipelines 和共享库。  通过与 Job DSL 中的 git 服务集成,我可以自动找到 git 仓库。我创建动态组织在文件夹中的任务。还调用 git 服务来设置触发这些任务的 webhooks。任务是普通的流水线,不是多分支,它们不使用 Git 中的 Jenkinsfile,而是使用 Job DSL 在任务中配置的 Jenksinfile。因此,所有任务配置和流水线均受版本控制。这一切都在这里发生。\n文献资料 该插件使用 JSONPath 以及 XPath 从 JSON 提取值并将其提供给构建。让用户从 webhook 中选择所需的内容。它还具有一个正则表达式过滤器,以允许在某些情况下不触发。\n该插件不是很大,只是 webhook、JSONPath/XPath 和正则表达式之间的粘合剂。所有这些部分都已被很好地记录下来,我会尽力维护该插件。这是一个非常有据可查的解决方案!\n",
        "auhtor": "Tomas Bjerre",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/12/14/generic-webhook-trigger-plugin/",
        "poster": "cover.png"
    },
262
    {
263
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/12/2019-12-19-full-build-automation-for-java-application-using-docker/",
264 265 266 267 268
        "title": "使用 Docker 全自动构建 Java 应用",
        "type": "wechat",
        "date": "2019-12-19 00:00:00 +0000 UTC",
        "tags": ["docker", "jenkins", "pipeline", "java"],
        "description": "这个过程很长,我们的目标是让所有这些事都自动化。",
269
        "content": " 这次的流水线中,我们使用 Docker 容器来构建我们的 Java 应用。\n我们会在 Docker 容器里运行 Jenkins,再使用 Jenkins 启动一个 Maven 容器,用来编译我们的代码,接着在另一个 Maven 容器中运行测试用例并生成制品(例如 jar 包),然后再在 Jenkins 容器中制作 Docker 镜像,最后将镜像推送到 Docker Hub。\n我们会用到两个 Github 仓库。\n Jenkins-complete:这是主仓库,包含了启动 Jenkins 容器所需的配置文件。 Simple-java-maven-app:使用 Maven 创建的 简单的 Java 应用。  在搭建之前,我们先来了解一下这两个仓库。\n了解 Jenkins-complete 这是我们构建 Jenkins 镜像的核心仓库,它包含了所需的配置文件。我们通过 Jenkins 官方提供的 Docker 镜像启动 Jenkins 容器,然后完成一些动作,例如安装插件、创建用户等。\n安装好之后,我们会创建用来获取 Java 应用的 Github 凭据,还有推送镜像到 Dockerhub 的 Docker 凭据。最后,开始创建我们应用的流水线 job。\n这个过程很长,我们的目标是让所有这些事都自动化。主仓库包含的文件和详细配置会用来创建镜像。当创建好的镜像启动运行以后,我们就有了: 1. 新创建的 admin/admin 用户 2. 已经装好的一些插件 3. Docker 和 Github 凭据 4. 新创建的名为 sample-maven-job 的流水线。\n如果把源码列成树状,就看到下面的结构:\njagadishmanchala@Jagadish-Local:/Volumes/Work$ tree jenkins-complete/ jenkins-complete/ ├── Dockerfile ├── README.md ├── credentials.xml ├── default-user.groovy ├── executors.groovy ├── install-plugins.sh ├── sample-maven-job_config.xml ├── create-credential.groovy └── trigger-job.sh  我们来看看它们都是干嘛的:\n default-user.groovy - 这个文件用来创建默认用户 admin/admin。\n executors.groovy - 这个 Groovy 脚本设置 Jenkins 的执行器数量为 5。一个 Jenkins 执行器相当于一个处理进程,Jenkins job 就是通过它运行在对应的 slave/agent 机器上。\n create-credential.groovy - 用来创建 Jenkins 全局凭据的 Groovy 脚本。这个文件可以创建任意的 Jenkins 全局凭据,包括 Docker hub 凭据。我们要修改文件里 Docker hub 的用户名密码,改成我们自己的。这个文件会被复制到镜像里,然后在 Jenkins 启动时运行。\n credentials.xml - XML 凭据文件。这个文件包含了 Github 和 Docker 凭据。它看起来是这样的:\n  \u0026lt;com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl\u0026gt; \u0026lt;scope\u0026gt;GLOBAL\u0026lt;/scope\u0026gt; \u0026lt;id\u0026gt;github\u0026lt;/id\u0026gt; \u0026lt;description\u0026gt;github\u0026lt;/description\u0026gt; \u0026lt;username\u0026gt;jagadish***\u0026lt;/username\u0026gt; \u0026lt;password\u0026gt;{AQAAABAAAAAQoj3DDFSH1******\u0026lt;/password\u0026gt; \u0026lt;/com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl\u0026gt;  仔细观察上面的代码,我们可以看到一个 id 为 “github” 的用户名以及加密后的密码。这个 id 很重要,我们会在后面的流水线中用到。\n怎样拿到加密后的密码呢? 想要拿到密码加密后的内容,你需要到这里去 Jenkins server -\u0026gt; Manage Jenkins -\u0026gt; Script console,然后在输入框里输入下面的代码\nimport hudson.util.Secret def secret = Secret.fromString(\u0026quot;password\u0026quot;) println(secret.getEncryptedValue())  将 “password” 换成你自己的密码,点击运行,你就得到了加密后的内容。再把这个内容粘贴到 credentials.xml 文件里面就可以了。\nDockerHub 的密码加密过程同上。\n sample-maven-job_config.xml - 这个 XML 文件包含了流水线 job 的细节内容。Jenkins 会在 Jenkins console 里创建一个名为“sample-maven-job”的 job,这个文件包含了它的详细配置。  这个配置很简单,Jenkins 读取文件后,会先创建一个名为 “sample-maven-job” 的流水线 job,然后把仓库指向 Github。 一并设置的还有名为 “github” 的凭据 id。 看起来像是这个样子:\n配置好仓库地址以后,用来远程触发 job 的 token 也就生成了。为了设置远程触发,我们需要打开 “Trigger builds remotely” 选项, 然后把上面的 token 设置到这里。这些配置可以在流水线配置页面的 “Build Triggers” 那一节中看到。为了在后面的 shell 脚本中用这个 token 触发 job, 我们把这个 token 命名为 “MY-TOKEN”。\n trigger-job.sh - 这是一个简单的 shell 脚本,其中的 curl 命令用来触发 job。  虽然,我们在容器里创建了 Jenkins 服务和一个 job,我们还需要一个触发器来触发整个自动构建。我喜欢下面的方法:\n 启动 Jenkins Docker 容器时,完成所有需要做的事,例如创建 job、凭据、用户等。 当容器启动好后触发 job。  我写的这个简单 shell 脚本就是用来在容器启动好以后触发 job 的。shell 脚本用 curl 向 Jenkins 发送了一个 post 请求命令。内容像这样。\n Install-plugins.sh - 这是我们用来安装所有所需插件的脚本。我们会把这个脚本复制到 Jenkins 镜像,并把插件名作为它的参数。 容器启动好以后,这个脚本就会根据插件名对应的插件。\n Dockerfile - 这是自动化过程中最重要的文件。我们会用这个 Docker 文件来创建完整的 Jenkins 服务和所有配置。理解这个文件对于编写你自己的自动化构建是很重要的。\n  FROM jenkins/jenkins:lts ARG HOST_DOCKER_GROUP_ID # 使用内置的 install-plugins.sh 脚本安装我们所需的插件 RUN install-plugins.sh pipeline-graph-analysis:1.9 \\ cloudbees-folder:6.7 \\ docker-commons:1.14 \\ jdk-tool:1.2 \\ script-security:1.56 \\ pipeline-rest-api:2.10 \\ command-launcher:1.3 \\ docker-workflow:1.18 \\ docker-plugin:1.1.6 # 设置 admin 用户的环境变量 ENV JENKINS_USER admin ENV JENKINS_PASS admin # 跳过初始设置向导 ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false # 启动脚本,设置执行器的数量、创建 admin 用户 COPY executors.groovy /usr/share/jenkins/ref/init.groovy.d/ COPY default-user.groovy /usr/share/jenkins/ref/init.groovy.d/ COPY create-credential.groovy /usr/share/jenkins/ref/init.groovy.d/ # 命名 job ARG job_name_1=\u0026quot;sample-maven-job\u0026quot; RUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/latest/ RUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/builds/1/ COPY ${job_name_1}_config.xml /usr/share/jenkins/ref/jobs/${job_name_1}/config.xml COPY credentials.xml /usr/share/jenkins/ref/ COPY trigger-job.sh /usr/share/jenkins/ref/ # 添加自定义配置到容器里 #COPY ${job_name_1}_config.xml \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/config.xml USER root #RUN chown -R jenkins:jenkins \u0026quot;$JENKINS_HOME\u0026quot;/ RUN chmod -R 777 /usr/share/jenkins/ref/trigger-job.sh # 用给定的用户组 ID 创建 'Docker' 用户组 # 将 'jenkins' 用户加到 'Docker' 用户组 RUN groupadd docker -g ${HOST_DOCKER_GROUP_ID} \u0026amp;\u0026amp; \\ usermod -a -G docker jenkins RUN apt-get update \u0026amp;\u0026amp; apt-get install -y tree nano curl sudo RUN curl https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz | tar xvz -C /tmp/ \u0026amp;\u0026amp; mv /tmp/docker/docker /usr/bin/docker RUN curl -L \u0026quot;https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)\u0026quot; -o /usr/local/bin/docker-compose RUN chmod 755 /usr/local/bin/docker-compose RUN usermod -a -G sudo jenkins RUN echo \u0026quot;jenkins ALL=(ALL:ALL) NOPASSWD:ALL\u0026quot; \u0026gt;\u0026gt; /etc/sudoers RUN newgrp docker USER jenkins #ENTRYPOINT [\u0026quot;/bin/sh -c /var/jenkins_home/trigger-job.sh\u0026quot;]   FROM jenkins/jenkins:lts - 我们将使用 Jenkins 官方提供的镜像。 ARG HOST_DOCKER_GROUP_ID - 需要记住的重点出现了,虽然我们在 Jenkins 容器里创建了 Docker 容器,但我们没有在 Jenkins 自身内部创建容器。 相反,我们是在它们自己的宿主机上创建了容器。确切的说,是我们让安装在 Jenkins 容器里的 Docker tool 部署一个 Maven 容器到宿主机上。为了实现这个部署,我们需要 Jenkins 容器和宿主机设置一样的用户组。  为了允许 Jenkins 这样的未授权用户访问,我们要把 Jenkins 用户加到 Docker 用户组里去。要做到这件事,我们只需要保证容器里的 Docker 用户组与宿主机上的 Docker 有一致的 GID 即可。用户组 id 可以通过命令 getent group Docker 获得。\nHOST_DOCKER_GROUP_ID 被设为了构建参数,我们要在构建时将宿主机的 Docker 用户组 id 做为参数传进来参与构建。\n# 使用内置的 install-plugins.sh 脚本安装我们所需的插件 RUN install-plugins.sh pipeline-graph-analysis:1.9 \\ cloudbees-folder:6.7 \\ docker-commons:1.14 \\  接下来是 install-plugins.sh 脚本,把要安装的插件作为参数传给脚本。这个脚本是默认提供的,也可以从宿主机复制一份。\n给 Jenkins Admin 用户设置环境变量 ENV JENKINS_USER admin ENV JENKINS_PASS admin  我们设置了 JENKINS_USER 和 JENKINS_PASS 两个环境变量,default-user.groovy 脚本会用它们创建帐号 admin 用户(密码 admin)。\n# 跳过初始设置向导 ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false  这个使得 Jenkins 以静默模式安装\n# 设置启动器数量和创建 admin 用户的启动脚本 COPY executors.groovy /usr/share/jenkins/ref/init.groovy.d/ COPY default-user.groovy /usr/share/jenkins/ref/init.groovy.d/ COPY create-credential.groovy /usr/share/jenkins/ref/init.groovy.d/  像我们讨论的那样,上面的脚本会设置执行器各数为 5,创建默认用户 admin/admin。\n需要注意的是,如果去看 Jenkins 官方的 Docker 镜像,你会看到有一个 VOLUME 指向了 /vars/jenkins_home 目录。这个意思是设置 Jenkins 的家目录,类似于物理机上使用包管理器安装 Jenkins 时的目录 /var/lib/jenkins。\n但是,当 volume 挂载好以后,就只有 root 用户有权限在那里编辑或者添加文件。为了让未授权的 jenkins 用户复制内容到 volume, 将所有东西复制到 /usr/share/Jenkins/ref/。 这样当容器启动后,Jenkins 会自动使用 Jenkins 用户把这个位置的文 件拷贝一份到 /vars/jenkins_home 中。\n同样,复制到 /usr/share/jenkins/ref/init.groovy.d/ 的脚本会在 Jenkins 启动后被执行。\n# 命名 job ARG job_name_1=\u0026quot;sample-maven-job\u0026quot; RUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/latest/ RUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/builds/1/ COPY ${job_name_1}_config.xml /usr/share/jenkins/ref/jobs/${job_name_1}/config.xml COPY credentials.xml /usr/share/jenkins/ref/ COPY trigger-job.sh /usr/share/jenkins/ref/  在上面的例子中,我把我的 job 名字设置为 “sample-maven-job”,然后创建目录,复制一些文件。\nRUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/latest/ RUN mkdir -p \u0026quot;$JENKINS_HOME\u0026quot;/jobs/${job_name_1}/builds/1/  这些说明很重要,它们在 Jenkins 家目录创建了一些用来存放配置文件的文件夹。latest/ 和 builds/1 存放的目录也需要与其 job 相对应。\n这些创建好以后,我们把已经复制到 /var/share/jenkins/ref 的文件 “sample-maven-job_config.xml”,再让 Jenkins 复制 到 /var/jenkins_home/jobs/,这样就有了 sample-maven-job。\n最后,我们同样把 credentials.xml 和 trigger-job.sh 文件复制到 /usr/share/jenkins/ref。 当容器启动以后, 所有这个目录下的文件都会以 Jenkins 用户的权限移动到 /var/jenkins_home。\nUSER root #RUN chown -R jenkins:jenkins \u0026quot;$JENKINS_HOME\u0026quot;/ RUN chmod -R 777 /usr/share/jenkins/ref/trigger-job.sh # 用指定的用户组组 ID 创建 'docker' 用户组 # 并将 'jenkins' 用户添加到该组 RUN groupadd docker -g ${HOST_DOCKER_GROUP_ID} \u0026amp;\u0026amp; \\ usermod -a -G docker jenkins RUN apt-get update \u0026amp;\u0026amp; apt-get install -y tree nano curl sudo RUN curl https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz | tar xvz -C /tmp/ \u0026amp;\u0026amp; mv /tmp/docker/docker /usr/bin/docker RUN curl -L \u0026quot;https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)\u0026quot; -o /usr/local/bin/docker-compose RUN chmod 755 /usr/local/bin/docker-compose RUN usermod -a -G sudo jenkins RUN echo \u0026quot;jenkins ALL=(ALL:ALL) NOPASSWD:ALL\u0026quot; \u0026gt;\u0026gt; /etc/sudoers RUN newgrp docker USER jenkins  下面的指令以 root 用户执行。在 root 用户的指令下,我们使用宿主机上的 Docker group ID 在容器里创建新的 Docker 用户组。然后把 Jenkins 用户加到 Docker 组当中。\n通过这些,我们就可以使用 Jenkins 用户创建容器了。这样就能突破只有 root 用户能创建容器的限制。为了让 Jenkins 用户能创建容器,我们需要把 Jenkins 用户添加到 Docker 用户组当中去。\n在下面的指令里,我们安装了 docker-ce 和 docker-compose 工具。我们设置了 Docker-compose 的权限。最后,我们把 Jenkins 用户加到 sudoers 文件里,以给到 root 用户特定的权限。\nRUN newgrp docker  这个指令非常重要。通常我们修改一个用户的用户组,都需要重新登录以使新的设置生效。为了略过这一步,我们使用 Docker 命令 newgrp 使设置直接生效。最后,我们回到 Jenkins 用户。\n构建镜像 理解了 Docker 文件后,我们就要用它构建我们的镜像:\ndocker build --build-arg HOST_DOCKER_GROUP_ID=\u0026quot;`getent group docker | cut -d':' -f3`\u0026quot; -t jenkins1 .  在 Dockerfile 的所在目录下运行上面的 Docker 构建指令。在上面的命令中,我们传了 Docker 用户组 ID 给 build-arg。 这个值会传给 HOST_DOCKER_GROUP_ID,用来在 Jenkins 容器里创建相同 ID 的用户组。下载以及安装 Jenkins 插件会增加构建镜像的时间。\n运行镜像 镜像构建好以后,我们以下面的命令运行:\ndocker run -itd -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker -p 8880:8080 -p 50000:50000 jenkins1  关于卷挂载有两件重要的事。第一是我们把 Docker 命令挂载到了容器里,当需要其它容器时,就可以在当前容器创建了。\n另一个重要的是挂载 /var/run/Docker.sock。 Docker.sock 是 Docker 守护进程监听的一个 UNIX socket。 这是访问 Docker API 的主要入口点。它也可以是 TCP 类型的 socket,但是出于安全原因,默认设定是 UNIX 类型的。\nDocker 默认通过这个 socket 执行命令。我们把它挂载到 Docker 容器里,是为了能在容器里启动新的其它容器。这个挂载也可以用于服务自省和日志目的。但这增加了被攻击的风险,使用的时候要小心。\n上面的命令执行后,我们就得到一个运行着的 Jenkins 容器。可以通过 URL\u0026lt;ip address\u0026gt;:8880 查看 Jenkins 控制台。使用 “admin/admin” 登录 Jenkins。 我们就可以看到还没有运行过的、使用 SCM,Token 和凭据创建的 sample-maven-job。\n运行 Job 要运行这个 job,我们只需要带着 containerID 以下面的方式执行 trigger-job.sh。\ndocker exec \u0026lt;Jenkins Container ID\u0026gt; /bin/sh -C /var/jenkins_home/trigger-job.sh  运行后我们就可以看到流水线的构建开始了。\n了解 Simple Java Maven App 如上面所说,这个仓库是我们的 Java 应用。它使用 Maven 打包成品,还包含一个 Dockerfile,一个 Jenkinsfile 以及源代码。源代码结构与其它 Maven 项目类似。\n Jenkinsfile - 这是 sample-maven-job 启动前的核心文件。流水线 job 使用 Github 凭据从 Github 下载源代码。  Jenkinsfile 文件里最重要事的是定义 agent。 我们使用 “agent any” 选择任何可用的 agent 来构建代码。我们也可以为某个 stage 定义 agent 环境。\nstage(\u0026quot;build\u0026quot;){ agent { docker { image 'maven:3-alpine' args '-v /root/.m2:/root/.m2' } steps { sh 'mvn -B -DskipTests clean package' stash includes: 'target/*.jar', name: 'targetfiles' } } }  在上面的 stage 中,我们设置它的 agent 环境为 Docker 镜像 “maven:3-alpine.” 这样 Jenkins 就会触发 maven:3-alpine 容器, 然后执行定义在步骤里的命令 mvn -B -DskipTests clean package。\n同样的,单元测试也是以这样的方式运行。docker 启动一个 Maven 镜像,然后执行 mvn test。\nenvironment { registry = \u0026quot;docker.io/\u0026lt;user name\u0026gt;/\u0026lt;image Name\u0026gt;\u0026quot; registryCredential = 'dockerhub' dockerImage = '' }  另一件重要的事是定义环境。我定义了名为 docker.io/jagadesh1982/sample 的仓库,意味着使用最终制品(jar 包)所创建的镜像名称也将遵循这个格式 docker.io/jagadesh1982/sample:\u0026lt;version\u0026gt;。如果你的镜像需要推送到 Dockerhub 的话,记住这一点是非常重要的。Dockerhub 希望镜像名按照 docker.io/\u0026lt;user Name\u0026gt;/\u0026lt;Image Name\u0026gt; 这样的风格命名,以方便上传。\n当构建结束后,新的镜像会被上传到 Dockerhub,本地的镜像则会被删除。\n Dockerfile - 这个仓库包含的 Dockerfile 用来创建 jar 包的镜像。它会拷贝我的 my-app-1.0-SNAPSHOT.jar 到镜像中去。它的内容是这样:  FROM alpine:3.2 RUN apk --update add openjdk7-jre CMD [\u0026quot;/usr/bin/java\u0026quot;, \u0026quot;-version\u0026quot;] COPY /target/my-app-1.0-SNAPSHOT.jar / CMD /usr/bin/java -jar /my-app-1.0-SNAPSHOT.jar  ",
270 271 272 273 274
        "auhtor": "Jagadish Manchala",
        "translator": "tomatofrommars",
        "original": "https://dzone.com/articles/full-build-automation-for-java-application-using-d",
        "poster": "Jenkins-Docker.png"
    },
275
    {
276
        "uri": "https://jenkins-zh.cn/meeting/2019-12-11/",
277 278 279 280 281 282 283 284 285 286 287
        "title": "",
        "type": "meeting",
        "date": "2019-12-11 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 论坛\n 邮箱没有配置好 更换域名(ok)@yJunS  还有一些链接没有更换,不紧急  给管理更多的管理权限  依赖邮箱的配置  把阿里云域名的权限给到管理员 (ok) @linuxsuren 管理员招募 https://discourse.jenkins-zh.cn/t/topic/103 把论坛的版本调整为正式版 @yJunS  介绍 Jenkins 容器发行版\n https://github.com/LinuxSuRen/docker-zh (ok) Jenkins 发行版的定制  jenkins+2.190.3+localization-zh-cn+++ http://custom.jenkins-zh.cn?version=2.190.3\u0026amp;plugin=localization-zh-cn   及时把公共信息放在很明显的位置,还是有人不去仔细看\n  ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
288
    {
289
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/12/2019-12-11-jenkins-health-advisor-by-cloudbees-is-here/",
290 291 292 293 294 295 296 297 298
        "title": "Jenkins 健康检查顾问",
        "type": "wechat",
        "date": "2019-12-11 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "CloudBees"],
        "description": "CloudBees 推出了一项新的免费服务:Jenkins Health Advisor,帮助您保持 master 节点的健康",
        "content": "管理任何软件都面临着独特的挑战。Jenkins Masters 也不例外。例如,\n 您如何掌握 Jenkins 环境中发生的所有事情?您是否正在查看问题跟踪器中打开的每个新缺陷? 您如何确保您的 master 或 agents 不会默默失效?您是否正在监控其日志?监控其所有内部组件?如果出现问题,您该如何解决? 您如何避免出现 “Angry Jenkins” 图标?  这就是我们通过 CloudBees 创建 Jenkins Health Advisor 的原因。\n在 CloudBees,我们拥有多年为使用 Jenkins 的客户提供支持的经验,其中包括基于 Jenkins 构建的专有产品,例如 CloudBees Core。因此,我们的支持团队由拥有 Jenkins 知识的自动化专家组成,您在其他任何地方都无法获得。\n当我们的工程师创建一个平台时,便会开始自动运行状况检查,以便他们可以编写规则来检测客户提供的 support bundles 中的已知问题,并将其重定向到所需的知识源以诊断和解决问题。\n经过多年的内部使用,我们决定与社区共享此服务,我们很高兴为 每个 Jenkins 用户推出一项新的免费服务:Jenkins Health Advisor by CloudBees。\nJenkins Health Advisor by CloudBees 自动分析您的 Jenkins 环境,主动识别潜在问题,并通过详细的电子邮件报告为您提供解决方案和建议。\nJenkins Health Advisor by CloudBees 可以检测到各种问题,从简单的配置问题到安全性和最佳实践问题-Jenkins 实现的所有关键要素。入门过程分为 3 个步骤,您将在 24 小时内收到第一份报告。\n我们希望您会喜欢这项服务,它将帮助您保持 masters 的健康。\n花几分钟时间阅读我们的文档,发现服务,并随时通过 Jenkins 社区渠道(Gitter、jenkinsci-users@googlegroups.com,…)与我们联系。\n也不要错过在 DevOps World|Jenkins World 2019上与我们的支持团队会面的机会。\n参考链接:\n 插件文档 Jenkins 插件网站 CloudBees Jenkins 支持  ",
        "auhtor": "Arnaud Héritier",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/11/22/jenkins-health-advisor-by-cloudbees/",
299
        "poster": "cover.jpg"
300
    },
301
    {
302
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-29-jenkins-cicd-with-git-secrets/",
303 304 305 306 307 308 309 310 311 312 313
        "title": "Jenkins CI/CD 集成 Git Secrets",
        "type": "wechat",
        "date": "2019-11-29 00:00:00 +0000 UTC",
        "tags": ["Jenkins 流水线", "Git Secrets"],
        "description": "本教程将 Git Secrets 与 Jenkins CI/CD 流水线联系起来",
        "content": " 通常,对我们在代码中使用的机密或凭据进行加密,然后将其保存在安全的地方。我们可以有很多选择来实现这一目标,例如使用 Vault 和 Git-crypt 等工具来。git-secret 是一个简单的工具,我们可以使用它在 Git 仓库中存储密钥。Git-secret 使用 gpg 加密和解密密钥。\ngit-secret 的工作方式如下。进入仓库中要加密文件的文件夹,然后,运行 git init \u0026amp;\u0026amp; git secret init。这将初始化 .gitsecret 文件夹,然后运行 git secret tell $email,如果您希望其他用户解密密钥文件,则必须导入其 gpg 公钥,然后再次运行 git secret tell $otheruseremailid。现在您可以运行 git secret add $secretfilename 和 git secret hide,这将创建名为 $secretfilename.secret 的加密的密钥文件。\n或许你会对在 Git 中存储加密的凭据感兴趣。\n现在,您可以提交 master 分支库了。git-secret 自动将 $secretfile 添加到 .gitignore,因此您只需提交 $secretfile.secret 文件。\n将 git-secret 集成到 Jenkins 中的主要挑战是 git-secret 使用 gpg 私钥和公钥。如果我们必须运行 git secret reveal,我们应该有一个 gpg 私钥。因此,我们如何在 Jenkins 上运行它,怎样使用一个从节点来拉取仓库并进行构建,如果您必须在从节点展示 git secret,则应该在从节点拥有 gpg 私钥。 我们如何在 Jenkins 流水线中实现这种加密和解密?\n这些步骤将说明在 Jenkins 流水线中使用 git-secret 的方法。\n在 Jenkins 上运行 git-secret 1.导出 gpg 私钥。\ngpg -a --export-secret-keys $keyid \u0026gt; gpg-secret.key gpg --export-ownertrust \u0026gt; gpg-ownertrust.txt  你将通过运行 gpg --list-secret-keys 获得密钥 ID。 此处的 E7CD2140FEC5B45F42860B2CC19824F8BC975ABCD 是密钥 ID。\nsec rsa4096 2019-09-17 [SC] E7CD2140FEC5B45F42860B2CC19824F8BC975ABCD uid [ultimate] Test (test gpg key) \u0026lt;test@domain.com\u0026gt;  2.将导出的 gpg 密钥和所有者信任作为 secret file 添加到 Jenkins 凭证。 下图展示了添加私钥作为 Jenkins 凭据。以相同的方式添加所有者信任文件。\n3.添加 gpg 私钥的密码短语作为 secret text。下图演示了这一点。\n4.在 Jenkins 流水线中使用添加的 gpg 私钥、所有者信任文件和密码短语。这里的 \u0026ldquo;gpg-secret\u0026rdquo;、\u0026rdquo;gpg-trust\u0026rdquo; 和 \u0026ldquo;gpg-passphrase\u0026rdquo; 是添加 Jenkins 凭据时给出的 ID。\npipeline { agent { node { label 'test_slave' } } environment { gpg_secret = credentials(\u0026quot;gpg-secret\u0026quot;) gpg_trust = credentials(\u0026quot;gpg-trust\u0026quot;) gpg_passphrase = credentials(\u0026quot;gpg-passphrase\u0026quot;) } stages { stage(\u0026quot;Import GPG Keys\u0026quot;) { steps { sh \u0026quot;\u0026quot;\u0026quot; gpg --batch --import $gpg_secret gpg --import-ownertrust $gpg_trust \u0026quot;\u0026quot;\u0026quot; } } stage(\u0026quot;Reveal Git Secrets\u0026quot;) { steps { sh \u0026quot;\u0026quot;\u0026quot; cd $WORKSPACE/$yoursecretfolder git init git-secret reveal -p '$gpg_passphrase' \u0026quot;\u0026quot;\u0026quot; } } } }  我希望本文能清楚地解释如何在 Jenkins 流水线中使用 git-secrets。\n进一步阅读 避免将安全凭据传递给 GitHub \n如何将 GitHub 仓库集成到 Jenkins 项目\n",
        "auhtor": "Aditya C S",
        "translator": "zhaoying818",
        "original": "https://dzone.com/articles/jenkins-cicd-with-git-secrets",
        "poster": "connection-netwok.jpg"
    },
314
    {
315
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-28-jcli-v0.0.23/",
316 317 318 319 320 321 322 323 324 325 326
        "title": "Jenkins CLI 命令行 v0.0.23",
        "type": "wechat",
        "date": "2019-11-28 00:00:00 +0000 UTC",
        "tags": [],
        "description": "jcli-v0.0.23 发布",
        "content": " Jenkins CLI 在参加 2019 年谁是最受欢迎的中国开源软件投票,如果您已经是 Jenkins CLI 的用户,请点击下面的链接帮忙投上一票。\nhttps://www.oschina.net/project/top_cn_2019#jenkins-cli\n如果,您还没有听说或者使用过 Jenkins CLI,欢迎阅读我们的官方文档,以及下面的 v0.0.23 版本更新内容。\nJenkins 国内镜像中心发布后,收到了很多的反馈。鉴于之前的操作步骤相对较多,本次 Jenkins CLI 给出了一键启动国内镜像源的方案: 只要执行命令:jcli center mirror 即可启动镜像源。如果希望使用原有的地址,也非常简单:jcli center mirror --enable=false\n更多有意思的玩法,请参考 Jenkins 中文社区论坛。\n🚀 功能  支持创建插件 (#255) @LinuxSuRen 支持子 shell 命令 (#253) @LinuxSuRen 支持启用(或禁用)更新中心镜像源 (#251) @LinuxSuRen 增加以键值对的形式触发参数化流水线 (#249) @LinuxSuRen 支持停止最近一次的构建任务 (#248) @LinuxSuRen 支持命令多语言的描述 (#245) @LinuxSuRen 支持选择以及移除 Jenkins 连接配置项 (#246) @LinuxSuRen 支持命令行自动补全 (#242) @LinuxSuRen 支持下载特定版本的 Jenkins war (#240) @LinuxSuRen 支持配置诊断 (#169) @yJunS 支持从镜像中心下载插件 (#222) @LinuxSuRen 支持从镜像中心下载 Jenkins war (#221) @LinuxSuRen 支持从本地或者 URL 中加载 Jenkinsfile (#220) @LinuxSuRen 支持多种方式编辑流水线 (#206) @LinuxSuRen 支持安装指定版本的插件 (#211) @sbcd90  📝 文档完善  完善 README-zh.md (#241) @donhui  👻 维护  增加关于分支策略的检查清单 (#227) @LinuxSuRen 升级 go.uber.org/zap 从 1.12.0 到 1.13.0 (#237) @dependabot-preview 升级 gopkg.in/yaml.v2 从 2.2.4 到 2.2.5 (#225) @dependabot-preview 升级 github.com/onsi/ginkgo 从 1.10.2 到 1.10.3 (#218) @dependabot-preview 升级 github.com/onsi/gomega 从 1.7.0 到 1.7.1 (#217) @dependabot-preview  🚦 测试  增加流水线参数命令的单元测试 (#232) @LinuxSuRen 增加插件检查的单元测试 (#224) @LinuxSuRen 增加任务历史命令的单元测试 (#228) @LinuxSuRen  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "jenkins-cli.png"
    },
327
    {
328
        "uri": "https://jenkins-zh.cn/meeting/2019-11-27/",
329 330 331 332 333 334 335 336 337 338 339
        "title": "",
        "type": "meeting",
        "date": "2019-11-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 论坛\n 邮箱没有配置好 更换域名(https://discourse.jenkins-zh.cn/t/topic/86/7)@yJunS 给管理更多的管理权限 把阿里云域名的权限给到管理员@linuxsuren 管理员招募 https://discourse.jenkins-zh.cn/t/topic/103  介绍 Jenkins 容器发行版\n https://github.com/LinuxSuRen/docker-zh Jenkins 发行版的定制  jenkins+2.190.3+localization-zh-cn+++ http://custom.jenkins-zh.cn?version=2.190.3\u0026amp;plugin=localization-zh-cn    ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
340 341 342 343
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-22-plugin-docs-on-github/",
        "title": "Jenkins 插件文档即代码:将文档迁移到 GitHub",
        "type": "wechat",
344 345 346 347 348 349 350 351 352
        "date": "2019-11-22 00:00:00 +0000 UTC",
        "tags": ["hacktoberfest", "developer", "documentation", "wiki", "contributors"],
        "description": "Jenkins 插件开发者,将你的插件文档迁移到 GitHub 吧!",
        "content": " 在2019年9月,我们宣布了对 GitHub 作为 Jenkins 插件站点文档来源的支持。 感谢 Zbynek Konecny 和 Olivier Vernin 以及其他贡献者, 现在可以将插件文档直接存储在插件储存库中,而不是 Jenkins Wiki 中,对于插件维护者和 Jenkins 基础设施团队来说,这在过去是很难维护的。\n这篇博文可能对插件维护者和那些想为 Jenkins 文档做贡献的人来说很有趣。 我将描述如何将插件文档迁移到 GitHub 并获得如下页面:\n为什么? 通过使用插件的 GitHub 仓库存储文档, 插件维护者可以遵循 文档即代码 的方法,将文档更改作为 pull request 的一部分,这样就不会忘记文档的后续工作。 它还提供了一个 review 文档更改以及增加文档贡献者的认可度的机会,尤其是如果 story 与 Release Drafter 结合。\n不幸的是,在2019年9月之前,GitHub 文档的使用引起了一些问题。 首先,许多插件维护者已经将他们的文档迁移到 GitHub,这导致了文档的碎片化(Wiki、GitHub、jenkins.io)。 为了解决这个问题,插件维护者仍然需要使用重定向来维护存根 Wiki 页面, 用户不得不花一些时间来找出真正的文档在哪里。 通过支持 GitHub 作为文档来源,我们允许维护者逐步淘汰插件 Wiki 页面,同时改善用户体验。\n现在进行迁移还有更紧迫的原因…… 如果你订阅了开发者邮件列表, 你可能还看到了 R. Tyler Croy 关于 Jenkins Wiki 稳定性问题的声明, 并将其设置为只读,作为稳定实例的临时措施邮件列表主题。 虽然功能后来部分恢复了, 基础架构团队一致认为,我们应该逐渐转向替代解决方案。\n例子 自从9月份宣布以来,超过50个插件已经从 Wiki 迁移到 GitHub。 几个例子:\n 配置即代码插件 Mailer 插件 Gradle 插件 角色策略插件  如何为你的插件启用 GitHub 文档?  将文档从 Wiki 转换到 GitHub Asciidoc 或 Markdown 格式,如果你还没有做。  它可以用半自动的方式完成,请看这里的指南。  更改 pom.xml 中的 \u0026lt;url\u0026gt; 字段,使其指向 GitHub(指南)。 有效链接的例子:  https://github.com/jenkinsci/mailer-plugin - 插件站点将使用 GitHub REST API 来提取 README https://github.com/jenkinsci/ssh-credentials-plugin/blob/master/doc/README.md - 从自定义位置提取插件页面  可选:添加徽章到页面,以改善外观和感觉,并为用户提供快速链接。 变更日志、聊天室、插件站点和安装量都有标准的徽章。  Markdown 例子 Asciidoc 例子  发布新的插件版本 等待几个小时,直到更改传播。 之后,Jenkins 插件站点将会展示来自 GitHub 的新文档。  下一步? 这个 story 被跟踪为 WEBSITE-406,它是使用 GitHub 作为 Jenkins 插件站点和更新管理器(WEBSITE-637)数据源的更广泛子项目的一部分。 后面的步骤包括支持显示来自 GitHub release 的变更日志,从 GitHub 中提取插件标签,显示插件 logo, 以及使用 Repository Permission Updater 作为维护者信息的来源。\n如何贡献? 10月是一个贡献的好机会! 插件文档是 Hacktoberfest 活动中的一个特色项目, 我们欢迎所有对文档和代码库的贡献。\n为文档做贡献 我们正在寻找有兴趣改进插件文档并帮助我们从 Wiki 迁移到 GitHub 的贡献者。 对于几十个插件来说,文档已经在 GitHub 中,欢迎你针对任何仓库提交 pull request。\n迁移文档:\n 迁移插件文档从 Wiki 到 GitHub 迁移文档从 Jenkins Wiki 到 jenkins.io 用于插件文档迁移的 issue 模板 [新手友好的文档任务]()  如果你有任何关于贡献文档的问题, 请查看这个页面或者在 Docs SIG Gitter 聊天室联系我们。\n贡献代码 您想用 Java 或 JavaScript 编写一些代码吗? 或者你愿意致力于 CSS 样式并改进 Jenkins 的设计吗? 在这种情况下,欢迎向 Jenkins 插件站点做贡献。 这是我们自己的插件市场实现,我们邀请对这个领域的贡献。 这个插件站点很容易开发。\n WEBSITE-637 - 用于插件站点以及 GitHub 集成的 Epic jenkins-infra/plugin-site - 前端 (JavaScript、React、XSS、YARN) jenkins-infra/plugin-site-api - 插件站点 API 和 Docker 包(Java、Maven、Docker)  有用的链接  插件文档 Jenkins 插件站点  ",
        "auhtor": "oleg_nenashev",
        "translator": "donhui",
        "original": "",
        "poster": "jenkins-plugin-docs-to-github.png"
    },
353
    {
354
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-20-jenkins-cli-help-you-manage-jenkins/",
355 356 357 358 359 360 361 362 363 364 365
        "title": "Jenkins CLI,助你轻松管理 Jenkins",
        "type": "wechat",
        "date": "2019-11-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "无论你是插件开发者,还是管理员或者只是一个普通的 Jenkins 用户,Jenkins CLI 都是为你而生!",
        "content": " Jenkins CLI,简称 jcli,一个使用 Golang 开发的开源的 Jenkins 命令行工具。 它可以帮忙你轻松地管理 Jenkins。 无论你是 Jenkins 插件开发者,还是 Jenkins 管理员或者只是一个普通的 Jenkins 用户,它都是为你而生!\nJenkins CLI 功能简介 从2019年6月份第一个 git commit 算起,经过不断迭代,截止目前 Jenkins CLI 已经对外发布了18个版本,下载量超过2000,功能也日益增多。 目前主要功能列表如下所示: * 支持多 Jenkins 实例管理 * 插件管理(查看列表、搜索、安装、上传) * 任务管理(搜索、构建触发、日志查看) * 在浏览器中打开你的 Jenkins * 重启你的 Jenkins * 支持通过代理连接\n此外,优秀的开源项目应该有着高代码质量。Jenkins CLI 始终坚持内建质量的原则,在开发过程中持续编写单元测试代码,并使用 TravisCI + SonarCloud 对代码质量持续分析,从而保证代码质量。 目前测试覆盖率为81.8%,下一个目标是将测试覆盖率提升到90%。 Go Report Card 给 Jenkins CLI 的代码质量评分为 A+。\n如何安装 Jenkins CLI? Jenkins CLI 目前支持的操作系统有:MacOS、Linux 以及 Windows。\n在 Mac 上安装 在 Mac 上可以通过 brew 来安装 jcli:\nbrew tap jenkins-zh/jcli brew install jcli  在 Linux 上安装 要在 Linux 操作系统上安装 jcli 的话,非常简单。 只需要执行下面的命令即可:\ncurl -L https://github.com/jenkins-zh/jenkins-cli/releases/latest/download/jcli-linux-amd64.tar.gz|tar xzv sudo mv jcli /usr/local/bin/  在 Windows 上安装 你只要点击这里就可以下载到最新版本的压缩包。然后,把解压后的文件 jcli 拷贝到你的系统目录下即可。\n其他包管理器 还可以使用一些其他的包管理器安装 jcli: * GoFish 的用户可以使用命令 gofish install jcli 来安装 * Scoop 的用户可以使用命令 scoop install jcli 来安装\nGoFish 同时支持 Linux 和 Windows,Scoop 支持 Windows。\n使用入门 安装 jcli 后,你需要提供一份配置文件。请执行命令 jcli config generate,该命令会帮助你编辑配置文件 ~/.jenkins-cli.yaml,你需要根据实际的 Jenkins 配置情况做相应的修改。\n配置文件准备好后,便可以进行一些实际操作了。 下面举几个插件管理和任务管理的例子作为说明。\n插件管理 使用 jcli 搜索插件:\njcli plugin search zh-cn  使用 jcli 下载插件,如果该插件有相关依赖插件的话,会同时下载依赖插件:\njcli plugin downlaod localization-zh-cn  使用 jcli 安装插件:\njcli plugin install localization-zh-cn  任务管理 使用 jcli 触发构建:\njcli job build pipeline-01  使用 jcli 查看构建日志,如果任务正在运行,它会实时监听日志输出,否则输出最近一次构建日志:\njcli job log pipeline-01  更多命令请查看帮助 限于篇幅原因,更多使用说明不做一一介绍,请查看帮助命令:\njcli --help jcli \u0026lt;command\u0026gt; --help jcli \u0026lt;command\u0026gt; \u0026lt;subcommand\u0026gt; --help  也可以查看官方文档: - https://github.com/jenkins-zh/jenkins-cli/blob/master/doc/README.md - https://jenkins-zh.github.io/jcli-docs/\n如果你有意愿使用 Jenkins CLI,那么赶快动手来体验吧!\n新功能路线图 Jenkins CLI 仍旧在不断发展中。 挑选了几个计划中的新功能,列表如下: - 支持自我升级 - 支持列出所有 agent 节点 - 支持更新所有插件 - 支持展示插件趋势\n如果你有希望开发的新功能,请提交 issue 到 GitHub 仓库。\n欢迎反馈与贡献 如果你在使用过程中遇到问题,欢迎在 GitHub 仓库提交 issue 来反馈; 同时,我们也非常欢迎贡献者对 Jenkins CLI 贡献自己的一份力量。 目前除了国内的主要贡献者: - LinuxSuRen - yJunS\n还有来自其他国家或地区的贡献者为 Jenkins CLI 做出过贡献,他们是: - zirmax - scottydocs - sbcd90 - oleg-nenashev\n无论是小到一个错别字的修改,大到一个新的功能的开发,或者是在使用过程中提交 issue 反馈,它们对 Jenkins CLI 发展而言都有着重要的意义。\nJenkins CLI 期待你的投票 2019 年的中国开源界,开源项目的数量也在激增。 作为中国开源界的一份子,此时此刻,Jenkins CLI 正在参加由 OSCHINA(开源中国)主办的2019年度最受欢迎中国开源软件评选活动。\n恳请占用你的一点宝贵时间,麻烦动动手指为 Jenkins CLI 投上支持的一票,不胜感激!\n投票方式:长按图片,识别图中二维码,打开投票活动页面,找到开发工具类--\u0026gt;Jenkins CLI,点击投票,再次感谢支持 Jenkins CLI !\n",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "jenkins-cli.png"
    },
366
    {
367
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-18-integration-of-c-stat-code-analysis-with-automated-jenkins-ci-build/",
368 369 370 371 372 373 374 375 376 377 378
        "title": "Jenkins CI 自动构建与 C-STAT 代码分析的集成",
        "type": "wechat",
        "date": "2019-11-18 00:00:00 +0000 UTC",
        "tags": ["C-STAT", "Jenkins CI"],
        "description": "了解如何通过与 Jenkins 集成来进一步进行静态代码分析,并且提供清晰的分析结果和生产静态的 HTML 报告。",
        "content": " 介绍 我们大多数人都知道,为嵌入式软件设置 CI/CD 总是有局限性或挑战性的,并且我们还看到在某些情况下仍然没有其他可用的选择,这会导致工作量加大和代码质量缺失。\n在本文中,我们将看到一个这样的嵌入式开发工具(IAR 嵌入式工作台),以及如何将 C-STAT 静态代码分析与持续集成版本 Jenkins 集成在一起,以及如何通过自动构建。\n先决条件: a. IAR 嵌入式工作台 IDE b. C-STAT 许可证 c. Jenkins 安装\nIAR 嵌入式工作台工具为我们提供了命令行执行选项,以实现 IAR 项目的静态代码分析。现在,我们将了解其工作原理。\nIAR 命令行应用程序 IAR 系统为我们提供了一个名为 IarBuild.exe 的应用程序,该应用程序用于在命令行中执行分析。您可以在安装路径中找到 IarBuild.exe 应用程序,如下所示。\nC:\\Program Files (x86) \\IAR Systems\\Embedded Workbench 8.1\\common\\bin\\  运行代码分析: 首先切换到命令路径中的上述路径,然后执行以下命令来分析整个项目。\nIarBuild.exe D:\\sample\\project\\setup\\sample.ewp -cstat_analyze Debug   D:\\sample\\project\\setup\\sample.ewp 是您的 IAR 项目文件路径 -cstat_analyze 是要执行分析的命令 设置项目模式为 Debug  通过执行上述命令,它将对整个项目执行静态代码分析,并且结果将存储在 cproject.db 文件中,位于路径 ...project\\setup\\Debug\\Obj\\ 下。\n注意下次运行代码分析时,如果自上次分析以来对源代码文件进行了任何更改,则必须首先清除数据库,以避免由于数据库文件中的新旧数据混合而引起的问题。\n清晰的分析结果 要使用命令行清除数据库文件,请执行以下命令,\nIarBuild.exe D:\\sample\\project\\setup\\sample.ewp -cstat_clean Debug  生成报告 要生成报告,我们可以使用 IAR 提供的 IREPORT 工具,您可以在同一安装目录中找到该工具。IREPORT 工具用于生成 C-STAT 执行的先前代码分析的 HTML 报告。\n该报告以数字和表格形式展示统计数据。可以生成两种不同类型的报告:\n 具有相关信息的大纲,例如有关在项目范围内启用的检查、消息总数、已取消的检查(如果有)、每个检查的消息等信息。 完整的报告,其中包含诸如轮廓之类的常量信息,以及在报告结束时有关所有已抑制和未抑制消息的其他信息。表格可以折叠和展开,列可以排序  要生成完整的 HTML 报告,我们可以执行以下命令,\nireport.exe --db D:\\sample\\project\\setup\\Debug\\Obj\\cstat.db --project D:\\sample\\project \\setup\\sample.ewp --full --output D:\\sample\\result.html  上面的命令包含四个参数:\n--db 指定报告所基于的数据库文件的路径。 --project 指定项目文件。 --full 生成完整报告,其中包含有关禁止检查和非禁止检查的信息。 --output 指定输出结果文件的名称。\n将 C-STAT 与 Jenkins CI 构建集成: 没有直接的插件或方法可用于将此 CSTAT 集成到任何 CI 工具。但是我们可以通过以下方法实现自定义集成。\n现在我们知道了用于分析、清理、生成报告文件的命令。使用这些命令,我们可以轻松地编写批处理脚本文件 (.bat) 文件,然后在 Jenkins 中调用此批处理文件,作为预构建命令执行步骤。\n设置阈值网关 我们将遇到需要通过设置“低”、“中”、和“高”问题的阈值在 CI 构建中定义网关的场景。如果该值大于设定值,则可以使构建失败。\n默认情况下,C-STAT 不向我们提供设置此值的选项。但是我们可以使用以下自定义脚本来实现此目的。\n我们可以获得包含低、中、高问题计数分析结果的 HTML 报告。这些值以格式 data: [0-9, 0-9 ,0-9] 在 HTML 结果文件中展现。\n请参阅下面的脚本,了解我是如何在一个变量中获取这些值,然后用 sea t 阈值进行验证。\nJenkins 构建结果 下面是 Jenkins CI 构建日志,供您参考。您可以看到由于标识为“中优先级”的 19 个问题而导致构建失败。\n结论 经过上面的分析,我们已经了解了如何使用 Jenkins CI 构建自动化 C-STAT 分析,以及如何设置阈值网关来确定构建状态。我希望此博客对那些使用 IAR 嵌入式工作台并希望使用您的 CI 构建系统自动执行 C-STAT 的人有所帮助。\n",
        "auhtor": "Sankara M",
        "translator": "wenjunzhangp",
        "original": "https://dzone.com/articles/integration-of-c-stat-code-analysis-with-automated",
        "poster": "cover.jpg"
    },
379
    {
380
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-15-using-jenkins-x-updatebot/",
381 382 383 384 385 386 387 388 389 390 391
        "title": "了解如何使用 Jenkins-X UpdateBot",
        "type": "wechat",
        "date": "2019-11-15 00:00:00 +0000 UTC",
        "tags": ["Jenkins-X", "UpdateBot"],
        "description": "了解如何使用 Jenkins-X UpdateBot 自动执行对依赖版本的更新。",
        "content": " Jenkins-X UpdateBot 是用于在项目源代码中自动更新依赖项版本的工具。假设您正在构建两个项目 A 和 B,B 使用 A 作为依赖项。A 的发布过程可以使用 UpdateBot 更新项目 B 的源,以使用 A 的新版本。在 pull request 中使用 UpdateBot,可以测试和检查更改或自动合并更改。\n在 Jenkins-X platform 中,UpdateBot 由 Jenkinsfile 中的 UpdateBot 命令自动显示和调用。但是 UpdateBot 也可以在 Jenkins-X 之外使用,并且单独运行它可以帮助了解它可以做什么并测试版本替换。因此,让我们用一个简单的测试项目来尝试一下。\n配置演示 UpdateBot 可以为各种不同的文件类型设置版本-我们不会在这里对它们进行全部测试,但是我们希望一个项目具有多个功能。因此,我们可以使用 JHipster sample app 示例应用程序,因为它具有 Maven pom.xml,npm package.json 和 Dockerfile。我们将对其运行 UpdateBot,以查看 UpdateBot 可以替换这些资源文件中哪些内容。\n我们可以下载 UpdateBot jar file(v1.1.31),并为要更新的项目设置指向 GitHub 存储库的简单 UpdateBot 配置文件:\ngithub: organisations: - name: ryandawsonuk repositories: - name: jhipster-sample-app useSinglePullRequest: true  useSinglePullRequest 标记意味着将创建一个包含我们所做的所有更改的 PR。但是我们实际上并不会进行任何更改-我们将在本地运行它,这样我们就不需要 GitHub 对存储库的写权限。通过设置环境变量,我们可以在不推送到 GitHub 的情况下运行:\nexport UPDATEBOT_DRY_RUN=true  然后,我们仍然需要使用 UPDATEBOT_GITHUB_USER 和 UPDATEBOT_GITHUB_PASSWORD(Token)的其他环境变量设置 git 凭据。\n然后,我们可以运行一些 UpdateBot 命令,并查看从 Git 克隆的项目中替换了什么。为此,我们可以在 GitHub 上使用一个包含预配置脚本的演示项目。\n运行演示 首先,脚本更新了 maven pom.xml,要求更改 Spring Boot 版本:\njava -jar updatebot-1.1.31.jar push-version --kind maven org.springframework.boot:spring-boot-starter-data-jpa 2.1.0.RELEASE  然后检查更改并输出 git diff,我们可以看到以下结果: 因此版本被替换了。请注意,在依赖项引用的属性中将其替换,在这种情况下,pom.xml 在属性中具有此版本。UpdateBot 还可以用于直接在依赖项或父项或插件中进行的更改。\n对 package.json 的更改是将 ngx-cookie 版本更改为 2.0.2:\njava -jar updatebot-1.1.31.jar push-version --kind npm ngx-cookie 2.0.2  这正是我们所期望的: 对 Dockerfile 的更改是将 openjdk 版本/标签更改为 jdk8:\njava -jar updatebot-1.1.31.jar push-version --kind docker openjdk 8-jdk  这表明我们可以抓取出来。Dockerfile 实际上使用两个不同的 openjdk 镜像,每个镜像都有一个不同的标签,并且此命令将替换这两个镜像: 我在运行命令之前没有考虑过这一点,因此在这里我需要确定我真正要替换的内容。\n实际运行 如果我们在没有 dry-run 标记的情况下运行,则将创建一个真实的 pull request,前提是我们有权创建它。\nUpdateBot 具有自动合并 pull request 的功能,例如通过轮询 GitHub 来检查 PR 状态并合并是否一切正常(命令为updatebot update-loop)。但是,GitHub 确实对这些请求进行了速率限制,因此 UpdateBot 也可以将其批准添加到 PR 中,以使其通过与 GitHub 直接集成的工具进行合并。当使用诸如 prow 或 mergify 之类的工具进行自动合并时,这可能会很好地工作。\nUpdateBot 可以尝试仅通过使用 updatebot push 而不是带有显式参数的 updatebot push-version 来推断要作为提交触发管道的一部分进行的更改。但是,通常管道作业将有权访问要推送的版本,而 push version 使更改更明确且更易于跟踪。\n本示例使用单个 UpdateBot YAML 文件将一组依赖项/版本推送到一个下游项目。YAML 文件还支持将一组更改推送到多个下游存储库。UpdateBot 推送其能够进行的所有替换,以便每个下游存储库都获得适用于它的所有更改。\n例如,在构建没有快照的 Maven 项目时,UpdateBot 可用于在 CI/CD 设置中传播版本。但是,正如我们已经看到的那样,它不仅限于 Maven,而且可以对产生各种不同类型制品的项目进行一系列更改。\n",
        "auhtor": "Ryan Dawson",
        "translator": "wenjunzhangp",
        "original": "https://dzone.com/articles/using-jenkins-x-updatebot",
        "poster": "cover.jpg"
    },
392
    {
393
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-14-gsoc-phase-1-updates-on-working-hours-plugin/",
394 395 396 397 398
        "title": "Working Hours 插件的第一阶段更新",
        "type": "wechat",
        "date": "2019-11-14 00:00:00 +0000 UTC",
        "tags": ["react plugins gsoc gsoc2019"],
        "description": "实现了 Working Hours Plugin 和 React 集成,提供更加好用的排除日期和时间范围选择器",
399
        "content": " Working Hour Plugin 提供了一个界面,用于设置允许的构建日期和时间。在配置 Working Hour 之外运行的作业将保留到下一个允许的构建时间为止。\n在 Google Summer of Code 的第一个代码阶段,我一直在从事 Working Hours Project 项目,该项目还有待于改善可用性。\n当我们想设计一个具有大量可以使用自定义库的 UI 时,React 似乎比经典的 Jelly 页面更受青睐,尤其是日期选择器之类的开源组件。\n但是,我们目前正致力于将 React 和 Jenkins 集成在一起,这是一个挑战。\n第一阶段的成就 在第一个代码阶段,我们专注于 UI 改进,我们取得了以下主要改进: * 一个独立的 Web 应用程序,可以将其集成。 * 滑块,用于选择时间范围。 * 设置排除日期时间的更多字段。 * 用于选择排除日期的预设。 * Jenkins 样式界面\n我们如何将 React 集成到 Jenkins 中 可以在这里找到集成的解决方案文档\n最初,我们发现 BlueOcean 是在 Jenkins 中使用 React 的一个很好的例子,但是对于使用插件进行通用开发来说,它并不是一个好的选择。因此,我们需要找到另一种集成方式。\n这是进行集成的步骤: * 在你 jelly 文件中的挂载点,通常是具有唯一 ID 的元素。 * 编写您的 React Application,但需要将安装点设置为您在上面设置的 ID。 * 将构建后的插件复制到 webapp 目录。 * 在你的 jelly 文件中,使用 script 标签引入\n\u0026lt;script type=\u0026quot;text/javascript\u0026quot; src=\u0026quot;${resURL}/plugin/working-hours/js/main.js\u0026quot;\u0026gt;\u0026lt;/script\u0026gt;   使用 React 之后,传统的请求将不再可用,处理请求的另一种方法是使用 stapler。您可以定义如下的过程函数[source, java]  public HttpResponse doDynamic(StaplerRequest request) { if (config == null) { config = ExtensionList.lookup(WorkingHoursPlugin.class).get(0); } String restOfPath = request.getRestOfPath(); String[] pathTokens = restOfPath.split(\u0026quot;/\u0026quot;); List\u0026lt;String\u0026gt; params = new ArrayList\u0026lt;\u0026gt;(); switch (params.get(0)) { case \u0026quot;list-excluded-dates\u0026quot;: return listExcludedDate(request); case \u0026quot;set-excluded-dates\u0026quot;: return setExcludedDates(request); case \u0026quot;list-time-ranges\u0026quot;: return listTimeRanges(request); case \u0026quot;set-time-ranges\u0026quot;: return setTimeRanges(request); } }   运行我们的应用程序 如果您想看一下我们的插件,可以查看 working-hours-plugin 的仓库。 只需阅读 README 文件,即可运行 working-hours-plugin 的副本。\n截图 当前的插件外观有点简单,插件使用起来有些不便。 比如说如果我们要输入排除的日期,它将是一个恒定格式的字符串,例如 15/9/2019,但是新的用户界面选择了 React,因此我们可以使用日期选择器进行改进。\n当前插件 新版时间范围选择器 新版排除日期 帮助链接 如果您有任何疑问或建议,我们很高兴收到您的来信。 下面列出了几个有用的链接: * Develop Repo * Main Repo * Design Doc * Doc for React Integration Solution * Gitter Chat * Slides for Phase 1 Demo * Video Recording for Phase 1\n",
400 401 402 403 404
        "auhtor": "Jack Shen",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/07/09/Phase1-Updates-On-Working-Hours-Plugin/",
        "poster": "cover.jpg"
    },
405
    {
406
        "uri": "https://jenkins-zh.cn/meeting/2019-11-13/",
407 408 409 410 411 412 413 414 415 416 417
        "title": "",
        "type": "meeting",
        "date": "2019-11-13 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 论坛\n 管理员招募? 如何管理 国内实名验证的问题(如何保证每个人都有手机号信息)  Jenkins 相关资源下载很慢,包括:容器镜像、deb 镜像源、插件等\n https://github.com/jenkins-zh/mirror-adapter   ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
418
    {
419
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-13-a-thanks-letter/",
420 421 422 423 424
        "title": "致霍格沃兹测试学院的一封感谢信",
        "type": "wechat",
        "date": "2019-11-13 00:00:00 +0000 UTC",
        "tags": [],
        "description": "社区大于代码,不满意就提 PR",
425
        "content": "Jenkins 虽然有着无数潜在的用户群体,但是,在国内直接参与社区的人却寥寥无几,甚至, 都没有一个集中沟通交流的场所。这是非常令人困惑不解的一点,毕竟 Jenkins 已经诞生15年之久, 这比许多人的职业生涯都要长。\n为了改善 Jenkins 在国内的使用体验,给大家一个可以集中讨论相关问的场所,Jenkins 中文社区 在一年前成立了。我们从一开始的双周例会(公开讨论社区发展相关的话题),增加了单周技术交流会 (分享交流持续交付相关的经验)。创建了一个零广告、零闲聊的技术交流微信群,目前有410+成员(有愿意 担任群2管理员的,可以与我们取得联系)。这都要感谢新老志愿者的无私贡献,不管是技术文章的翻译, 还是 issue、PR 或者代码、文档,甚至只是一个小小的建议,社区正因为有你们的存在而变得更好。 为了表示对他们的感谢和鼓励,给予贡献者一些小小的激励, 包括:图书、大会免费门票等等。这要感谢人民邮电出版社等对我们长期的大力支持。\n我们今天尤其想要表示感谢的是——下面给予 Jenkins 中文社区现金10000元捐赠的企业。\n霍格沃兹测试学院是中国领先的测试开发技术在线教育机构, 由知名测试社区 TesterHome 与测吧(北京)科技有限公司合作创办,专注于高级测试人才的培养。\n对我们而言,并没有业内专家的驻场,背后也没有大厂的光环,全部是草根个人在努力奉献自己的力量。但是,我们深深地 理解开源的意义所在,开源并不是走秀,并不是只有大佬可以玩。任何一个不只是流于口舌的同学都是社区里的主人, 不满意就提 PR,这就是开源社区所需要的人才。社区大于代码,开源不只是把代码扔到 GitHub 上就可以了。我相信, 霍格沃兹测试学院也正是出于 Jenkins 中文社区下面的行为准则才愿意支持我们的:\n 治理开源  公开例会 公开会议记录(文字、视频) 公开奖励 公开支出  活动开源  公开讨论如何组织活动  代码开源  https://github.com/jenkins-zh  文档开源  设计文档 教程   我们会把得到捐赠的资金用于社区基础设施的建设,带给更多关注 Jenkins、关注 DevOps、关注开源的同学们。资金去向请访问下面的地址:\nhttps://jenkins-zh.cn/about/sponsors-list/\n最后,我们由衷地希望霍格沃兹测试学院和开源事业发展的越来越好,得到更多人和组织的关注和支持。\n",
426 427 428 429 430
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "open-source.png"
    },
431
    {
432
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-12-2019-jenkins-board-and-officer-elections-update/",
433 434 435 436 437 438 439 440 441 442 443
        "title": "Jenkins 2019 年 Board 和 Officer positions 选举更新",
        "type": "wechat",
        "date": "2019-11-12 00:00:00 +0000 UTC",
        "tags": ["community", "governance", "elections"],
        "description": "Jenkins 社区正在进行 2019 年 Board 和 Officer positions 的选举活动,我们诚恳的邀请您参加并且投出您宝贵的一票。",
        "content": " Jenkins 社区正在进行 2019 年 Board 和 Officer positions 的选举。提名征集已经结束。我们征集到了很多提名。根据愿意接受提名的人和无可争议的 Officer Positions,我们将有 3 票:\n 投票选举 3 名board members 投票选举 Jenkins security officer 投票选举 Jenkins events officer  候选人 每位候选人都提供了一份声明,以帮助指导选民为什么要为候选人投票。有关更多详细信息,请参阅候选人宣言。竞选 board members 的候选人为:\n Alex Earl Oliver Gondza Ullrich Hafner Oleg Nenashev Mark Waite 赵晓杰(Rick)  竞选 security officer 的候选人是:\n Daniel Beck Wadeck Follonier  竞选 events officer 的候选人是:\n Alyssa Tong 赵晓杰(Rick)  选民登记 这是近一段时间以来我们第一次进行 Jenkins 选举。我们正在学习。Jenkins 选举旨在实现包容性。我们不仅将选举限于代码提交者。在 2019 年 9 月 1 日之前注册了 Jenkins 帐户的任何人都有资格投票。Jenkins 是一个成功的项目,大约有 10 万个符合该标准的帐户。我们正在与符合条件的选民联系,并要求他们明确 选择性加入 以参加投票。\n如果符合条件,您将在注册的 jenkins.io 电子邮件地址中收到一封电子邮件。该邮件来自 elections@jenkins.io,标题为 2019 Jenkins Election - Invitation to Participate。该电子邮件将提供选举详细信息,并包含一个 I want to participate 按钮。\n投票确认 点击链接后,您将看到一个确认屏幕,如下所示:\n如果您在 2019 年 11 月 14 日之前仍未收到电子邮件,或者在投票时遇到任何问题,请对 Jenkins Election 2019 Jira issue 问题发表评论。\n表决 投票将于 2019 年 11 月 11 日正式开始。候选人将收到 Kohsuke Kawaguchi 发送的 Condorcet 互联网投票电子邮件。每次投票将发送一封电子邮件(因此,总共 3 票:board 1 票,events officer 1 票,security officer 1 票)。投票将要求使用以下截图对候选人进行排名:\n选举日期 以下是关键选举日期的摘要:\n   Date Event     Now Voter registration ongoing   Nov 11, 2019 Voting begins   Nov 17, 2019 Voter registration closes   Nov 24, 2019 Voting closes a 5:00 PM Pacific Time   Dec 3, 2019 New representatives announced    选举结果将发布到 Jenkins 开发人员的邮件列表中,然后在 jenkins.io 上发布公告博客。\n如果对建议的日期有任何延迟,我们将尽快通知您。非常感谢所有向我们的社区展示 Jenkins 服务精神的候选人。我们鼓励所有人注册投票并参与 Jenkins 社区。\n无可争议的职位 当一个 officer position 只有一个愿意接受提名的候选人时,没有理由对该职位进行投票。该人将成为该职位的唯一候选人。\n毫无争议的 Officer Positions 包括:\n   Name Role     Olivier Vernin Infrastructure Officer   Oliver Gondza Release Officer   Mark Waite Documentation Officer    参考文献  Jenkins Governance Board Jenkins Board Election Process Jenkins Officers Announcement in the developer mailing list 2019 elections proposal in the developer mailing list  ",
        "auhtor": "Tracy Miranda",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/11/08/board-elections/",
        "poster": "cover.png"
    },
444
    {
445
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-11-update-center-mirror-announcement/",
446 447 448 449 450
        "title": "Jenkins 插件中心国内镜像源发布",
        "type": "wechat",
        "date": "2019-11-11 00:00:00 +0000 UTC",
        "tags": [],
        "description": "忍受不了官方站点下载速度的速速看过来",
451
        "content": "Jenkins 社区的网络基础设施都是架设在国外的服务器上,而且,并没有在国内有 CDN 或者负载均衡的配置。 对所有的 Jenkins 用户而言,1500+的插件可以帮助他们解决很多问题。然而,我相信,对于国内的很多用户来说, 可能有过一些不太愉快的经历——插件下载速度很慢,甚至会超时。难道遇到这种情况下,我们就只能等吗?\n程序员,作为天生懒惰的人,总是希望能通过手中的键盘来解决各种各样的问题。凭什么?下载一个插件, 我还的苦苦地等待来自美国的数据包呢?数数你手里的 Jenkins 都安装了多少个插件。30个算少的吧。 经过一番搜索,发现果然已经有前人帮忙把大树种好了。让我们一起感谢“清华大学开源软件镜像站”提供的镜像服务:\nhttps://mirrors.tuna.tsinghua.edu.cn/jenkins/\n但是,当我兴冲冲地把 Jenkins 插件管理页面的更新中心的地址修改后,却发现了一个奇怪的情况,好像还是那么慢啊。 不管是换地址,还是换4G,换电脑都解决不了这个网络排队的问题。本着开源的精神(不满意就提 issue 或者 Pull Request), 我只好继续挖掘这里的秘密。下面,是我向 TUNA 提的一个 issue(可以看到貌似我并不是第一个吐槽的人):\nhttps://github.com/tuna/issues/issues/659\n是的,rsync 可以帮我们把106G的文件同步过来,免去了出国下载插件的麻烦,可没有解决最后一公里的痛。\n通过下面的 PR 我们可以大致了解到,Jenkins 是通过解析 update-center.json 文件的方式来获取插件版本, 以及下载插件的。另外,如果你认为只是修改下文件里的 URL 就能解决这个问题的话,那么,请再仔细想一下这个事情。 既然小白兔可以把地址修改为一个比较方便的值,那么,大灰狼为啥不能往那些插件里加点辣椒水呢。 Jenkins 作为一个在 CI/CD 领域里领先了15年之久的大叔,当然不会输给了一些小毛贼。简单来说呢,这个事情 是通过两把钥匙来解决的——官方用其中一把钥匙给文件做了签名,并保管起来;把另外一把钥匙对外公布(保存在发行版中)。 只有通过了公钥验证的 update-center.json 文件,才会被使用到。\nhttps://github.com/jenkins-infra/update-center2/pull/245\n知道了问题所在,解决起来自然就容易了。Jenkins 中文社区帮大家把钥匙和地址的问题解决了,按图索骥三步走:\n想了解技术细节?担心我们是大灰狼?我们欢迎喜欢学习的同学,更欢迎人民大众的检阅。 提问题,提需求,提代码,提文档,都是可以的。实际上,我们的整套方案中,所有的部分(除了拿一把钥匙以外) 都是开源的,包括还不够完善的设计文档。而且,并不需要花一分钱,完全利用现有的计算、存储资源。 此处,让我们再次感谢清华开源镜像站点、GitHub Actions、码云 Page 等。\nhttps://github.com/jenkins-zh/mirror-adapter\n最重要的事情,一定要在最后才说出来(不喜欢认真阅读文档的同学,对不起了)。想要体验极速 安装插件的同学,请认准 Jenkins 简体中文插件的版本:1.0.10\nhttps://plugins.jenkins.io/localization-zh-cn\n",
452 453 454 455 456
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "flash.jpg"
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
457
    {
458
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-08-remoting-over-apache-kafka-plugin-with-kafka-launcher-in-kubernetes/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
459 460 461 462 463
        "title": "在 Kubernetes 中通过 Apache Kafka 插件远程处理 Kafka 启动程序",
        "type": "wechat",
        "date": "2019-11-08 00:00:00 +0000 UTC",
        "tags": ["kafka kubernetes helm"],
        "description": "在 Kubernetes 中通过 Apache Kafka 插件远程处理 Kafka 启动程序",
464
        "content": " 我是越南 FPT 大学的 Long Nguyen ,我的 Google Summer of Code 2019 项目是 Remoting over Apache Kafka with Kubernetes features 。这是我第一次为 Jenkins 做贡献,我非常兴奋地宣布在第一阶段已经完成的功能。\n项目介绍 当前版本的 Remoting over Apache Kafka plugin 远程处理需要用户手动配置整个系统,包括 zookeeper 、 kafka 和远程处理代理。它也不支持动态代理配置,因此很难实现具有伸缩性的扩展。我的项目旨在解决两个问题: 1. 提供 Apache-Kafka 集群的现成解决方案。 2. Kubernetes 集群中的动态代理配置。\n当前状态  支持凭据的 Kubernetes 连接器。 Kubernetes 功能中的 ApacheKafka 预配功能已完全实现。 Helm chart 部分实现。  Kubernetes 中的 Apache-Kafka 配置 此功能是 2.0 版本的一部分,因此尚未正式发布。您可以通过使用 Experimental Update Center 更新到 2.0.0-alpha 版本或直接从 master 分支构建来尝试该功能:\ngit clone https://github.com/jenkinsci/remoting-kafka-plugin.git cd remoting-kafka-plugin/plugin mvn hpi:run  在全局配置页面上,用户可以输入 Kubernetes 服务器信息和凭据。然后他们只需点击一个按钮就可以启动 ApacheKafka 。\n当用户点击 Start Kafka on Kubernetes 按钮时, Jenkins 将根据信息创建一个 Kubernetes 客户机,然后从 resources 中应用 zookeeper 和 kafka yaml 规范文件。\nHelm Chart Apache-Kafka 插件上远程处理的 Helm 图表基于 stable/jenkins 图表和 incubator/kafka 图表。截至目前,该图表仍在开发中,因为它仍在等待第 2 阶段的 Cloud API 实现。但是,您可以使用一个独立的远程 Kafka 代理查看演示图表:\ngit clone -b demo-helm-phase-1 https://github.com/longngn/remoting-kafka-plugin.git cd remoting-kafka-plugin K8S_NODE=\u0026lt;your Kubernetes node IP\u0026gt; ./helm/jenkins-remoting-kafka/do.sh start  命令 do.sh start 将执行以下步骤: * 安装图表(与 Jenkins 和 Kafka 一起使用)。 * 通过应用下面的 JCasC 在 Jenkins master 上启动一台 Kafka 计算机。\njenkins: nodes: - permanent: name: \u0026quot;test\u0026quot; remoteFS: \u0026quot;/home/jenkins\u0026quot; launcher: kafka: {}   启动单个 Remoting Kafka Agent pod 。 您可以通过运行 kubectl 来检查图表状态,例如: ``` $ kubectl get all -n demo-helm NAME READY STATUS RESTARTS AGE pod/demo-jenkins-998bcdfd4-tjmjs 2\u0026frasl;2 Running 0 6m30s pod/demo-jenkins-remoting-kafka-agent 1\u0026frasl;1 Running 0 4m10s pod/demo-kafka-0 1\u0026frasl;1 Running 0 6m30s pod/demo-zookeeper-0 1\u0026frasl;1 Running 0 6m30s  NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/demo-0-external NodePort 10.106.254.187  19092:31090/TCP 6m30s service/demo-jenkins NodePort 10.101.84.33  8080:31465/TCP 6m31s service/demo-jenkins-agent ClusterIP 10.97.169.65  50000/TCP 6m31s service/demo-kafka ClusterIP 10.106.248.10  9092/TCP 6m30s service/demo-kafka-headless ClusterIP None  9092/TCP 6m30s service/demo-zookeeper ClusterIP 10.109.222.63  2181/TCP 6m30s service/demo-zookeeper-headless ClusterIP None  2181/TCP,3888/TCP,2888/TCP 6m31s\nNAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/demo-jenkins 1\u0026frasl;1 1 1 6m30s\nNAME DESIRED CURRENT READY AGE replicaset.apps/demo-jenkins-998bcdfd4 1 1 1 6m30s\nNAME READY AGE statefulset.apps/demo-kafka 1\u0026frasl;1 6m30s statefulset.apps/demo-zookeeper 1\u0026frasl;1 6m30s ```\n下一阶段计划  实施 Cloud API 来配置 Remoting Kafka Agent 。(JENKINS-57668) 将 Cloud API 实施与 Helm 图表集成。(JENKINS-58288) 单元测试和集成测试。 发布版本 2.0 和地址反馈。(JENKINS-58289)  链接  第一阶段演示视频 第一阶段演示幻灯片 Remoting over Apache Kafka plugin 项目页面 Gitter Channel  ",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
465 466 467 468 469
        "auhtor": "Long Nguyen",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/07/11/remoting-kafka-kubernetes-phase-1/",
        "poster": "“./2019-11-08-remoting-over-apache-kafka-plugin-with-kafka-launcher-in-kubernetes/cover.jpg”"
    },
470
    {
471
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-06-building-new-operating-model-devops/",
472 473 474 475 476 477 478 479 480 481 482
        "title": "为 DevOps 构建新的运营模型",
        "type": "wechat",
        "date": "2019-11-06 00:00:00 +0000 UTC",
        "tags": ["DevOps", "运营转型"],
        "description": "为 DevOps 构建新的运营模型",
        "content": " 我一直在撰写有关企业面临的 DevOps 挑战的文章。从根本上讲,它是关于规模的:当企业尝试将其扩展到大型企业通常拥有的 800 多个应用程序中时,它们正努力实现在小型 DevOps 概念验证中看到的相同收益。 如果 DevOps 能够兑现其诺言并为企业带来可观的价值,那么就必须克服这一规模挑战。\n重塑业务 今天,我想看看企业内部的关键变化,在实现 DevOps 的好处之前,这绝对是必须发生的:运营转型。\n如今,大多数企业都围绕具有单向命令和控制结构的分层模型工作。这是自去年以来建立企业的方式:公司高层的“高级主管”领导层以相当专制的方式设定了公司的目标和战略。在此模型中,经理和业务部门负责人是高级管理人员意愿的执行者,以确保公司其他所有人都可以执行其战略方向。DevOps 的发展方向相反-从开发人员和运营人员的基层运动开始,然后逐步发展到如今在董事会席位上占有一席之地。\n民主发展 为了使 DevOps 大规模发展,需要用更加有机、松散和自治的东西来代替这种结构。如果旧模式是专制的,那么新模式与现代政治革命家在松散连接和组织上“扁平”的结构中融合的方式有更多的共同点。\nDevOps 的理想运营模式是一种权力民主化的模式,并且公司中的每个人都有权发挥自己的领导作用。在这里,高级主管确定了出行的方向,但是然后相信他们熟练的开发人员会做些必要的事情。在这种模式下,管理者促进和授权,而不是直接参与;确保开发人员拥有实现目标所需的一切,同时在这里和那里轻轻地推动,以确保他们的工作与整体公司议程和战略路线图保持一致。这涉及到我们在流动的劳动力中看到的宏观变化,并逐渐过渡到非中介的世界。\n毋庸置疑,进行这种转换并不容易。这意味着要颠覆数百年来公认的惯例,放弃某些人认为晋升和任期使他们有权获得的精细控制。而且要明确一点:IT 部门将首当其冲。长期以来,控制权的守卫者需要转变为促进者。IT 将围绕应用程序开发设置指南和策略,并在需要时进行干预,但在日常工作中,IT 部门将需要退后一步,让 DevOps 开发人员继续前进,然后一定会建立信任和真正创新的文化,并蓬勃发展。\n让专家掌控 开发人员团队比公司中的其他任何人都更了解他们的业务所面临的软件工程挑战。他们是理想的解决方案,同时敏捷的 DevOps 流程将帮助他们做到这一点。但是,如果开发人员大规模利用 DevOps,则需要摆脱来自 IT 和更广泛业务的严格监督。这不是关于信任的问题-人力资源和分析技术可供企业领导者远程监视和分析开发人员的效率。它只是归结为效率:以一种更加敏捷和有效的开发方法来消除障碍。以一种可以为您提供广泛、以业务为中心并且与供应商无关的方式执行此关键操作。如果没有民主变革的能力,并根据我们的经验来衡量结果,您将永远无法完全成功并获得真正的利益。\n在我的下一个博客中,我将探讨帮助 DevOps 扩展的另一个关键因素:度量。 因此,请再次访问。\n",
        "auhtor": "Jon Hammant",
        "translator": "zhaoying818",
        "original": "https://www.linkedin.com/pulse/building-new-operating-model-devops-jon-hammant/",
        "poster": "devops.jpg"
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
483
    {
484
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/11/2019-11-04-jcli-v0.0.22/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
485 486 487 488 489 490 491 492 493 494 495
        "title": "Jenkins CLI 命令行 v0.0.22",
        "type": "wechat",
        "date": "2019-11-04 00:00:00 +0000 UTC",
        "tags": [],
        "description": "jcli-v0.0.22 发布",
        "content": " Jenkins CLI 可以帮忙你轻松地管理 Jenkins。不管你是一名插件开发者、管理员或者只是一个普通的 Jenkins 用户,它都是为你而生的!\n项目地址:https://github.com/jenkins-zh/jenkins-cli\n本次发布的更新 本次发布,包含了三位贡献者提供的代码以及文档改进。而且,两位贡献者,以该项目的名义向 JetBrains 申请了 Goland 的开源许可证。到目前为止,包含有5位开发者的贡献。期待有更多的 Jenkins 用户参与到这个项目当中。\nWindows 用户,现在可以通过 Scoop 来很方便地安装 jcli 了。 安装命令为:scoop install jcli\n🚀 功能  支持 HTTP 请求的语言设置 (#183 ) @yJunS 支持通过拷贝的方式创建 Jenkins 任务 (#205) @LinuxSuRen  📝 文档完善  在自述文件中增加 JetBrains 开源许可证的描述 (#209) @LinuxSuRen 完善英文的自述文件 (#210) @scottydocs 在文档中增加对 scoop 的描述 (#208) @LinuxSuRen 增加 godoc 的徽章 (#201) @LinuxSuRen  👻 维护  增加 PR 模板 (#212) @LinuxSuRen 把 dependencies 添加为标签 (#203) @LinuxSuRen 把 gopkg.in/yaml.v2 从 2.2.2 升级到 2.2.4 (#202) @dependabot-preview  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“great-wall.jpeg”"
    },
496
    {
497
        "uri": "https://jenkins-zh.cn/meeting/2019-10-30/",
498 499 500 501 502 503 504 505 506 507 508
        "title": "",
        "type": "meeting",
        "date": "2019-10-30 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 例会时间  双周,指的是以年为单位的,第一周为单周,第二周为双周,以此类推  论坛  管理员招募?  捐助\n 充值到阿里云账号 一周之内,发出一份公开的感谢信(测试吧)@linuxsuren  清理不活跃的账号权限\n github 百度统计 @yJunS 公众号(zhaizhijun0) 统一下其他媒体平台的关联手机号 @yJunS  Jenkins 相关资源下载很慢,包括:容器镜像、deb 镜像源、插件等\n 思考如何能把这块接起来  视频,在微信公众号上发布\n 技术交流 例会  微信群\n 坏处  缺少管理员 不希望有人同时在多个群里发同样的问题  好处  希望交流的人肯定是大于500人的 方便通知(技术相关的,不会有活动类的)  能够解决管理问题的前提下,可以开群2。管理员必须参加例会,可以不做其他的 管理员需要做的事情 @zhaoying818  能够认同并严格执行群管理规则 时间上,机器人会负责拉人,管理员审批通过;或者,警告违规的人;不听警告的踢出   流量的导向?\n 新人介绍\n zhaoying818   ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
509
    {
510
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/10/2019-10-28-introducing-new-folder-authorization-plugin/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
511 512 513 514 515 516 517 518 519 520 521
        "title": "介绍新的文件夹授权插件",
        "type": "wechat",
        "date": "2019-10-28 00:00:00 +0000 UTC",
        "tags": ["外挂程式 安全 性能 gsoc gsoc2019"],
        "description": "介绍新的文件夹授权插件",
        "content": " 在我的 Google Summer of Code Project 期间,我创建了全新的 Folder Auth 插件,可轻松管理 Folders plugin 对文件夹中组织的项目的权限。这个新插件旨在通过易于管理的角色进行快速权限检查。该插件的 1.0 版本刚刚发布,可以从您的 Jenkins 更新中心下载。\n该插件的灵感来自角色策略插件,可改善性能并简化角色管理。开发该插件是为了解决 Role Strategy Plugin 在许多角色上的性能限制。同时,该插件通过文件夹解决了 Jenkins 中组织项目最受欢迎的方式之一。该插件还具有一个新的 UI ,将来会有更多改进。\n该插件支持三种类型的角色,分别适用于 Jenkins 中的不同位置。 * 全局角色:适用于 Jenkins 的所有地方 * 代理角色:限制连接到您的实例的多个代理的权限 * 文件夹角色:适用于文件夹内组织的多个作业\n角色策略插件的性能改进 与角色策略插件不同,此插件不使用正则表达式来查找匹配的项目和代理,从而改善了我们的性能并简化了管理员的工作。为了减少需要管理的角色数量,通过文件夹角色授予文件夹的权限将继承其所有子项。这对于通过单个角色访问多个项目很有用。同样,一个代理角色可以应用于多个代理,并分配给多个用户。\n此插件的设计目的是在权限检查方面优于角色策略插件。这些改进是使用我在 GSOC 项目的第一阶段创建的micro-benchmark framework来衡量的。两个插件相同配置的基准测试表明,与角色策略 2.13 中的全局角色相比, 500 个全局角色的权限检查速度提高了 934 倍,角色策略 2.13 本身包含一些性能改进。将文件夹角色与角色策略的项目角色进行比较,对于 250 个组织在 150 个用户的实例上的两级深层文件夹中的项目,对作业的访问权限检查几乎快了 15 倍。您可以在 此处 看到基准和结果比较。\nJenkins 配置作为代码支持 该插件支持 Jenkins 的“代码即配置”功能,因此您无需通过 Web UI 即可配置权限。YAML 配置如下所示:\njenkins: authorizationStrategy: folderBased: globalRoles: - name: \u0026quot;admin\u0026quot; permissions: - id: \u0026quot;hudson.model.Hudson.Administer\u0026quot; # ... sids: - \u0026quot;admin\u0026quot; - name: \u0026quot;read\u0026quot; permissions: - id: \u0026quot;hudson.model.Hudson.Read\u0026quot; sids: - \u0026quot;user1\u0026quot; folderRoles: - folders: - \u0026quot;root\u0026quot; name: \u0026quot;viewRoot\u0026quot; permissions: - id: \u0026quot;hudson.model.Item.Read\u0026quot; sids: - \u0026quot;user1\u0026quot; agentRoles: - agents: - \u0026quot;agent1\u0026quot; name: \u0026quot;agentRole1\u0026quot; permissions: - id: \u0026quot;hudson.model.Computer.Configure\u0026quot; - id: \u0026quot;hudson.model.Computer.Disconnect\u0026quot; sids: - \u0026quot;user1\u0026quot;  带有 Swagger 支持的 REST API 该插件提供 REST API ,用于通过 Swagger.json 管理具有 OpenAPI 规范的角色。您可以在 SwaggerHub 上查看 Swagger API 。SwaggerHub 提供了多种语言的存根,可以下载并用于与插件进行交互。您还可以使用 curl 从命令行查看一些示例请求。\n接下来做什么 在不久的将来,我想改进用户界面,使插件更容易使用。我还希望改进 API 、文档和更多的优化来提高插件的性能。\n链接和反馈 我很想听听你的意见和建议。请随时通过 Role Strategy Plugin Gitter chat 或通过 Jenkins Developer Mailing list 与我联系。\n Presentation slides for second phase evaluations Documentation for the Folder Auth Plugin Demo of the Folder Authorization plugin  ",
        "auhtor": "Abhyudaya Sharma",
        "translator": "wenjunzhangp",
        "original": "https://jenkins.io/blog/2019/08/16/folder-auth-plugin/",
        "poster": "“./2019-10-28-introducing-new-folder-authorization-plugin/cover.jpg”"
    },
522
    {
523
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/10/2019-10-25-plugin-management-tool-alpha-release/",
524 525 526 527 528 529 530 531 532 533 534
        "title": "Alpha 版本的插件管理库和 CLI 工具",
        "type": "wechat",
        "date": "2019-10-25 00:00:00 +0000 UTC",
        "tags": ["plugins", "pluginmanagement", "platform-sig", "cli", "gsoc", "gsoc2019"],
        "description": "Alpha 版本的插件管理库和 CLI 工具",
        "content": " \u0026ldquo;人人都在重复造轮子,部分像实现插件管理的\u0026rdquo;细节\u0026rdquo;(签名元数据,制品校验和,从核心独立出来的插件\u0026hellip;)。 很明显, Jenkins 应该为实时 Jenkins 实例之外的插件安装提供充足的工具。\u0026rdquo; JENKINS-53767\n我的 Google Summer of Code project 项目试图解决这个问题,方法是创建一个库,该库将在 Jenkins 的不同实现中统一插件管理逻辑,并提供一个可以使用户轻松下载插件并在 Jenkins 启动之前查看插件信息的 CLI 工具。 我很高兴分享我们刚刚发布的 Alpha 版本,您可以在此处查看!\nGSoC 阶段 1 更新 当我考虑将插件管理器从 Jenkins 核心中移出时,由于依赖项的复杂性和数量,这最终成为了最具挑战性的第一步。相反,我们决定首先将 Jenkins Docker 中的 install-plugins.sh bash 脚本转换为 Java。 install-plugins.sh 脚本存在多个问题,即它是 bash 脚本并且扩展性有限,此外,它不会检索所有最新的更新中心的元数据。\nAlpha 版本详情 模仿官方 Jenkins Docker 镜像中 install-plugins.sh 脚本中的操作,新的插件管理库接收插件列表、它们的版本和(或) URL,从中可以下载插件,并下载所需的插件及其依赖。插件从更新中心下载到指定目录,然后可以加载到 Jenkins 中。当前,可以通过 plugins.txt 文件和(或) -plugins 的 cli 选项指定要下载的插件,我们计划进一步扩展可以接收的输入格式。 还支持用于不同更新中心的自定义版本说明符。\n该库将首先检查当前是否在用户指定的下载位置或用户指定的 Jenkins war 文件中安装了任何请求的插件。如果要求更高版本或更高版本作为依赖项,则将忽略或升级已安装的插件。确定插件下载 URL 后,库将下载插件并解析和下载其依赖。\n这仅仅是个开始:插件管理器库和 cli 工具仍在开发中。 有关 CLI 选项以及如何运行该工具的最新信息,请参见存储库 README.md 。 即将提供更强大的输入解析,对安全警告和可用更新的支持,Docker集成以及其他功能!\n链接和反馈 欢迎通过插件安装管理器 CLI 工具 Gitter 聊天室或 Jenkins 开发者邮件列表与我们联系。我希望收到您的问题,评论和反馈!我们在世界标准时间下午6点(星期二和星期四)开会。\n Phase 1 Presentation Slides Phase 1 Recorded Demo Jira Issue Search Repository  ",
        "auhtor": "stopalopa",
        "translator": "zhaoying818",
        "original": "https://jenkins.io/blog/2019/07/02/plugin-management-tool-alpha-release/",
        "poster": "devopsworld.jpg"
    },
535
    {
536 537 538 539
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/10/2019-10-20-online-activity/",
        "title": "Jenkins 线上技术交流",
        "type": "wechat",
        "date": "2019-10-20 00:00:00 +0000 UTC",
540
        "tags": [],
541 542 543
        "description": "各种技术群里交流不过瘾?线上技术交流期待你的参与!",
        "content": "在 Jenkins 中文社区微信技术交流群里,看到有人提出各种各样的问题,有一些问题快速得到了解答, 有一些则可能由于各种原因没有收到回答。大家都能看出来,在各种群里交流有很多的弊端,例如:\n 某个时段大家在忙工作上的事情 文字性的问题描述不够清晰 难以记录交流成果 其他  为了能让更多 Jenkins 的用户有一个集中交流的地方,掌握正确的学习以及使用方法,了解常见问题如何排查。 我们会定期组织线上交流会,时间为两周一次,时长一个小时。参与者需要提前准备好 zoom 软件。如果希望 提问的话,则一定要提前找一个周围没有噪音的地方,否则主持人会禁掉你的麦克风。\n那么,分享的内容是什么呢?具体的活动流程是什么样的?\n值得您注意的是,任何人都可以在下次活动发布之前,申请作为分享人。您可以通过如下的几种方式进行申请:\n Jenkins 公众号后台留言 在社区活动微信群中留言 发送邮件到 admin@jenkins-zh.cn  您需要说明要分享的主题,时间控制在半个小时以内;如果内容较多的话,可以以系列的形式来分享。我们希望尽可能 给其他参与者多留一些提问时间。作为分享人,需要至少提前十分钟进入会议。\n因此,活动流程非常简单。首先是技术分享,然后参与者提问互动。活动中会有视频录制,并在结束后上传到 Jenkins 中文社区的哔哩哔哩账号下。\n而本次的线上分享活动,由 Jenkins 中文微信技术群的群主来分享有关 Jenkins 多分支流水线的内容。 大致内容包括:\n 流水线概要 多分支流水线的使用场景 多分支流水线的应用 多分支流水线的优缺点  活动时间:每个单周周三21:00~22:00 参与方式:请访问 https://jenkins-zh.github.io/event/\n注意\n每次活动时间开始后,五分钟内没有人加入的话,活动取消。 具体活动的动态,我们会在微信*活动群*中给出通知。\n",
        "auhtor": "linuxsuren",
544 545
        "translator": "",
        "original": "",
546
        "poster": "eagle.jpeg"
547 548
    },
    {
549 550 551 552
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/10/2019-10-17-jcli-v0.0.21/",
        "title": "Jenkins CLI 命令行",
        "type": "wechat",
        "date": "2019-10-17 00:00:00 +0000 UTC",
553
        "tags": [],
554 555 556
        "description": "jcli-v0.0.21 发布",
        "content": " Jenkins CLI 可以帮忙你轻松地管理 Jenkins。不管你是一名插件开发者、管理员或者只是一个普通的 Jenkins 用户,它都是为你而生的!\n项目地址:https://github.com/jenkins-zh/jenkins-cli\n本次发布的更新 本次发布,主要增加了下载归档文件以及命令行补全的功能。\n🚀 功能  增加为 jcli 生成完整文档的子命令 (#174) @LinuxSuRen 支持流水线 input 的输入 (#164) @LinuxSuRen 增加下载归档文件的子命令 (#185) @LinuxSuRen  🐛 缺陷修复  为每个请求增加权限信息 (#187) @yJunS 修复了首次安装后无法打印版本信息的问题 (#186) @zirmax  📝 文档完善  增加中、英文项目自述文件的链接 (#194) @LinuxSuRen  👻 维护  移除无用的代码行 (#178) @LinuxSuRen 为 job 客户端增加测试代码 (#190) @LinuxSuRen 为idea 增加 git 提交时忽略的文件配置 (#199) @LinuxSuRen 增加 jcli completion 的命令描述 (#188) @LinuxSuRen 绑定代码质量和构建状态 (#184) @LinuxSuRen 为 user client 增加测试代码 (#180) @LinuxSuRen 增加代码仓库自动备份的流水线 (#173) @LinuxSuRen 增加下载数量以及代码仓库大小的徽标 (#168) @LinuxSuRen  ",
        "auhtor": "linuxsuren",
557 558
        "translator": "",
        "original": "",
559
        "poster": "“great-wall.jpeg”"
560
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
561
    {
562 563 564 565
        "uri": "https://jenkins-zh.cn/meeting/2019-10-16/",
        "title": "",
        "type": "meeting",
        "date": "2019-10-16 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
566
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
567
        "description": "",
568
        "content": " 例会时间  双周,指的是以年为单位的,第一周为单周,第二周为双周,以此类推  论坛  http://discourse.surenpi.com/ 邮箱服务器,不支持腾讯企业邮箱(可以自己搭建一个) 管理员  捐助  充值到阿里云账号   ",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
569
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
570 571
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
572
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
573 574
    },
    {
575 576 577 578
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-27-jenkins-in-hacktoberfest/",
        "title": "Jenkins 喊你参加 Hacktoberfest",
        "type": "wechat",
        "date": "2019-09-27 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
579
        "tags": [],
580 581 582
        "description": "第六届黑客十月庆典",
        "content": " Hacktoberfest 是一场为期一个月的开源软件庆祝活动,该活动由 DigitalOcean 和 DEV 共同组织。\n Hacktoberfest 面向全球社区的每一位贡献者 至少须要向公开的 GitHub 仓库提交四个正式的 Pull Request 你可以在十月一日到三十日之前的任意时间注册  如何开始? 在 https://hacktoberfest.digitalocean.com/ 注册账号,并提交 PR 到 GitHub 的公共仓库。推荐提交高质量的 PR。\n而作为 Jenkins 的用户,我们的首选当然是 Jenkins 社区的相关代码仓库了。\n我们非常地欢迎各位认可、热爱开源的朋友们,共同完善 Jenkins 简体中文插件、Jenkins 中文网站等本地化的内容。\n除了上一届活动的项目以外,今年社区还推荐了一个由 Golang 编写的 Jenkins CLI 项目。下面是 jcli 这个命令行工具的功能特点:\n 管理多个 Jenkins 服务器 支持搜索、安装、卸载、升级以及下载 Jenkins 插件 支持搜索、编辑、触发流水线任务,查看构建历史 支持查看、移除队列中的任务 支持命令行补全 支持代理设置  如果你用的是 MacOS 的话,可以通过 brew 很方便地安装该工具,命令如下:\nbrew tap jenkins-zh/jcli brew install jcli  对于其他操作系统的用户,也可以在项目首页 https://github.com/jenkins-zh/jenkins-cli/ 上找到对应的安装帮助信息。\n如果还希望了解更多的社区项目,请访问 https://jenkins.io/events/hacktoberfest/\n如何获取奖品 在你完成指定的 PR 后,请关注你的邮箱,官方会发送邮件让你来填写T恤尺码以及收件地址等。奖品除了T恤以外还有官方的贴纸。如果在11月初还没有收到邮件的话,请及时联系官方人员。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
583 584
        "translator": "",
        "original": "",
585
        "poster": "hacktoberfest_19_logo.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
586 587 588 589 590 591 592 593
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-23-devops-world-jenkins-world/",
        "title": "2019 DEVOPS WORLD和JENKINS WORLD 获奖者公布",
        "type": "wechat",
        "date": "2019-09-23 00:00:00 +0000 UTC",
        "tags": ["DEVOPS JENKINS"],
        "description": "2019 DEVOPS WORLD和JENKINS WORLD 获奖者公布",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
594 595 596 597 598 599 600
        "content": "  15个组织和个人荣获DevOps杰出成就,开源贡献和渠道合作伙伴绩效\n DEVOPS WORLD | JENKINS WORLD,2019年8月15日在旧金山,由CloudBees,企业DevOps领导者推动经济持续发展,今天宣布了2019 DevOps world 和 Jenkins world 获奖者。该奖项表彰3个类别的成就:Jenkins 社区奖,表彰对 Jenkins 项目做出重大贡献的人;CloudBees 创新奖,表彰在 DevOps 转型中取得优秀成果的组织;和CloudBees 渠道合作奖,重点介绍在创收和帮助组织实现DevOps转型方向表现出色的合作伙伴。\nCloudBees创新将的获得者包括各种规模的组织,从风险投资的小型创业公司到全球技术巨头。Jenkins 社区将授予了4个人,他们为 Jenkins 社区做出了贡献。最后5个渠道合作伙伴因在勤奋卓越获得认可。\nJENKINS 社区奖 Jenkins 社区奖由 Jenkins 创始人兼 CloudBees 首席科学家 Kohsuke Kawaguchi 和 Jenkins 大使组成的小组选出。Jenkins 大使每年都会被提名,他们都是有影响力的 Jenkins 爱好者,热衷于与他人分享 Jenkins 的技术专长。\n“2019 Jenkins社区奖表彰了社区成员的努力,他们在几个关键领域为推进 Jenkins 做出了重大贡献“,Kawaguchi 表示,”今年的提交的质量比以往任何时候都要好。”\n2019 Jenkins 社区奖得主:  2019最有价值的 Jenkins 贡献者 - Oliver Gondža 2019Jenkins 安全 MVP - Victor Gazdag 2019最有价值的 Jenkins 倡导者 – 赵晓杰 2019最有创新的 Jenkins X 实现 - Vincent Behar  *CloudBees创新奖** CloudBees 创新奖由一个评委团选出,评委团成员包括 CloudBees 首席执行管兼联合创始人 Sacha Labourey,DevOps.com 主编兼创始人 Alan Shimel,Google Cloud 产品管理总监 Aparna Sinha。\n“我们很高兴有机会庆祝 CloudBees 客户定期展示的杰出成就”,CloudBees 首席执行管兼联合创始人 Sacha Labourey 表示,“2019 DEVOPS WORLD | JENKINS WORLD奖获奖者是DevOps行业杰出领导力的5个例子”。\n2019 CloudBees 创新奖得主:  DevOps 可扩展性成就 – AIG DevOps 可扩展性成就 – Accenture DevOps 优秀自动化 – American Express Global Business Travel DevOps 优秀自动化 – Broadridge Financial Solutions DevOps 新星(荣誉奖)- Pinger  CloudBees 渠道合作伙伴奖 CloudBees 渠道合作伙伴奖由 CloudBees 渠道团队选出。奖项颁发给5个合作伙伴类别中的渠道合作伙伴。获奖者在 DevOps 中展示了经过验证的专业知识,同时在合作领域也表现出色。\n2019渠道合作伙伴奖得主:  2019年度美洲合作伙伴 – Zivra 2019年度最佳新秀合作伙伴 – ThunderCat 2019年度渠道营销合作伙伴 – Fierce Software 2019年度公共部门合作伙伴 - Fierce Software 2019年度亚太地区合作伙伴 – TechMatrix  ",
        "auhtor": "Deborah Schalm",
        "translator": "H5ang",
        "original": "https://devops.com/2019-devops-world-jenkins-world-award-winners-announced/",
        "poster": "jenkins-world.jpeg"
    },
    {
601
        "uri": "https://jenkins-zh.cn/meeting/2019-09-22/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
602 603 604 605 606 607 608 609 610 611 612 613
        "title": "",
        "type": "meeting",
        "date": "2019-09-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "今天主要讨论社区对于接收外部资金捐助的事情\n 有捐助意向的企业是:测吧(北京)科技有限公司 金额  我的理解是至少能给到2500(是基于在阿里云上购买一年的服务器的费用) 本次希望能得到2500~10000元的捐助  捐助方的权益  在官网首页以及合作伙伴中加logo以及链接  是否专款专用?\n 公开社区基金的用途\n 基础设施(域名、服务器) 技术类活动组织(茶歇、礼品、场地) 成员激励:季度、年度  社区基金问题\n 没有对公账户 缺少了解财务的人才  考虑从在校学生里的相关专业来招募  需要在一个地方明确地列出来资金的使用情况(进账、出账) 对资金的(进账、出账)做分类  需要确定一个流程\n 确定意向 确定捐助细节  捐助类型(资金、实物、虚拟物品等) 接收款项的账户 资金用途 时间 双方的联系人  公开捐助记录(历次)  https://jenkins-zh.cn/about/sponsors-list/(增加类型以及明细)  撰写并发布感谢捐助方的文章  论坛\n 选型(开源)  https://github.com/discourse/discourse https://github.com/satellity/satellity https://github.com/search?q=forum https://github.com/b3log/symphony  管理员(征集?严格的挑选)  考虑分短期和长期的管理员  调试完成后再使用基金   ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
614
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-19-introduce-react-plugin-template/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
615 616 617 618 619 620 621 622 623 624 625
        "title": "React Plugin Template,让你可以使用 React 来编写 Jenkins 插件",
        "type": "wechat",
        "date": "2019-09-19 00:00:00 +0000 UTC",
        "tags": ["react", "plugin", "template", "gsoc", "gsoc2019"],
        "description": "React Plugin Template,让你可以使用 React 来编写 Jenkins 插件",
        "content": " 模板地址\nReact Plugin Template https://github.com/jenkinsci/react-plugin-template\n起因 这个模板是笔者在今年的 Google Summer of Code 中的项目 Working Hours - UI Improvement 中产出的。由于我们想使用 React 的一些组件来优化用户体验,例如在 Working Hours 里面我们想用 ReactDatepicker 来帮助用户选择日期,于是整个 Working Hours 插件的前端部分都试图用 React 来编写,而由于 Jenkins 的传统插件编写主要还是用的 Jelly ,一套类似 JSP 的后端渲染引擎,因此笔者在一开始也踩了不少坑。以至于想到,可以抽象出一套插件的脚手架来帮助有相似需求的同学。\n链接:\nGSoC:Working Hours UI Improvement https://summerofcode.withgoogle.com/projects/#6112735123734528\nGithub:Working Hours 插件 https://github.com/jenkinsci/working-hours-plugin\n概述 在以往,我们可以使用 Jelly 来开发 Jenkins 插件的前端部分,同时一些请求可以绑定到对应的类,但是当我们想要更高程度地去自定义插件界面的时候,Jelly 就显得捉襟见肘了。这就是这个模板的目的,帮助开发者使用 React 来开发一个插件。\n同时,有了 React ,我们就可以使用很多基于 React 的库,webpack 也可以帮助我们更安全更高效地使用 js 库。\n特点 | 集成 React | 开发者可以使用 React 充分控制 UI | 使用了 Iframe | Iframe 隔离了之前 Jenkins 添加的一些 js 库会造成的影响,例如 Prototype.js。 | 使用 maven 的生命周期 | 使用了 Frontend Maven Plugin https://github.com/eirslett/frontend-maven-plugin, npm 脚本可以在 maven 的生命周期中被同步执行。 | 使用 Webpack | Webpack 可以减少最终包的体积,同时避免 js 库对全部命名空间的影响 | 为每个请求附加 Jenkins Crumb| Jenkins Crumb 是 Jenkins 的一套 token 系统,在本模板中已经自动附加到 axios 实例上 | 使用了 Express 的 devserver | 可以单独打开一个支持热更新的 devserver 来编写前端界面\n截图 插件 UI\n示例入口\n入门 克隆仓库:\ngit clone https://github.com/jenkinsci/react-plugin-template.git cd react-plugin-template  安装 maven 依赖和 npm 包\nmvn install -DskipTests  运行支持热更新的网页\nnpm run start  运行插件\nmvn hpi:run -Dskip.npm -f pom.xml  发送HTTP请求 由于 Jenkins Crumb 策略默认是开启的,每个请求都被要求包含一个 Jenkins Crumb, 所以请使用已经设置好了 Jenkins Crumb 的 axiosInstance,可以在 src/main/react/app/api.js 中找到。\nexport const apiGetData = () =\u0026gt; { return axiosInstance.post(\u0026quot;/data\u0026quot;); };  或者你想使用你自己的 http client,你只需将 Jenkins Crumb 添加到你每个请求的 header中,这个 header 的 key 和 content 都可以使用 src/main/react/app/utils/urlConfig.js,具体操作如下\nconst headers = {}; const crumbHeaderName = UrlConfig.getCrumbHeaderName(); if (crumbHeaderName) { headers[crumbHeaderName] = UrlConfig.getCrumbToken(); }  编写后端的请求处理器 当你可以自定义你的请求后,你同时也需要一个在后端的 Handler。\nJenkins 使用了一个叫做 Stapler的框架来处理请求。你可以使用一个继承了 Action 的类来创建一个子 url ,同时可以使用一个 StaplerProxy 来转发或者直接处理请求。\n链接\nStapler Reference http://stapler.kohsuke.org/reference.html.\n示例 handler 如下,ManagementLink(已经继承 Action )会首先拿到这个请求然后转交个 PluginUI 来处理。\n@Extension public class PluginManagementLink extends ManagementLink implements StaplerProxy { PluginUI webapp; public Object getTarget() { return webapp; } public String getUrlName() { return \u0026quot;react-plugin-template\u0026quot;; } }  随后, stapler 会在 PluginUI 中寻找适合的处理函数,如下, doDynamic 便是一个处理函数, 然后便是我摸自定义的,根据 url 来判断需要调用的函数, getTodos 或者 setTodos, 在这里 PluginUI 可能更像一个 url router。\npublic class PluginUI{ public HttpResponse doDynamic(StaplerRequest request) { ... List\u0026lt;String\u0026gt; params = getRequestParams(request); switch (params.get(0)) { case \u0026quot;get-todos\u0026quot;: return getTodos(); case \u0026quot;set-todos\u0026quot;: return setTodos(request); } ... } }  保存数据 你可以使用一个 Descriptor 来保存你的数据\n@Extension public class PluginConfig extends Descriptor\u0026lt;PluginConfig\u0026gt; implements Describable\u0026lt;PluginConfig\u0026gt;  当你每次修改数据, 调用 save() 来保存他们。Jenkins 是使用基于 xml 的序列化方法来保持数据的。\npublic void setTodos( @CheckForNull List\u0026lt;Todo\u0026gt; value) { this.todos = value; save(); }  而在你的 handler 中,你可以调用如下代码来找到你的这个存储数据的对象。\nconfig = ExtensionList.lookup(PluginConfig.class).get(0);  自定义你的插件 把所有 react-template 修改为你的插件名  在 org/jenkinsci/plugins/reactplugintemplate/PluginUI/index.jelly , 修改 iframe 的 id 和 source url. 在 src/main/react/server/config.js , 修改 devserver 的代理路径 在 src/main/react/package.json , 修修 start 命令中的 BASE_URL 在 pom.xml , 修改 artifactId 在 org/jenkinsci/plugins/reactplugintemplate/PluginManagementLink.java , 修改 names。  为你的插件自定义一个页面 比较推荐使用 Management Link, 这会让你的插件有一个独立的页面, 并且可以在系统管理界面 /manage 放置一个入口。\n原理 本模板仅仅是将一个 webpack 的 project 放到了 Maven project 中,同时将 webpack 的 build 结果复制到插件的 webapp 目录,随后便可以在 iframe 中通过 url 访问到,最后被 Jelly 渲染到网页。\n为什么使用Iframe? 因为到现在,Jenkins 的网页已经添加了很多的 js 库了(似乎是添加到全局的),因此可能会和较新的库产生一些冲突。因此也行一个 Iframe 可以使我们的插件运行在一个相对“干净”的环境里面。\n链接 Github: React Plugin Template https://github.com/jenkinsci/react-plugin-template\nGithub: Working Hours Plugin https://github.com/jenkinsci/working-hours-plugin\n",
        "auhtor": "jackshen",
        "translator": "",
        "original": "",
        "poster": "plugin-ui.jpg"
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
626
    {
627
        "uri": "https://jenkins-zh.cn/meeting/2019-09-18/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
628 629 630 631 632 633 634 635 636 637 638 639
        "title": "",
        "type": "meeting",
        "date": "2019-09-18 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 线上活动  hacktoberfest 定期的线上活动,由于 zoom 出了问题,暂时没有推进  线下活动  上海  10月20日,人民广场 https://github.com/jenkins-zh/jenkins-zh/pull/95 人数(120),门票50 议题  Testerhome 接口测试(与 Jenkins 无关) UWA 自动化测试(与 Jenkins 无关) daocloud(待定)    社区合作  开源年会\n 给社区贡献的同学一张免费的门票(早鸟票99),以及其他的权益 没有在当地活跃的成员,无法开展我们社区的展台 工作坊(暂时无人组织)  开源基础设施\n 工作坊(暂时无人组织)   社区管理  是否容易获取到社区的动态 微信群  难以做到用户增长 其他问题   ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
640
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-16-jenkins-world-contributor-summit-and-ask-the-experts-booth/",
641 642
        "title": "Jenkins World 贡献者峰会及专家答疑展位",
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
643
        "date": "2019-09-15 00:00:00 +0000 UTC",
644 645 646 647 648 649 650
        "tags": ["jenkinsworld", "devopsworld2019", "gsoc2019", "community", "opensource", "events", "contributorsummit", "asktheexperts"],
        "description": "本文为 Jenkins World 贡献者峰会活动期间的记录",
        "content": " Jenkins 15周岁啦!Jenkins World 将 DevOps 思想领袖、IT 主管、持续交付实践者以及 Jenkins 社区和生态系统齐聚这场全球活动,让与会者有机会学习、探索以及面对面交流,帮助塑造 Jenkins 的下一次发展以及针对 DevOps 的解决方案。\n此外,Jenkins 贡献者峰会也于旧金山举行。Jenkins 贡献者峰会是现有贡献者以及未来贡献者围绕 Jenkins 项目,以最新思考和最大努力来共同探讨、学习和协作的地方。上午峰会安排是由核心贡献者进行一系列展示介绍。这些介绍突出了每项工作的内容,以及社区成员可以提供哪些帮助。下午分组讨论会上,与同好小组进行了深入讨论,并同子项目贡献者进行合作。\n我非常荣幸能成为其中一员。 第一天 第一天以贡献者峰会开场。这让大家有机会聚在一起讨论对社区的贡献,把脑海中熟悉的名字和本人对上号。大多数人我只通过视频聊天和在 gitter 上见过,所以当时我特别激动。我们聚在一起了解 Jenkins 开源画卷的起点。\n接下来是同好讨论/非正式会议。我主导这些讨论会,个人认为进展十分顺利。成员组织管理员 Martin d’Anjou 和 Jeff Pearce 为我们带来一场有关 Google 编程夏令营(Google Summer of Code,以下简称 GSoC)项目的演讲。\nGSoC 学生 Natasha Stopa 介绍了她的项目——Plugin Installation Manager Library/CLI Tool。这是一个超酷的项目,在社区受到广泛欢迎。\n讨论会结尾是博思艾伦咨询公司(Booz Allen Hamilton)的 Steven Terrana 的展示和精彩的 Jenkins 模板引擎。如果你还没有试过这个,请一定不要错过https://github.com/boozallen/jenkins-templating-engine。\n主展厅 从第二天起,我和其他几位 Jenkins 组织管理者将在 Jenkins 社区的专家答疑(Ask the Expert)展位。\n这真的是一场非常有意思的体验,让我有机会了解社区正在做什么,帮助他们解决面对的问题。问题涉及的范围很广,从 Jenkins X 到我负责维护的种种插件,如 Jenkins Prometheus 和 Sysdig Secure Scanning 插件。也有很多关于 Kubernetes 的问题。有很多关于 Kubernetes 使用情况提高的市场营销方面的数据,但对 Kubernetes 上 Jenkins 的超高兴趣度真的让我大吃一惊。当然,也有机会拍点儿自拍。\n午餐时段的 demo 开始,我们的流程很紧凑。第一个上台的是超棒的 Mark Waite,他来谈谈 Git 插件。很多人在 Jenkins 上用 git。非常感谢 Mark 的分享。\n下一位是 Jenkins 组织管理者 Martin d’Anjou,他介绍了 GSoC。让人难以相信的是,GSoC 也和 Jenkins 一样成立15周年了!\nNatasha Stopa 是参与 GSoC 的学生,她介绍了自己的项目 Plugin Installation Manager Library/CLI Tool。Natasha 真的在这个插件上做了很多努力,能在她的展示中看到结果和支持真的是太棒了。\n最后压轴的就是我了。我展示了正在维护的 Sysdig Secure Scanning 的 Jenkins 插件。感谢每一位当场的朋友。\n就在午餐 demo 之后,我顺道去看了下 Jenkins 开放区。这对社区而言,是讨论议题、自主活动的机会。我真的非常享受这次讨论会,觉得该形式在与会人员中的接受程度很好。\n我们以 Jenkins 组织管理员与 GSoC 学生的合照作为当天活动的结尾。未参与合照的组织管理员为 Lloyd Chang 和 Oleg Nenashev。\n结语 这是一场无与伦比的非凡体验。非常感谢 CloudBees、Jenkins 社区、GSoC、Tracy Miranda、Alyssa Tong 和我的公司 Sysdig。\n想到 Jenkins 成立15周年,真是太了不起了!我们完成了那么多事情,未来也格外灿烂。非常感谢让我有幸为社区服务,成为社区的一部分。未来还有更多个15年!\n如果你有兴趣加入 Jenkins 的任何特别兴趣小组(SIG),请查看以下链接。我们需要您的帮助:(https://jenkins.io/sigs/)\n如果你有兴趣参加编程夏令营,请看此处:(https://jenkins.io/projects/gsoc/) 如果你想和大家聊天讨论,可以在这找到我们:(https://jenkins.io/chat/) 如果你想给我们发邮件,请发送至:(https://jenkins.io/mailing-lists/)\n现场照片 关于作者 Marky Jackson (https://jenkins.io/blog/authors/markyjackson-taulia/)\n该作者没有设置个人简介,请参阅下方社交媒体链接。 GitHub(https://github.com/markyjackson-taulia)\n",
        "auhtor": "Marky Jackson",
        "translator": "shunw19",
        "original": "https://jenkins.io/blog/2019/08/25/jenkinsworld-contrib-summit-ask-the-expert-booth/",
        "poster": "./2019-09-15-jenkins-world-contributor-summit/cover.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
651 652
    },
    {
653
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-11-introducing-gitlab-branch-source-plugin/",
654 655 656 657 658 659 660 661
        "title": "介绍新的 GitLab 分支源插件",
        "type": "wechat",
        "date": "2019-09-11 00:00:00 +0000 UTC",
        "tags": ["gitlab", "plugins", "pipeline", "multibranch", "gsoc", "gsoc2019"],
        "description": "新的 GitLab 分支源插件,允许您基于 GitLab `用户` 或 `组` 或 `子组` 项目创建任务",
        "content": " GitLab 分支源插件已经走出 beta 阶段,并已发布到 Jenkins 更新中心。 它允许您基于 GitLab 用户 或 组 或 子组 项目创建任务。 您可以:\n 从 GitLab 用户/组/子组导入单个项目的分支作为任务(多分支流水线任务) 从 GitLab 用户/组/子组导入所有或部分项目的分支作为任务(GitLab 组任务或 GitLab 文件夹组织)  GitLab 组项目对项目进行扫描, 根据设置的规则导入流水线任务。 导入项目之后, Jenkins 立即基于 Jenkinsfile 流水线脚本运行任务并且将状态通知到 GitLab 流水线状态。 这个插件与其他分支源插件不同,它提供了 GitLab 服务器配置,可以在系统配置中配置。 Jenkins 配置即代码 (JCasC) 也可以用于配置服务器。 要想了解更多关于服务器配置的信息,请参考我之前的博客。\n要求  Jenkins - 2.176.2 (LTS)\n GitLab - v11.0+\n  创建任务 要创建多分支流水线任务(使用 GitLab 分支源)或 GitLab 组任务,您必须将 GitLab 个人访问令牌添加到服务端配置。 凭据用于获取项目的元数据,并在 GitLab 服务器上设置 hook。 如果令牌具有管理访问权限,您还可以设置 系统 Hook,而 Web Hook 可以从任何用户令牌设置。\n创建多分支流水线任务 转到 Jenkins \u0026gt; 新建任务 \u0026gt; 多分支流水线 \u0026gt; 添加源 \u0026gt; GitLab 项目\n Server - 从下拉菜单中选择所需的 GitLab 服务器,需要在创建此任务之前进行配置。\n Checkout Credentials - 如果插件要构建任何私有项目,添加 SSHPrivateKey 或 用户名/密码 类型的凭据。如果所有的项目都是公开的则不需要检出凭据。检出凭据与 GitLab 服务器配置中的凭据(GitLab 个人访问令牌 类型)不同。\n Owner - 可以是 用户、组 或 子组。 根据这一点填充 Projects 字段。\n Projects - 从下拉菜单中选择要构建的项目。\n Behaviours - 这些特性是非常强大的工具,用于配置构建逻辑和构建后逻辑。我们定义了新的特性。您可以在仓库文档中看到所有信息。\n  保存并等待分支索引。您可以从这里自由导航,任务进度显示在左侧。\n索引完成后,导入的项目将所有分支、合并请求和标签列示为任务。\n查看每个任务,您会发现左侧有一些操作项:\n 您可以通过选择 立即构建 手动触发任务。 您可以通过选择相应的按钮访问 GitLab 服务器上的特定分支/合并请求/标签。  创建 GitLab 组类型任务 转到 Jenkins \u0026gt; 新建任务 \u0026gt; GitLab Group\n您可以注意到,配置非常类似于多分支流水线任务,只是缺少 Projects 字段。 您可以添加在您的 Owner(用户/组/子组)中所有项目。 表单验证将与 GitLab 服务器检查 owner 是否有效。 您可以添加 Discover subgroup project 的特性,该特性允许您发现组或子组中所有子组的子项目,但此特性不适用于用户。 在索引时,web hook 在每个项目中创建。 GitLab Api 不支持创建组 web hook,所以这个插件不支持只有 GitLab EE 才支持的特性。\n现在可以查看导入的项目,如果需要,可以在每个文件夹上配置不同的设置。\nGitLab 流水线状态通知 GitLab 从任务排队的角度得到关于构建状态的通知。\n 成功 - 任务成功了 失败 - 任务失败了并且合并请求还没准备好合并 出错 - 发生了意外;例如:Jenkins 任务被终止了 等待 - 任务正在构建队列中等待  关于 GitLab 流水线状态,有指向相应 Jenkins 任务构建的超链接。 要查看流水线阶段和控制台输出,需要访问 Jenkins 服务器。 我们也计划通知管道阶段到 GitLab,但它有一些缺点,目前这已得到解决,有未来的计划添加它作为特性。\n您还可以通过从特性列表中选择 Skip pipeline status notifications 来跳过关于流水线状态的 GitLab 通知。\n合并请求 实现对项目合并请求的支持具有挑战性。 第一,MR 有两种类型,即原始分支和 Fork 的项目分支,因此每个 head 必须有不同的实现。 第二,来自 fork 的 MR 可能来自不可信的源,所以实现了一种新的策略 Trust Members,它允许 CI 仅从具有 Developer/Maintainer/Owner 访问级别的可信用户构建 MR。\n第三,来自 fork 的 MR 由于 GitLab 的问题不支持流水线状态通知,请参考这里。 您可以添加一个特性 Log Build Status as Comment on GitLab ,它允许那您添加一个 sudo 用户(如果你希望 owner 用户为空)以在 commit/tag/mr 上对构建结果进行评论。 要添加 sudo 用户,令牌必须具有管理访问权限。 默认情况下,只有失败/出错以评论的形式被记录,但是您也可以通过勾选复选框来启用成功构建的日志记录。\n有时候,合并请求因为外部错误而失败,因此因此您希望通过评论 jenkins rebuild 来触发 mr 的重新构建。 要启用该触发器,添加特性 Trigger build on merge request comment。 评论内容可以在特性中修改。 出于安全原因,评论者需要有该项目的 Developer/Maintainer/Owner 访问权限。\nHook 如果在服务器配置中配置了 web hook,则在项目上自动创建 web hook。 请确保 web hook 通过 CSRF 过滤器。 Jenkins 监听 /gitlab-webhook/post 路径上的 web hook 。 GitLab 上 web hook 在以下事件上被触发:\n Push Event - 当提交或分支被推送时\n Tag Event - 当新标签被创建时\n Merge Request Event - 当合并请求被创建/更新\n Note Event - 当对合并请求进行评论时\n  如果令牌具有管理访问权限,还可以在 GitLab 服务器上设置系统 Hook。 在创建新项目时触发系统 hook,Jenkins 根据配置触发新项目的重新扫描,并在其上设置 web hook。 Jenkins 监听 /gitlab-systemhook/post 路径上你的系统 hook。 GitLab 上系统 hook 在 Repository Update Events 上被触发:\n你也可以使用 Override Hook Management mode 特性来覆盖默认你的 hook 管理以及选择是否要使用不同的上下文(比如 Item)或完全禁用它。\nJob DSL 以及 JCasC 你可以使用 Job DSL 来创建任务。 下面有一个 Job DSL 脚本的示例:\norganizationFolder('GitLab Organization Folder') { description(\u0026quot;GitLab org folder created with Job DSL\u0026quot;) displayName('My Project') // \u0026quot;Projects\u0026quot; organizations { gitLabSCMNavigator { projectOwner(\u0026quot;baymac\u0026quot;) credentialsId(\u0026quot;i\u0026lt;3GitLab\u0026quot;) serverName(\u0026quot;gitlab-3214\u0026quot;) // \u0026quot;Traits\u0026quot; (\u0026quot;Behaviours\u0026quot; in the GUI) that are \u0026quot;declarative-compatible\u0026quot; traits { subGroupProjectDiscoveryTrait() // discover projects inside subgroups gitLabBranchDiscovery { strategyId(3) // discover all branches } originMergeRequestDiscoveryTrait { strategyId(1) // discover MRs and merge them with target branch } gitLabTagDiscovery() // discover tags } } } // \u0026quot;Traits\u0026quot; (\u0026quot;Behaviours\u0026quot; in the GUI) that are NOT \u0026quot;declarative-compatible\u0026quot; // For some 'traits, we need to configure this stuff by hand until JobDSL handles it // https://issues.jenkins.io/browse/JENKINS-45504 configure { def traits = it / navigators / 'io.jenkins.plugins.gitlabbranchsource.GitLabSCMNavigator' / traits traits \u0026lt;\u0026lt; 'io.jenkins.plugins.gitlabbranchsource.ForkMergeRequestDiscoveryTrait' { strategyId(2) trust(class: 'io.jenkins.plugins.gitlabbranchsource.ForkMergeRequestDiscoveryTrait$TrustPermission') } } // \u0026quot;Project Recognizers\u0026quot; projectFactories { workflowMultiBranchProjectFactory { scriptPath 'Jenkinsfile' } } // \u0026quot;Orphaned Item Strategy\u0026quot; orphanedItemStrategy { discardOldItems { daysToKeep(10) numToKeep(5) } } // \u0026quot;Scan Organization Folder Triggers\u0026quot; : 1 day // We need to configure this stuff by hand because JobDSL only allow 'periodic(int min)' for now triggers { periodicFolderTrigger { interval('1d') } } }  你也可以使用 JCasC 从 Job DSL 脚本直接创建任务。示例请查看该插件仓库。\n如何与我们讨论 bug 或新特性?  这个项目使用 Jenkins JIRA 来跟踪问题。 你可以查看 gitlab-branch-source-plugin 组件下面的问题。\n 在开发者邮件列表中发送你的邮件。\n 加入我们的 Gitter channel。\n  未来的工作  积极维护 GitLab 分支源插件 并从用户那里获取反馈以改进插件的用户体验。 扩展在 BlueOcean 中对 GitLab 流水线的支持。  资源  GitLab API 插件 GitLab API 插件 Wiki GitLab 分支源插件 项目概要 GitHub 分支源插件发布  感谢 Jenkins 以及 Google 编程夏令营 :)\n",
        "auhtor": "baymac",
        "translator": "donhui",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
662
        "original": "",
663
        "poster": "./2019-09-11-introducing-gitlab-branch-source-plugin/gitlab_and_jenkins.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
664 665
    },
    {
666
        "uri": "https://jenkins-zh.cn/meeting/2019-09-05/",
667 668 669
        "title": "",
        "type": "meeting",
        "date": "2019-09-05 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
670 671
        "tags": [],
        "description": "",
672
        "content": " 社区治理  公众号数据分享  线下活动 上海  地点:人民广场 费用:35 时间:需要进一步确定 日程:十月底  线上活动  形式:定期 时长:一小时 时间:周日晚上七点:grhahaha、yJunS 工作日(八点、九点):donhui、linan607、linuxsuren 费用:1~2 回顾:不作为标配,但有人愿意做的话,可以有  ",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
673 674 675 676 677 678
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
679
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/09/2019-09-05-award/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
680 681 682 683 684 685 686
        "title": "Jenkins 中文社区第二届明星贡献者名单",
        "type": "wechat",
        "date": "2019-09-05 00:00:00 +0000 UTC",
        "tags": ["贡献激励"],
        "description": "社区贡献激励",
        "content": " 有这样一群人,他们是一群富有热情的英雄,他们本着内心的使命感,从四面八方汇聚到开源社区,并且为社区贡献自己的一份力量。他们就是“Jenkins 中文社区贡献者”\nJenkins 中文社区贡献激励活动是一个旨在长期为社区贡献者谋福利的活动。在社区伙伴们的积极参与下,第二届社区激励活动结果新鲜出炉了!\n让我们用热烈的掌声恭喜五位明星贡献——donghui、李楠、yJunS、李煜东、书生。他们在社区运营、活动组织、技术交流等方面有着卓越的贡献,并得到社区伙伴们的广泛认可。\n为了表示对五位明星贡献者的感谢和认可,社区将给予五位奖励。奖品是由赞助方——人民邮电出版社提供的精美书籍一本(由贡献者自行挑选),同时明星贡献者名单将在 Jenkins 中文社区官网进行展示。\n奖品展示    成员 奖品     donghui 《人生护城河 如何建立自己真正的优势》   李楠 《持续交付 2.0 业务引领的 DevOps 精要》   yJunS 《精通 jQuery(第二版)》   李煜东 《算法 第四版》   书生 《极简主义——风靡欧美的工作与生活理念》    通过此次活动,让我们再次感觉到了伙伴们参与社区活动的热情! 社区也更加充满动力,会持续举办明星贡献者激励活动!\n为对 Jenkins 中文社区做出卓越贡献的伙伴们谋取更多福利! 第三届激励活动已经在路上,敬请期待。。。\n欢迎广而告之,让更多有着同样理想的伙伴们加入我们的社区! 让更多人一起共建开放、包容、活跃的 Jenkins 社区!\n相关说明: 感谢 Jenkins 中文社区赞助商—人民邮电出版社提供的奖品赞助,感谢积极参与投票的各位社区伙伴。如果有好的意见或者建议欢迎随时联系我们!!\n历次的激励名单请查看 https://jenkins-zh.cn/about/star-plan/\n",
        "auhtor": "shuimujiazi",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
687 688
        "translator": "",
        "original": "",
689
        "poster": "eagle.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
690
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
691 692 693 694 695 696 697 698 699 700 701 702 703 704
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-30-open-source-meeting/",
        "title": "庆祝开源人线下见面会圆满结束",
        "type": "wechat",
        "date": "2019-08-30 00:00:00 +0000 UTC",
        "tags": ["open source"],
        "description": "让我们衷心庆祝开源人线下见面会圆满结束",
        "content": "  什么是开源精神、为什么以及如何参与开源、开源与个人以及企业之间的关系、开源社区存在的重要意义、996是否与开源背道而驰。\n 活动介绍 于2019年8月24日(周六)下午2点举办的开源人线下见面会圆满结束啦。本次活动是由Jenkins 中文社区与开源社首次联合主办的一次以社区、开源为主题的活动。\n活动主要分为几个部分: * 签到 * 嘉宾演讲 * Panel * 活动复盘\n嘉宾介绍 赵晓杰 Jenkins 中文社区发起人\n热衷于传播开源理念、开源技术。多年研发经验,目前关注于 DevOps 领域,尤其是持续交付方面。\n刘天栋 Ted 开源社理事长暨联合创始人、Apache 软件基金会正式会员\n开源社理事长暨联合创始人, Apache 软件基金会正式会员,ASF孵化器项目委员会成员/导师,ASF 筹款委员会成员/赞助伙伴大使,中国信息通信研究院。云计算开源产业联盟.特聘开源治理个人顾问。于2014年10月联合创始开源社。于2018年当选 ASF 正式成员,随后加入 ASF 筹款委员会并成为赞助伙伴大使,2019年成为 ASF 孵化器项目委员会成员,并担任孵化项目(ECharts)导师。 曾历任微软中国战略业务总监、微软开放技术公司及微软亚太研发集团负责开源技术布道及开源社区发展工作;甲骨文(中国)渠道及联盟总监、甲骨文(中国) Linux 战略总监、甲骨文大中华区中间件事业部总经理;Turbolinux 亚太区副总裁等。\n慕睿涛 北京卓晟互联网络技术有限公司 CTO\n毕业于北京工业大学,2003年加入 Sun Microsystems,负责嵌入式 Java 虚拟机的研发。曾于2008年创建了 PSP 上的JavaME 模拟器项目——PSPKVM,在 PSP 自制软件社区有很高的普及度。目前在北京卓晟互联网络技术有限公司任 CTO ,创建并主持了 JOSH 开源项目,致力于为微小型物联网终端设备提供 Java 应用开发与运行环境。\n曹勇华 Chatopera 软件工程师\n从事3年软件开发工作,掌握全栈开发技能,熟悉JavaScript、Java和Node.js等。目前在Chatopera从事春松客服,聊天机器人平台。春松客服是帮助中小型企业快速而低成本的获得好用的智能客服系统。\n演讲环节  赵晓杰分别从扁平~等级、自由~局限、多样~单一、社区精神等几个层面为我们讲解了他对于开源以及开源社区的理解,很客观地从这几个方面把开源的意义进行了剖析。  刘天栋 Ted为我们讲解了Apache 之道:从孵化器到顶级项目之路,生动地讲解了 Apache 之道20年如一日的态度持续为公众提供软件以及软件项目社区提供服务和支持。并且讲解了 Apache 如何从一个孵化器逐步成长为全球最大的开源基金会,令在场的听众听的可谓是如痴如醉。  慕睿涛为我们讲解了他在 Sun 公司的一些经历,以及跟开源开始结缘的一些事宜。从自由软件运动回顾、自由的代价、开放标准与开源代码、Android 与 Java 的纷争、Android 与 Linux 社区的分歧几个方面回顾与分析了开源与开放的本质区别。   panel 环节 此环节的主题为开源社区的发展和维护,由赵晓杰、刘天栋、慕睿涛、曹勇华等4位嘉宾进行了小组讨论。大家就社区而言比较了国内社区与国外社区环境的差别、从公司与社区等不同角度进行了分析,大家分别发表了自己的一些见解和看法。并且对于国内996的环境因素纷纷发表了自己对一些看法。 活动复盘环节 在复盘环节,现场观众纷纷发表了大家对一些看法,以及对于本次活动对一些态度。据现场观众描述,活动举办还是比较成功的,纷纷表示均有不少收获。 以下是现场观众对本次活动的一些建议: * 活动话题\u0026ndash;因为是 Jenkins 中文社区举办,所以大家在潜意识中认为可能会跟 Jenkins 相关,希望可以在活动介绍中把活动主题注明 * 活动议题\u0026ndash;在未参加活动前,大家对活动的议题不太了解,希望可以提前获知,并且可以提前将自己的问题准备好,提高效率 * 分享内容不完整\u0026ndash;因为时间关系,有些演讲嘉宾的内容没有全部分享完,令现场观众心中会有遗憾 * 互动比较少\u0026ndash;在活动中,嘉宾与现场观众的互动较少,提问环节时间较短 * 提前发通知\u0026ndash;希望可以在活动开始前几天提前通知。我们是通过邮件通知的,如果能在活动前加到微信群里的话,效果会好一些 * 设置专场\u0026ndash;希望可以设置不同专场,大家根据不同的专场参加\n结束语 在此,非常感谢京东云、平安云 GitHub、翊翎资本提供对Jenkins 中文社区的大力赞助,同时也感谢开源社与我们一起举办此次活动。\n最后,衷心庆祝本次开源人线下见面会圆满结束。\n",
        "auhtor": "yJunS",
        "translator": "",
        "original": "",
        "poster": "551566921548_.pic_hd.jpg"
    },
    {
705 706 707
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-23-cloud-native-jenkins-on-aws/",
        "title": "AWS 上的云原生 Jenkins",
        "type": "wechat",
708 709 710 711 712 713 714 715
        "date": "2019-08-23 00:00:00 +0000 UTC",
        "tags": ["AWS"],
        "description": "我们如何运用 Terraform、Packer、Docker、Vault、ELB、ASG、ALB 或 EFS 等 AWS 服务实现 Jenkins Cloud-native,以及我们一路走来的收获",
        "content": " 我们使用 Jenkins 搭建持续交付流水线,和其他很多团队一样,这些年我们围绕 Jenkins 创建了很多工作流程和自动化。Jenkins 是我们团队取得成功的关键,让我们能够在上一季度顺利进入生产677次,搭建及部署时长平均为12分钟。\n我们的大部分应用和基础设施可以看作云原生,但当时 Jenkins 服务并不完全适合这个分类:服务在单个服务器上运行,同时很多任务直接在 master 上运行,其部分手动配置包括 secret、插件、定时任务和 startup hacking 的普通膨胀,该膨胀是自2014年首次搭建起不断累积而成。\nJenkins 不仅变成了单体服务和单点故障,而且拆除及重建 Jenkins 对企业也是很大的风险。\n我们决定必须做出改变。这篇博客说明了我们如何运用 Terraform、Packer、Docker、Vault、和 ELB、ASG、ALB 或 EFS 等 AWS 服务实现 Jenkins Cloud-native,以及我们一路走来的收获。\nJenkins 状态 当时不得不面对的关键问题是:如果我们将 Jenkins 服务置于一个容器/自动缩放实例中,我们需要恢复何种状态?\n问题的答案并不简单,值得一提的是,有个 Jenkins 特别兴趣小组(SIG)已经识别出所有导致这一 Jenkins 状态的存储组件。这是一个很棒的起点,因为我们至少得确保那篇文章列出的所有存储类型都考虑在内。\n捷径 这不是新问题。很多团队使用 Docker 容器运行 Jenkins,官方 Jenkins Docker 镜像也得到良好维护。如《Jenkins Dokcer 镜像》文档中解释的:\ndocker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts  这会把 workspace 存在 /var/jenkins_home。所有的 Jenkins 数据(包括插件和配置)都存在上述目录里。创建一个明确的 volume 可以方便管理和附加到另一个容器进行升级。\n上述示例装载主机上的 jenkins_home,其中包括所有 Jenkins 状态。然后该目录可以存在一个外部磁盘上,比如 Kubernetes 持久化存储卷。或者,如果 Jenkins 在 EC2 上运行,该目录可存在一个外部 EBS 或 EFS 卷上。\n这是一种有效的方法,但我们认为这个方法不能达到我们的标准,因为 jenkins_home 不仅包括状态,还包括配置。Block storage 拥有大量用户案例,但一个小小的配置修改就必须进行 snapshot 恢复操作,这似乎并不算是好的解决方案。此外,我们并不是想转移问题:外部存储无法免去手动配置、凭据储存在文件系统等问题。\nSCM 救援 过去,我们用了 Jenkins 备份插件,该插件基本上把配置修改备份在源码控制里,允许配置恢复。这个插件的设计想法很棒,但我们决定不使用它,因为我们无法轻松控制哪些数据实现备份,而且该插件自2011年就没有任何更新了。\n这样的话,如果我们把 jenkins_home 创建成个人 Git repo,并自动提交对 Jenkins 所做的修改呢?此处的关键是排除单独储存的任何二进制文件、secrets 或大型文件(稍后详细介绍)。我们的 .gitignore 文件如下所示:\n/.bash_history /.java/ /.kube/ /.ssh/ /.viminfo /identity.key.enc /jobs/ /logs/ /caches/ # Track static worker and exclude ephemeral ones /nodes/** !nodes/static-node/config.xml /org.jenkinsci.plugins.github_branch_source.GitHubSCMProbe.cache/ /plugins/ /saml-idp-metadata.xml /saml-jenkins-keystore.jks /saml-jenkins-keystore.xml /saml-sp-metadata.xml /scm-sync-configuration/ /scm-sync-configuration.success.log /secret.key /secret.key.not-so-secret /secrets/ /updates/ /workspaces/  几乎所有的纯文本配置都正在 Git 实现持久化。为了给 Jenkins 提供这一配置,我们要做的就是检查 startup 上的 repo;事情渐渐成形。\nSecrets Jenkins 要访问很多地方,也就是说我们需要一个安全的 secret 存储空间。因为我们是 HashiCorpVault 的重度用户,所以自然而然就选了这个工具,不过遗憾的是,Vault 无法涵盖所有场景。比如,scm-branch-source 流水线插件需要 SCM 的认证凭据,并默认为 Jenkins 凭据插件。每次从 Vault 动态检索这些,我们都需要同步一个仓库,这可能导致错误,也会需要额外的精力去维护。\n这就是为什么我们采用 Vault 与 Jenkins 凭据混合的方法: 1. 在 startup 实例中,Jenkins 进行认证,VAult采用 IAM 认证方法。 2. 一个引导脚本检索 Jenkins master.key 和凭据插件所用的其他加密密钥。更多详情请参阅这篇文章。 3. 储存在 jenkins_home/credentials.xml 上的凭据现在可由 Jenkins 解密和访问。\n用 Vault 完全取代凭据插件是我们未来可能探索的问题,不过我们很开心这个方法满足了安全性要求, 同时能轻松与 Jenkins 的其余功能实现集成。\n任务和 workspace 数据 问题从这一步开始变得棘手:jenkins_home/jobs and jenkins_home/workspaces 都含有介于非结构化数据、创建制品和纯文本之间的混合体。这个信息很有价值,可以帮助我们审计、理解之前的流水线 build。这些 build 尺寸很大,而且不太适合 SCM 同步,因此这两个目录都排除在 .gitignore 之外了。\n那我们把这些储存在哪儿呢?我们认为 block storage 最适合存储这种数据。作为 AWS 的重度用户,使用 EFS 完全说得通,因为 EFS 的文件存储可扩展、可用性高并可以通过网络访问,非常易于使用。我们使用 Terraform 整合了 AWS EFS资源,并用 AWS 备份服务制定了一份定期备份计划。\n在 startup,我们将 EFS 卷 、符号链接 jenkins_home/jobs 和 jenkins_home/workspaces 装载到 EFS 目录上,然后启动 Jenkins 服务。\n接下来,Jenkins 服务是唯一可以读写任务 /workspace 数据的界面。值得一提的是,我们有一个 Jenkins 任务定期删除几周前的任务和 workspace 数据,这样数据不会一直增加。\nPacker 和 Terraform 实现编码化 Jenkins 你可能想知道这些是如何凑在一起的?我甚至没说过在哪里运行 Jenkins!我们广泛使用 Kubernetes,花了一些时间思考将 Jenkins 作为容器来运行,可我们决定使用 Packer 和 EC2 来运行 Jenkins master,用短暂 EC2 实例运行这些任务。\n尽管将 master 和 worker 双双作为容器运行的想法很有用,但我们在当前 Kubernetes 集群里没有找到存储 Jenkins 的地方。而且只是为了 Jenkins 就新建一个集群似乎有点儿“杀鸡用牛刀”。此外,我们想保留从其余服务中解耦的基础设施的关键部分。这样的话,如果 Kubernetes 升级对我们的 app 有影响,我们希望至少可以运用 Jenkins 进行回滚。 运行“Docker in Docker”还有另一个问题,这个问题有解,不过还是需要说明一下,因为我们的 build 经常用到 Docker 命令。\n其体系架构如下: 能使用 EC2 实例让过渡更顺畅:我们当时通过 Jenkins EC2 插件用临时 worker node 运行流水线工作,并在声明式流水线代码上调用了这一逻辑,所以不必重构就能用 Dokcer 代理节点是一个加分项。其余工作就是 Packer 和 Terraform 代码,这是我们已经很熟悉的部分了。\n插件 因为插件也是状态!我们在这个项目里想要解决的问题之一就是更好地审计、管理插件。在手动场景中,插件管理可能不受控制,很难了解安装插件的时间和原因。\n大多数 Jenkins 级别的插件配置可以在常规 Jenkins 配置 xml 文档中找到,但安装插件也导致 jar 制品、元数据、图片和其他文件存在 jenkins_home/plugin 目录。\n一种方法是在 EFS 中存储插件,不过我们想将 EFS 使用率保持在最低水平,这无法解决问题,只是转移问题。这就是为什么我们选择对插件安装进行“Packer 化”。\n基本上,在我们的 AMI 定义中,有一个插件文件罗列了插件和版本,大致如下:\n# Datadog Plugin required to send build metrics to Datadog datadog:0.7.1# Slack Plugin required to send build notifications to Slack slack:2.27  然后,我们的 AMI provision 脚本解析该文件,用 Jenkins CLI 安装插件和所选版本:\n# Wrapper function for jenkins_cli jenkins_cli() { java -jar \u0026quot;$JENKINS_CLI_JAR\u0026quot; -http -auth \u0026quot;${user}:${pw}\u0026quot; \u0026quot;$@\u0026quot; }for plugin in \u0026quot;${plugins[@]}\u0026quot;; do echo \u0026quot;Installing $plugin\u0026quot; jenkins_cli install-plugin \u0026quot;$plugin\u0026quot; -deploy done  然后,任何需要安装的新插件或升级到当前安装版本的版本升级都需要 GitHub Pull Request,这会触发搭建新 AMI。完美!\n安装其他软件 根据定义,Jenkins 要安装很多软件才能创建、测试和部署。首先,我们不想让 master node 运行任何任务,所以我们避免安装任何与任务相关的软件。Master 的主要任务是在其他短暂 worker node 上提供界面、编排 builds。\n这意味着我们可以在 worker node 上安装所需工具,但我们决定尽可能多地使用 docker run。这是因为我们是使用 Scala、Java、Node、Golang、Python等其他编程语言的多语言组织。为所有这些软件栈维护不同 build 工具可能让 worker node 设置变得有点儿复杂。\n以 JavaScript 为例,我们想让 Jenkins 针对 install 和 test 等 app 运行 yarn 命令。简单将加载检查过的 repo 目录作为一个 volume 安装到 Docker 容器里,从该容器中运行任何命令。以下为运用 Groovy 工作流代码的例子:\ndef node(command, image) { def nodeCmd = [ 'docker run -i --rm', '-u 1000', // Run as non-root user '-v ~/.npmrc:/home/node/.npmrc:ro', '-v ~/.yarn:/home/node/.yarn', '-e YARN_CACHE_FOLDER=/home/node/.yarn/cache', \u0026quot;-v ${env.WORKSPACE}:/app\u0026quot;, '--workdir /app', \u0026quot;${image}\u0026quot; ].join(' ') sh \u0026quot;${nodeCmd} ${command}\u0026quot; }  然后,我们检查仓库后可以调用这个功能:\ncheckout scm node('yarn install --frozen-lockfile', 'node:12.6.0-alpine')  漂亮收尾!因为除了 Docker 后台程序或 kubectl,我们不必在 worker machine 上安装、维护所用工具的多个版本。我们也相信 build 命令在本地和 CI 环境之间是一致的,因为用的是同一个 Docker 镜像。\n运用临时 node 创建时要记得缓存依赖。比如,一个 worker node 重建后,我们丢失了 sbt 缓存,由于缓存必须重建,这导致创建时间变慢。如果外部依赖不可用,这甚至会导致失败。我们决定将相关依赖缓存在另一个外部 EFS 上,以求获得更快、更可靠的 build。\n结语 Jenkins 是一个很棒的工具,但在管理外部状态上略有不足,因此以 cloud native 的方式创建 Jenkins 较有难度。我们的方法并不完美,但我们相信这个方法结合了两者的精华,而且确保安全性、操作简单、有弹性。令人高兴的是,我们完成这个项目,并把所有的生产 build 迁移到新的 Jenkins 服务之后,可以终止 master server,让自动缩放在几分钟内完成重建,而不会影响以前储存的状态。\n",
        "auhtor": "Alberto Alvarez",
        "translator": "shunw",
        "original": "https://medium.com/bench-engineering/cloud-native-jenkins-on-aws-b5c957c4fe18",
        "poster": "butler-in-action.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
716 717
    },
    {
718
        "uri": "https://jenkins-zh.cn/meeting/2019-08-21/",
719 720 721
        "title": "",
        "type": "meeting",
        "date": "2019-08-21 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
722 723
        "tags": [],
        "description": "",
724
        "content": " 社区治理  对于微信群里设置一个投诉机制,对于符合一定条件的,把被投诉的人移出 @linuxsuren  在公众号后台或者邮件(admin at jenkins-zh.cn)发送投诉,写明被投诉人和理由 @linuxsuren 可以先和被投诉人进行私下沟通,如果不改正的话,就执行移除 @Shunw19  在公众号里发起一个投票,调研大家对公众号文章类型,质量的看法以及建议 @linuxsuren  文章类型:技术类、志愿者等活动类  考虑定期发起志愿者招募,例如在寒暑假之前 @linuxsuren  需要的人数 @Shunw19  分布在多个城市  如何组织 @linuxsuren  尽量明确任务 区分社区志愿、活动志愿者 @baobeizuoshoubuli  把完成志愿任务的人,在官网展示出来 @linuxsuren  给公众号加个目录分类,检索 @Shunw19  可以通过关键字检索  贡献者采访 @linuxsuren  口语比较好的来协作采访国外的贡献者 需要出一些稿子(中文、英文)   线下活动 北京  黑客松\n 活动报名已经启动 需要把活动宣传工作做好  开源人线下见面会 8月24日\n  教程 https://jenkins-zh.cn/tutorial/\n",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
725 726 727 728 729 730
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
731
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-19-hackathon-signup/",
732 733 734
        "title": "开源持续交付黑客松,5000大奖等你来拿",
        "type": "wechat",
        "date": "2019-08-19 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
735
        "tags": [],
736 737 738
        "description": "黑客松编程比赛开启报名,巅峰对决,等你来战!",
        "content": " 你是否希望与顶尖编程高手同场较量,是否想体验创意与技术的碰撞?黑客松编程比赛释放你的激情,满足冠军梦想。\n黑客松编程比赛报名正式拉开帷幕。本次赛事以 DevOps 为主题集结研发、测试、运维、产品、文档、HR等各路人马,秉承开源开放的方式,旨在为各个行业面临的 IT 挑战提出解决方案,鼓励人人参与开源社区,展现开源之魅力。\n本次比赛为期两天,由 Jenkins 中文社区联手 CloudBees、京东云、阿里云、码云、开源社和微软组织承办。选手要在48小时内根据所选议题设计解决方案,在有限的时间内激发无限创意想法。\n比赛规则  活动中创建的新代码仓库均在码云上的 Jenkins 中文社区进行托管,任何人都可以根据对应开源协议进行修改、分发等操作。 所有代码工作(包括文档、设计等)必须当场完成。若提前准备或抄袭,一经发现,将取消当年及次年的比赛资格。 所有项目必须可以做到持续构建,持续交付和灰度发布则为加分项。 推荐与不同技能的小伙伴组建3人左右的团队,一起完成项目。  评选标准 团队协作、完整性、创新程度、难易程度、大众评分\n报名方式 本次比赛通过第三方平台“活动行”进行线上报名。组团报名满3人可享9折优惠,欢迎公司组团报名。 请点击开源持续交付黑客松或扫描下列二维码报名参赛。\n报名说明 选手须年满十八周岁且熟练使用码云。需要注意的是,报名者选定项目提议后,在报名时必须提供与所选项目相关且于活动发布后合并了的 PR 链接,我们将根据该链接决定是否通过报名。\n报名成功后,选手需给出明确项目提议,即有待完成的具体功能列表和需要修复的缺陷列表等。请注意,只有审核通过的项目提议可以在最后的线下活动继续比赛。\n上述流程必须在报名截止日期9月30日之前完成。后续通知可通过关注 Jenkins公众号获得。如果你对 Jenkins 技术交流感兴趣,可以在公众号后台回复“社区活动”来加入我们的微信群。\n奖项设置  冠军项目,5000元 亚军项目,2000元 入围项目,500*2元  项目提议  Kubernetes 插件优化  所需技能:Kubernetes、Java  Jenkins 中文社区网站改版  所需技能:Hugo、Markdown、JavaScript、CSS  Jenkins 命令行工具 jcli  所需技能:Golang、Jenkins API  Jenkins 微信公众号后端服务  所需技能:Golang、微信公众号 API  Jenkins Java 语言客户端  所需技能:Java、Jenkins API  微信机器人  所需技能:JavaScript   ",
        "auhtor": "shunw",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
739 740
        "translator": "",
        "original": "",
741
        "poster": "hackathon-poster.jpg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
742 743
    },
    {
744
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-17-award/",
745 746 747
        "title": "提名 Jenkins 中文社区激励候选人",
        "type": "wechat",
        "date": "2019-08-17 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
748
        "tags": [],
749 750 751
        "description": "Jenkins 中文社区贡献激励活动",
        "content": " Jenkins 中文社区是由 Jenkins 国内的爱好者、贡献者组成,共同推广以及完善 CI/CD 技术的学习试用和落地。我们非常欢迎每一位同学为社区贡献自己的一份力量,相应的我们会给予杰出贡献者奖励以表示认可和感谢,同时也欢迎更多对社区活动感兴趣的同学加入! 社区贡献激励是一个旨在长期为社区贡献者谋福利的活动,因此社区每三个月就会举办一次激励活动,惊不惊喜,激不激动! 第一期激励活动已经圆满落下帷幕,让我们再次恭喜三位明星贡献者——donhui,zacker330,yJunS,感谢三位对社区做出的杰出贡献,此处应该有掌声!!\nHold on!! 没有赶上第一期活动的同学们,请往这里看——第二期激励投票活动马上开始了,在这个炎热的夏天,让我们一起行动起来吧!\n评选规则: 社区秉承公平、公正、公开的原则,希望每位社区贡献者都有机会参与评选,本次活动将采取邮件征集投票的方式,选出本期社区突出贡献者\n参评标准:  翻译 Jenkins 相关文章 Jenkins 中文本地化 发表 Jenkins 原创文章 Review PR 在 Jenkins 中文社区有开源贡献(eg: 提交新的特性代码,提交补丁优化代码,撰写和改进项目的文档 etc.) 积极参与 Issue 的讨论,如答疑解惑、提供想法或报告无法解决的错误 组织社区活动 Meet up 其他重大贡献  投票规则:  请各位同学请选出心目中最佳贡献者,发送邮件至 admin@jenkins-zh.cn 可以推荐一位或者多位候选人 请在邮件正文中标注推荐的候选人信息:  GitHub ID 微信号 推荐理由(理由要切实与本社区相关的哟,不要因为小哥哥小姐姐太好看就给投票哈)  邮件投票截止时间2019年8月28日23点59分——我们会在社区的例会上对从邮件中征集的候选人进行公开投票,最终选出五位最佳贡献者给予奖励(从直接参与社区贡献的人中挑选四位,从社区技术群积极帮助他人的人中挑选一位) 贡献激励: 加入 Jenkins 社区贡献者名单,并展现在 Jenkins 中文社区官网——获得由与社区合作的人民邮电出版社提供的技术书籍 有机会成为线下技术沙龙特邀嘉宾   相关说明: 评选结果将在 “Jenkins 官方微信公众号”进行公布——合作的出版社将直接邮寄奖品。\n激励让社区活动更加有趣,让我们一起构建伟大,无所不能。还不快快行动,让更多的人因为你的贡献打开通往新世界的大门!\n",
        "auhtor": "shuimujiazi",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
752 753
        "translator": "",
        "original": "",
754
        "poster": "eagle.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
755 756
    },
    {
757
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-16-tutor-recruitment/",
758 759 760 761 762 763 764
        "title": "持续交付黑客松--导师招募",
        "type": "wechat",
        "date": "2019-08-16 00:00:00 +0000 UTC",
        "tags": ["黑客松", "导师", "招募"],
        "description": "持续交付黑客松导师招募",
        "content": "  Jenkins 中文社区计划于2019年10月25日发起一场以 DevOps 为主题的黑客松编程比赛,我们将以开源、开放的方式策划、组织本次活动。开源\u0026ndash;黑客松上产生的所有代码、文档甚至想法都是开源的,都会托管在国内最大的代码托管网站\u0026ndash;码云上。开放\u0026ndash;任何岗位、背景的人都可以参与我们的活动,不仅仅只有研发、测试、运维等岗位的同学,我们非常欢迎文档工程师、产品经理、敏捷教练的加入,甚至 HR、PR 的同学也可以来参与。\n 集结这么多具有不同技能的同学后,我们希望能解决什么问题呢?我们希望让大家切实地体会到,参与开源并没有你想的那么困难、无趣,也绝不仅仅只有键盘侠的 Coding 独秀,人人都可以参与开源社区。通过开源社区可以集中解决很多通用性的问题,通过开源的黑客松活动,更是可以集中地解决我们在使用开源的持续交付方案中遇到的诸多通点。\n主办方  Jenkins 中文社区  合作方  CloudBees 码云 京东云 开源社 微软  导师招募 如果你在 - Java、JavaScript、Golang、css、Hugo - K8S 、Jenkins、Jenkins API - CI/CD、敏捷等 DevOps\n等相关领域有丰富的经验、独到的见解,包括且不限于以上领域,欢迎踊跃报名成为黑客松活动的导师。我们会认真、仔细地筛选符合条件的报名者。\n我们热切期盼你的到来,指导参赛队取得好成绩!\n 要求导师在某个领域工作至少5年以上\n 报名方式 发送邮件到event@jenkins-zh.cn,内容如下,请如实填写(注: GitHub ID 示例:https://github.com/githubId):\n活动名称: 姓名: 公司名称: 所在地: 部门: 职务: 联系电话: 微信号: GitHub ID: T 恤尺码: 个人简介(若您被选中导师,以下信息将发布在网站及海报上,请仔细填写):如工作经验、是否带过团队等信息 技术指导方向:参考项目提议选择指导方向 是否指导过黑客松比赛:  导师相关义务  积极配合议题的评审工作,以确保解决方案的高质量 比赛期间(10.25晚-10.27晚),请与指导团队准时到达比赛现场 协助活动组织者在微信等宣传渠道宣传本次活动 比赛结束后分享比赛心得及经验  你将获得  收获业内同行间最有价值的碰撞结果 K8S、Jenkins、Docker 等先进工具最佳实践案例 DevOps 、敏捷等方法的实际落地法 建立同行业人脉关系 树立个人行业影响力 为您的团队招揽精英  ",
        "auhtor": "linan607",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
765 766
        "translator": "",
        "original": "",
767
        "poster": "./2019-08-16-tutor-recruitment/tutor.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
768 769
    },
    {
770
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-15-jenkins-pipeline-stage-result-visualization-improvements/",
771 772 773 774 775
        "title": "Jenkins 可视化阶段视图的改进",
        "type": "wechat",
        "date": "2019-08-15 00:00:00 +0000 UTC",
        "tags": ["pipeline", "blueocean"],
        "description": "流水线除了成功或失败以外,还有一种介于两者之间的状态",
776
        "content": " 最近发布了的一些变更给了流水线编辑者新的工具以改善在 Blue Ocean 中的流水线可视化,有一个备受瞩目关注的工单JENKINS-39203,这会导致当流水线的构建结果为不稳定时所有的阶段都被设置为不稳定的。这个缺陷导致无法快速地识别为什么构建是不稳定的,使得用户必须查看完整的日志和 Jenkinsfile 才能弄明白究竟发生了什么。\n为了修复这个问题,我们引入了一个新的流水线 API 用于为单个流水线步骤添加额外的结果信息。像 Blue Ocean 这样的可视化工具在决定阶段如何显示时会使用到这新的 API。像 junit 这样的步骤只能设置整个构建结果,现在可以通过新的 API 设置步骤级别的结果信息。我们创建了新的步骤 unstable 和 warnError,这样流水线编辑者在更复杂的场景下仍然可以利用这个新的 API。\n该问题涉及到的重要的修复包含在如下的插件中,它们都需要 Jenkins 2.138.4 以及更新的版本:\n Pipeline: API 2.34 Pipeline: Basic Steps 2.18 (需要同步更新到 Pipeline: Groovy 2.70) Pipeline: Graph Analysis 1.10 Pipeline: Declarative 1.3.9 Blue Ocean 1.17.0  这里是一条使用了 unstable 步骤的流水线在 Blue Ocean 中的截图,只会把失败的阶段标识为不稳定的:\n例子 这里给出一些如何在你的流水线中使用该特性的示例:\n 使用新的步骤 warnError 用于捕获错误,并把构建和阶段标记为不稳定的。 warnError 只需要一个 字符串 的参数,用于当捕获到错误时以日志的形式输出。当 warnError 捕获到一个错误时,它会记录该消息以及错误,并设置构建和阶段的结果为不稳定的。效果如下:  warnError('Script failed!') { sh('false') }   使用新的步骤 unstable 设置构建和阶段结果为不稳定的。可以使用该步骤直接替换 currentBuild.result = 'UNSTABLE',在 warnError 不够灵活时这会比较有用。步骤 unstable 只需要一个 字符串 参数,当该步骤运行时会作为消息。使用的方法如下:  try { sh('false') } catch (ex) { unstable('Script failed!') }   JUnit Plugin: 更新到 1.28 或者更高的版本,使得步骤 junit 可以直接把该阶段设置为不稳定的。 Warnings Next Generation Plugin: 更新到 5.2.0 或者更高的版本,使得步骤 publishIssues 和 recordIssues 可以直接把该阶段设置为不稳定的。 其他插件: 如果你的流水线被其他插件中的步骤标记为不稳定的,请(在检查没有重复项后)给该组件提交一个新的 issue,清晰地描述哪个步骤是有问题的,以及发生问题的环境,并添加链接到该文章的开发者区域,以便维护者了解如何才能解决该问题。  局限  如果你不迁移到 unstable 或 warnError 步骤,或不升级插件到集成来新 API 的情况下设置构建状态,那么即使构建是不稳定的,Blue Ocean 也不会把任何阶段显示为不稳定的。 即使在这些变化后,currentBuild.result 继续只会覆盖构建状态。不幸的是,由于 currentBuild 是作为全局变量而实现的,因此,无法让它设置步骤或者阶段级别的结果,这意味这它没有任何步骤级别的上下文可以使用到新的 API。 Pipeline Stage View Plugin 尚未升级到使用这个新的 API,因此,这些变更不会在它提供的可视化中得到体现。  历史 Jenkins 流水线步骤可以以两种方式完成:成功并返回一个结果(可能为 null),或者是失败的,并抛出一个异常。当步骤失败并抛出异常时,该异常会贯穿整个流水线,直到有其他的步骤或者 Groovy 代码捕获,或者它到达流水线的顶层并导致流水线失败。基于抛出的异常的不同类型,流水线最终的结果可能不是失败(例如:某些情况下是被终止的)。基于异常传播的方式,像 Blue Ocean 这样的工具可以轻松地识别哪些步骤(以及阶段)是失败的。\n为了能够让流水线能够与相应的 Jenkins API 交互,对于流水线构建来说,可以在构建期间修改构建结果也是有必要的。对于其他的,这使得流水线可以使用构建步骤以及原先出自于自由风格的任务中的项目。\n在一些情况下,一个流水线步骤需要能够成功地完成,以便流水线可以继续正常执行,但对此而言能够标记有某种错误发生,因此,在可视化时能够识别到发生错误的步骤,即使没有彻底失败。比较好的一个例子就是 junit 步骤。该步骤关注特定的测试结果,如果有任何错误,会把整个构建结果标记为不稳定的。这种行为对类似 BlueOcean 的可视化工具而言是有问题的,因为该步骤是成功的,而且无法通过编程的方式覆盖于该步骤相关的最终结果。\n再次查看下 JENKINS-39203,我们看到关于可视化有两项基本的选项。因为有的步骤导致构建变成不稳定的,设置总体的构建结果是不稳定的,或者所有的步骤都成功完成来也展示为不稳定的;或者由于我们没有办法把特定步骤相关的构建结果作设置,它们可能显示为成功的。最后,选择了第一个选项。\n为了解决该问题,部分用户尝试通过抛出异常并在阶段中增加 try/catch 这样的代码块用于处理异常,这样 Blue Ocean 能够借助这些异常来标记步骤和阶段的结果为期望的状态,而且,捕获异常后,流水线可以继续正常执行。这种方式不容易理解,脆弱,而且无法在申明式的流水线中使用。\n开发者 如果你是一个插件的开发者,并在集成流水线时使用了步骤,想要利用这个新的 API 的话,你的步骤就可以给出一个非成功的结果,而不是抛出异常。请查看 Jenkins 开发者邮件列表中的这个帖子,如果你遇到任何问题了,可以在那里提问。\n",
777 778 779 780
        "auhtor": "dwnusbaum",
        "translator": "linuxsuren",
        "original": "https://jenkins.io/blog/2019/07/05/jenkins-pipeline-stage-result-visualization-improvements/",
        "poster": "./superhero.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
781
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
782
    {
783
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-14-continuous-testing-what-why-and-how/",
784 785 786 787 788 789 790 791 792 793
        "title": "持续测试的那些事",
        "type": "wechat",
        "date": "2019-08-14 00:00:00 +0000 UTC",
        "tags": ["测试", "持续测试", "持续交付", "软件生命周期", "DevOps"],
        "description": "持续测试究竟是什么?你又如何实现它呢?",
        "content": " 敏捷,DevOps 和持续交付已然存在于现今每个技术人员的词汇当中。我们都想要像硅谷里的巨头和初创公司一样,敏捷开发,快速发布软件,做出创新的产品。 向敏捷转型在多方面都已有总结,并且到了能被顺利实践的程度。然而,测试仍然是一个有思想困惑和实践挑战的领域。 当软件发布周期从以年、月缩短到以周、天为单位,或者更短时; 我们该如何重塑测试实践,以保证当软件发布到生产环境时能令用户满意, 而不是掉链子?\n鉴于大多数 DevOps 实践仍然把测试视为软件生产中最令人头疼的瓶颈,显然,这是一个常见的挑战。\n持续测试就是答案,但持续测试究竟是什么?你又如何实现它呢? 维基百科定义持续测试为「在软件交付流水线中执行自动化测试的过程,目的是为了获得关于预发布软件业务风险的即时反馈」。 但是这个定义缺少了本质,缺少了持续测试所示意的转变的量纲。 除了自动化是一个重要的部分以外,持续测试从根本上转变了测试, 它把线性过程中的时间点事件嵌入到整个过程当中去,作为基础贯穿于整个软件交付周期的所有活动中。\n敏捷环境里持续测试的目标应该是「迭代内测试(in-sprint testing)」。 不管你的迭代是两周还是四周,目标都应该是完成迭代内所有类型的测试,这样每个迭代都可以得到一个测试完备的,准备交付的软件。 事实上很多持续交付的最佳实践都会告诉你,你不能简单的在没有持续测试的情况下去做持续交付。 如果你认为你的迭代时间不允许你去做一个综合的测试,很有可能是你对它的理解有误。\n七个步骤实现持续测试 1. 尽早规划测试,甚至早于写代码 描述不清的要求或者有不正确的理解,都可能导致返工甚至延期。 使用像行为驱动开发(BDD), 验收测试驱动开发(ATDD)和 基于模型的测试这类技术所使用的工具,如 cucumber/gherkin 和 CA Agile Requirements Designer (ARD), 可以确保业务主管,产品经理,开发人员和测试人员充分沟通并记录需求,定义清晰的测试用例,提早编写测试脚本,以达到一个流畅的测试过程。\n2. 优化测试覆盖率 一些组织默认「每次运行所有的测试」来保证代码覆盖率。这不但浪费资源还延长了测试周期,而且没有真正的保证代码覆盖率。 测试那些需要测试的部分,以节省时间、金钱和资源。可视化模型可以让各种路径被探索优化,以便只用少量的测试用例就能提供最大化的覆盖率。 可以借助 Rally, Jira, HP ALM, JIRA 等此类工具导入测试用例、移除重复用例、分发优化过的用例。\n3. 测试左移 为了实现「迭代内(in-sprint)」测试,将测试前置——这样测试可以在开发周期的早期运行。开发人员自己测自己的;卓越中心提供专家,定制系统和服务。 自动化测试覆盖 UI, 功能,性能和安全。各个团队一起工作,一起以要交付给客户的业务价值为专注点。这需要对开发者友好的工具以及文化转变。\n4. 提供完整的测试环境 提供测试环境的能力对实现持续测试是至关重要的。 通过友好型(例如编码、CI/CD 集成、被开源支持的软件)开发工具按照需求提供的完整的测试环境来消除障碍和减少等待时间。 这些环境应该包括:\n 虚拟服务——给那些不可达,不可访问的,还在开发中的服务提供鲁棒的模拟。开发和测试可以根据虚拟服务模拟实际服务返回的结果持续并行工作。 按照需求测试数据——帮助并保证各个团队可以使用与生产环境类似的数据来运行综合的测试。 预发环境——准备上线的需求,使用后退役。  5. 获取正确的测试数据 在很多应用发布周期,获取鲁棒性测试数据能力的缺乏会造成严重延期。为了准确的测试新功能,测试数据应该尽可能的跟生产环境时所应用遇到的数据相近。 如果测试数据缺乏特定真实世界的特征(例如具体字段、数据定义、负面场景等),测试就很难找到许多潜在问题和应用的弱点。 理解数据模型并提取出正确的数据是一种特殊的技巧。尽管使用生产环境数据测试是最接近真实的,但数据隐私条例通常都会限制使用生产数据。 下面,我们来看看 CA Test Data Manager 是如何复制生产数据,抹掉敏感信息的同时保持了测试所希望的生产数据特征(接近现实,并且多行指征完整)的。 生产数据不可用时,测试数据也可以使用 TDM 工具根据模版生成。\n6. 别忘了测试右移 测试向右移动,使用开发周期和生产中的数据来优化测试周期、调整测试用例,以建立最佳回归套装。右移技术包括真实用户监控、金丝雀部署、A/B 测试、混沌工程等。 例如,通过测试右移,你可以确定哪些功能被用于生产,保证回归测试覆盖能够这些功能。 同样的方法,你可以开放新功能给一小部分人(内部或外部),了解新功能可能给生产造成的影响,按需调整。 许多敏捷公司例如 Facebook 和 Netflix 都严重依赖测试右移。 Gartner(美国一家从事信息技术研究和顾问的公司)最近发布了一份测试右移的报告, 声称测试右移对 DevOps 实践来说是「必需」的。\n7. 使用数据矩阵持续优化 建立跨团队协作,根据可行性分析和反馈机制不断优化。持续交付和持续测试就像旅行。确保你的所有团队都有 KPI, 查阅那些能够提供附加优化的数据。 不要只是收集数据,那很容易办到,收集并且总结数据能够帮助你提出持续优化的确切建议。探索应用发布流程以实施建议,并作为所有团队应用交付周期的「单一事实来源」。\n要了解更多关于持续测试的挑战和实践,点击这里 CT Academy Video Series.\n",
        "auhtor": "Sushil Kumar",
        "translator": "tomatofrommars",
        "original": "https://dzone.com/articles/continuous-testing-what-why-and-how",
        "poster": "./2019-08-14-continuous-testing-what-why-and-how/test_automation.jpg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
794 795
    },
    {
796
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-09-volunteer-recruitment/",
797 798 799 800 801 802 803
        "title": "持续交付黑客松--志愿者招募",
        "type": "wechat",
        "date": "2019-08-09 00:00:00 +0000 UTC",
        "tags": ["黑客松", "志愿者", "招募"],
        "description": "持续交付黑客松志愿者招募",
        "content": "  Jenkins 中文社区计划于2019年10月25日发起一场以 DevOps 为主题的黑客松编程比赛,我们将会以开源、开放的方式策划、组织本次活动。开源——黑客松上产生的所有代码、文档甚至想法都会是开源的,都会托管在国内最大的代码托管网站——码云上。开放——任何岗位、背景的人都可以参与我们的活动,不仅仅只有研发、测试、运维等岗位的同学,我们非常欢迎文档工程师、产品经理、敏捷教练的加入,甚至 HR、PR 的同学也可以来参与。\n 集结这么多具有不同技能的同学后,我们希望能解决什么问题呢?我们希望让大家切实地体会到,参与开源并没有你想的那么困难、无趣,也绝不仅仅是只有键盘侠的 Coding 独秀,人人都可以参与开源社区。并且,通过开源社区可以集中地解决很多通用性的问题,通过开源的黑客松活动,更是可以集中地解决我们在使用开源的持续交付方案时遇到的诸多痛点。\n主办方  Jenkins 中文社区  合作方  CloudBees 码云 开源社 微软  志愿者招募 如有意愿参与黑客松活动,欢迎踊跃报名。我们会认真、仔细地筛选符合条件的报名者。\n报名方式 发送邮件到event@jenkins-zh.cn,内容如下,请如实填写(注: GitHub ID 示例:https://github.com/githubId):\n活动名称: 姓名: 公司名称(选填): 所在地: 职业: 联系电话: 微信号: GitHub ID: T 恤尺码: 个人擅长: 参加志愿者的初衷:  志愿者职责划分  文案、宣传 拍照/摄像 签到、场地布置 场地秩序维护、活动事项解答、物品库存管理等  志愿者职责说明 依据不同志愿者的职责分工,志愿者需提前对自己对职责做一个大概对计划表,提前与社区活动相关负责人员相互沟通,尽量减少在活动中遇到突发事件对情况以及对可能遇到突发事件的情况做好应对方案。\n志愿者福利 我们会根据志愿者的实际参与情况,给予志愿者相应福利: * 免费参加自本活动启动时一年内的所有活动 * 活动纪念品 * 赠送与本社区有合作关系的其他公司或者社区组织的活动门票\n",
        "auhtor": "yJunS",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
804 805
        "translator": "",
        "original": "",
806
        "poster": "./2019-08-09-volunteer-recruitment/needyou.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
807 808
    },
    {
809
        "uri": "https://jenkins-zh.cn/meeting/2019-08-08/",
810 811 812
        "title": "",
        "type": "meeting",
        "date": "2019-08-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
813 814
        "tags": [],
        "description": "",
815
        "content": " 线下活动 上海  开源基础设施峰会2019 11月4-6日  https://www.openstack.cn/  开源年会 11月2-3日  https://www.bagevent.com/event/5518928?bag_track=bagevent  meetup 9月21/22日  场地(赵晓杰) 讲师,三名(需要征集一名) 活动宣传稿(高嵘) 礼品(空缺)   北京  黑客松  门票价格,早鸟票,标准票,晚鸟票  100,120,150  志愿者(彦军) 设备,摄像等 视频剪辑(王顺) vs-code  服务器的配置要求?   开源人线下见面会 8月24日  成员招募 明天拉个群\n教程 https://jenkins-zh.cn/tutorial/\n",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
816 817 818 819 820 821
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
822
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-08-jenkins-x-new-logo/",
823
        "title": "Jenkins X 新 logo",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
824
        "type": "wechat",
825 826 827 828 829 830 831 832
        "date": "2019-08-08 00:00:00 +0000 UTC",
        "tags": ["jenkins x"],
        "description": "Jenkins X 推出新 logo",
        "content": " 早在2018年3月,Jenkins X 项目作为 Kubernetes 自动化 CI/CD 的 Jenkins 对应项目突然出现。作为这次发行的一部分,它的 logo 是 Jenkins logo 的一个变种,一个叼着烟斗的船长,他的帽子上有 Kubernetes logo。\n在软件中,我们喜欢说命名是困难的——因为确实如此。另一件同样困难的事情是试图在 logo 中捕捉项目的本质。Logo 在一个小空间里有很多意义。Icon ,例如 Jenkins logo,与许多开发人员建立强烈的情感联系。因此,考虑到这一点,我们总是密切听取有关新 logo 的反馈,以及人们如何看待这个项目。\n为什么我们要改变 logo 在听取各种不同来源的各种反馈时,我们听到了许多积极的事情,但也强调了一些问题和困惑。\n 并不是每个人都喜欢这个 logo,我们听到了不少关于人们不喜欢它的方面的反馈意见,其中“叼着烟斗”这个反馈意见排在最前面。 与 Jenkins 项目的混淆——我们也看到这个 logo 与 Jenkins 的其他吉祥物更加一致,这导致了关于 Jenkins X 是什么类型的项目的混淆——一些人认为这是生态系统中的另一个插件。 我们还听说,使用 Kubernetes logo 令人困惑,或可能并非完全在 Kubernetes logo 指南的范围内。 从实用的角度来看,我们也听说这个 logo 太详细了,因此不能很好地作为一个 icon,尤其是一个 favicon。它被看作是吉祥物而不是 logo。  随着持续交付基金会的成立,Jenkins X 是基金会创始项目之一,区别于 Jenkins,我们觉得是时候处理这个反馈了。所以我们真的回到了画板上,思考什么样的 logo 可以更好地代表 Jenkins X 作为一个项目。我们考虑了我们希望人们与项目相关联的内容:开源、持续交付、速度、自动化、稳定性、团队等等。我们也想要一个 logo,可以提高代表性,所以我们想要避免一个基于人的 logo,它可能会无意间编码性别、年龄和其他因素。此外,“X” 已经成为项目 logo 的一个独特部分,所以我们想在新 logo 中真正强调它。\n设计新 logo 和社区反馈 最终,我们专注于尝试可视化速度和自动化,这导致了机器人的想法。但是,我们仍然希望以某种方式向 logo 中的原始 Jenkins 项目表示致敬。我们明确决定不坚持传统上与 Kubernetes 和相关项目相关的航海主题。我们经历了几次迭代,精炼并减少细节。设计工作与 Linux 基金会创意总监 Craig Ross 及其团队密切合作,他们还制作了持续交付基金会,CNCF,Network Service Mesh 和 Tekton 品牌。\n在核心 Jenkins X 团队确定他们满意的设计之后,我们将其带到社区以获得反馈并解决一些细节问题。我们有很多反馈,包括它让人们想起的所有事情(一个颠倒的考拉,Bill Nye,Reddit logo,Flash Gordon,Tekton logo 等)。最初的设计有一个始终如一的主题,那就是它没有反映出社区的友好性。Kyounger 特别帮助分析了这一反馈,并加倍努力提出解决方案。我们同意并喜欢这个建议,并将其反馈到 logo 的最终版本中。非常感谢 Kenny 和开源 FTW!\nJenkins 和 Jenkins X Jenkins X 最初是 Jenkins 子项目,现在是持续交付基金会(CDF)的一个独立项目。新 logo 中的领结时刻提醒着人们它的出处。尽管我们的 logo 和品牌可能会发生变化,但在 CDF 的庇护下,我们将继续与 Jenkins 项目紧密合作,为开发人员的 CI/CD 和生产力需求共享相同的服务精神。\n推出新 logo 我们现在已经开始切换到新的 logo,并期待看到一些新的 swag 很快可用。我们现在将把旧的 logo 作为 Jenkins X 项目的吉祥物。如果您希望更新使用的 logo,新的艺术品在这里。\n这对项目来说是一个很大的改变,但最终我们投入这么多时间和精力的原因是,这对我们来说很重要,我们在做的每件事中都代表着 Jenkins X 的精神。所以当你使用 Jenkins X 的时候,当你看到新 logo 的时候,我们想让你感觉到开放友好的社区的一部分,我们想让你的团队专注于你真正想要关注的事情:以任何速度和规模交付高质量的软件。\n",
        "auhtor": "tracymiranda",
        "translator": "donhui",
        "original": "https://jenkins-x.io/news/new-logo-jenkins-x/",
        "poster": "./2019-08-08-jenkins-x-new-logo/jenkinsx-stacked-color.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
833 834
    },
    {
835
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-07-hackathon-startup/",
836 837 838 839 840 841 842
        "title": "开源持续交付黑客松--号角声起",
        "type": "wechat",
        "date": "2019-08-07 00:00:00 +0000 UTC",
        "tags": ["黑客松"],
        "description": "给你48小时,可以持续交付多少创意呢?",
        "content": "  Jenkins 中文社区计划于2019年10月25日发起一场以 DevOps 为主题的开源黑客松编程比赛,该活动旨在为当下金融、能源、政务、交通等场景面临的 IT 挑战提出解决方案,我们希望本次赛事期间您也能够收获业内同行间最有价值的碰撞成果。\n 本次活动由 Jenkins 中文社区主办,并由受到 Cloudbees、码云、京东云以及开源社等合作伙伴的大力支持。我们非常欢迎关心和关注开源以及持续交付的企业以及社区加入或者支持我们。有意与我们合作,可以在 Jenkins 公众号后台回复,或者发送电子邮件到 admin@jenkins-zh.cn。\n比赛规则 活动中创建的新代码仓库,都会托管在 Jenkins 中文社区托管在码云上的组织下 。因此,任何人都可以根据对应的开源协议进行修改、分发等。\n 所有的代码(或文档、设计等)工作,必须在现场完成,如有发现提前准备或者抄袭者,将会被取消当年以及次年的比赛资格 所有项目必须可以做到持续构建,能做到持续交付、灰度发布的项目可以加分 推荐与不同技能的小伙伴组成3人左右的团队,一起完成项目  评选标准:团队协作、完整性、创新、难度、大众评分\n报名说明 年满十八周即可报名参加,鉴于我们的所有项目都会托管在码云上,因此,参赛者必须能够熟练地使用码云。而为了能够证明你能够完成本次活动中的项目,当你从下面的项目提议中选定一个后,在报名时必须提供一个与你所选项目相关的、自本活动发布后的、已经合并了的 PR 链接,我们会根据该 PR 链接来决定你的报名是否可以通过。\n报名成功后,需要给出明确的项目提议——要做的具体功能列表、修复的缺陷列表等。请注意,只有审核通过的项目提议才可以在最后的线下活动中继续参加比赛。\n上述过程必须在“报名截止”之前完成。具体报名方式,请关注 Jenkins 公众号后续的通知,或者在 Jenkins 公众号后台回复“社区活动”后加入我们的微信群。\n项目提议  Kubernetes 插件优化  所需技能:Kubernetes、Java  Jenkins 中文社区网站改版  所需技能:Hugo、Markdown、JavaScript、CSS  Jenkins 命令行工具 jcli  所需技能:Golang、Jenkins API  Jenkins 微信公众号后端服务  所需技能:Golang、微信公众号 API  Jenkins Java 语言客户端  所需技能:Java、Jenkins API  微信机器人  所需技能:JavaScript   奖项设置  悬赏项目(1~2个) 冠军项目(1个) 亚军项目(2个) 入围项目(若干)  活动安排  8月1日~8月31日  议题征集  9月30日  报名截止  10月25日~10月27日  比赛时间(以下为比赛日的时间)  10月25日(周五)晚上七点~八点  签到  10月25日(周五)晚上八点~九点  比赛动员宣讲  10月25日(周五)晚上九点~10月27日(周日)下午四点  持续创作  10月27日(周日)下午四点~晚上七点  作品评选  10月27日(周日)晚上七点~晚上八点  颁奖仪式   ",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
843 844
        "translator": "",
        "original": "",
845
        "poster": "hackthon.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
846 847
    },
    {
848
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/08/2019-08-05-jenkins-multi-branch-pipeline/",
849
        "title": "在大型企业里维护多分支流水线",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
850
        "type": "wechat",
851 852 853 854 855 856 857 858
        "date": "2019-08-05 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "multi-branch", "Pipeline", "remote-file"],
        "description": "如果没有适当的解决方案,在大型企业可能难以创建和维护多分支流水线",
        "content": " Jenkins 是 DevOps 领域里非常好的 CI/CD 工具,它凭借其独特的功能,几乎可以满足你一切的的业务要求。其中一个独特的功能是多分支流水线(Multi-branch 流水线),可以动态配置流水线。但是,随着公司的发展,单独的多分支流水线并不能完全满足你的所有需求,特别是在涉及大型企业时,你需要考虑流水线的集中管理,治理,稳定性,限制和安全性等其他事项。因此对于具有 Jenkins 流水线的大规模 CI/CD 环境,你需要添加之前没有想到的更多功能。\n动态配置流水线 当一个开发人员创建一个新分支并将其推送到远程代码仓库时,Jenkins 会为这个新分支动态创建流水线。根据代码仓库,甚至也可以作为动态创建 Pull Request 流水线。这个动态功能在使用 Feature 分支或其他类似功能的团队中非常有用,由于本文的主题不是多分支流水线,你可以在端到端多分支流水线项目创建中找到详细信息和一些示例。\n流水线即代码 在多分支流水线中,脚本存储在项目代码仓库中,这就是“流水线即代码”的概念。此外,当你拥有小型开发人员团队或项目没有大量分支时,它非常有用。这样,开发人员可以根据需要更改流水线,将更改推送到分支,并立即看到更改生效,但对于拥有数百或数千名拥有大量项目的开发人员的大型企业而言,这种方案就完成不可行了。\n集中式库 当你的团队或项目增加时,是时候考虑一种方法,比如通过共享的的方式应该在所有项目中。从长远来看,这种“集中式库”变得非常关键,因为随着规模的扩大,流水线中出现了新的要求或变化,在这种情况下,手动更改每个流水线或脚本对管理员来说将是一场噩梦。因此,如果你在一个地方进行更改并且每个流水线都得到更新,那么拥有该集中式库将更加实用。这是 Jenkins 共享库概念的用武之地。有关详细信息,你可以访问该站点。\n即使你只有一个流水线,仍然可以使用集中式库。\n治理与稳定 如果你的团队有对 CI/CD 一定了解的开发人员,并且你确信他们不会做出重大更改或编写脚本错误导致影响环境的稳定性,那么将流水线脚本放在代码中是很好的。但是,你真的确定吗?\n有人很可能会意外删除流水线文件或者可能出现小错误,这些小错误都会影响 CI/CD 的稳定性。如果你在早期发现这些错误时很容易解决这些错误,如果没有,这些微小的变化或错误将可能比你想象的更严重的影响 CI/CD,它将被传播到不同项目中的所有分支或 tag,这会变得很难解决。\n你需要将正确的流水线脚本推送到所有分支和/或代码仓库,或是要求每个开发人员提取最新的脚本,这种类型的问题集中式库这种更高级的方式来解决,除此之外,你的环境会因为有人可能会删除 Jenkins 文件或输入一些拼写错误带来风险。\n远程文件插件 为了消除不必要的更改的风险并降低使用的库的复杂性,我们需要以某种方式将流水线脚本与项目/代码代码仓库分开,同时仍继续使用多分支流水线功能。为此,我们有远程文件插件。\n这个插件使多分支流水线能够从其他代码仓库运行/加载流水线脚本,而不是将它们放在项目/代码代码仓库中,通过这个功能,你可以拥有一个单独的代码仓库,你可以在其中放置所有流水线脚本,并且只能为你自己提供访问权限。这样,你将拥有与集中式库相同的集中式流水线脚本代码仓库。此外,你可以将流水线脚本存储在集中式库本身中。\n这个功能的好处是除了有访问权限的人之外,没有人能够在流水线脚本中进行更改。你在集中流水线脚本中所做的任何更改都将影响使用该脚本文件的所有多分支流水线。这样,你无需等待所有开发人员获取更新版本或将脚本推送到所有代码仓库上的所有分支。\n另一个好处是,如果你将集中式流水线脚本放入 BitBucket 或 GitHub 等代码仓库中,你还将拥有代码审查功能。这样,你可以与其他人共享代码仓库,同时仍可限制或查看其他人所做的更改。\n结论 在大型企业中创建 CI/CD 流水线并不容易,你需要考虑治理,限制,稳定性和安全性等概念。在此上下文中,借助 Jenkins 的其他功能,Remote File Plugin 提供了一个独特的功能,用于集中,维护和共享流水线脚本。\n有关插件的详细信息,你可以访问插件的 Wiki 页面。\n",
        "auhtor": "Aytunc BEKEN",
        "translator": "shenxianpeng",
        "original": "https://dzone.com/articles/maintaining-multi-branch-pipelines-in-large-scale",
        "poster": "./2019-08-05-jenkins-multi-branch-pipeline/cover.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
859 860
    },
    {
861
        "uri": "https://jenkins-zh.cn/about/volunteer-part-in/",
862 863 864
        "title": "活动志愿者报名",
        "type": "about",
        "date": "2019-08-05 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
865
        "tags": [],
866 867 868
        "description": "社区活动志愿者报名",
        "content": "  Jenkins 中文社区将不定期举行一些活动,志愿者的参与是不可或缺的。希望有更多的小伙伴可以通过志愿者的身份参与进来\n 如何报名 以邮件的形式发送到志愿者申请 內容如下(注: Github ID 示例:https://github.com/githubId):\n活动名称: 姓名: 公司名称(选填): 所在地: 职业: 联系电话: 微信号: Github ID: 个人擅长: 参加志愿者的初衷:  志愿者福利:  免费参加自本活动启动时一年内的所有活动 活动纪念品(小型活动没有纪念品) 赠送与本社区有合作关系的其他公司或者社区组织的活动门票  申明  欢迎小伙伴们报名志愿者,并且为志愿者准备了一些社区福利。但为了避免有人浑水摸鱼的事情发生,我们会根据实际参与情况以及参与活动的态度积极性来评判是否拥有志愿者福利的待遇。  ",
        "auhtor": "yJunS",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
869 870 871 872
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
873
    {
874
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-31-pipeline-config-history-plugin/",
875
        "title": "Jenkins 流水线配置历史插件介绍",
LinuxSuRen's avatar
LinuxSuRen 已提交
876
        "type": "wechat",
877 878 879 880 881 882 883 884
        "date": "2019-07-31 00:00:00 +0000 UTC",
        "tags": ["pipeline", "plugins", "jenkins"],
        "description": "Jenkins 流水线配置历史插件,让流水线变更可追溯",
        "content": " 流水线是在 Jenkins 中创建任务的有效的和现代的方式。 为了快速、简单地识别流水线变更,我们开发了流水线配置历史插件。 这个插件检测流水线的变更,并为用户提供一个选项,以明显地、可追溯地查看流水线配置两次构建(差异)之间的变更。\n一切是如何开始的 这一切开始于十年之前 —— 经典的任务类型 (例如:自由风格、Maven 等等)。 每隔一段时间,用户就会联系我们,因为他们的任务无法在一夜之间完成。 为什么这个任务失败了呢? 这次失败和任务配置变更有关系吗? 用户典型的回答是:\u0026rdquo;我们没有改任何东西\u0026rdquo;,但这是真的吗? 我们思考了这个问题,并决定开发一个插件来帮助我们解决这个问题。 这就是plugin:jobConfigHistory[任务配置历史]的想法和开始。\n现在可以查看任务配置的变更(例如其他分支、JDK版本等),而且更常见的情况是,破坏构建的原因是任务配置的变更。\n多年来,该插件得到了开发,目前仍在开发中。 添加了新的功能,不仅可以查看任务配置,还可以查看全局和代理配置的变更。 还可以恢复旧的配置版本。 如今,这个插件已经有超过30,000次安装量。 多年来,JobConfigHistory 减轻了我们的日常工作 —— 我们有超过3000个 Jenkins 任务! 然后出现了一种新的任务类型:流水线。\n流水线 —— 需要一些新的东西 流水线任务和经典的任务类型有根本地区别。 经典的任务类型是通过 Jenkins GUI 配置的,而流水线任务是配置即代码。 实际上,每个流水线任务都是通过 Jenkins GUI 创建的,然而这并不一定是流水线配置的位置。 流水线可以被配置:\n 直接在 Jenkins 任务中作为脚本。 代码将直接插入任务配置页面。 作为源代码管理系统(SCM)中的 Jenkinsfile:流水线配置在 SCM 中的文本文件(Jenkinsfile)中定义。 在任务本身中,只配置了 Jenkinsfile 存储库的路径。 在构建过程中,Jenkinsfile 从 SCM 中被检出并被处理。 作为共享库:流水线配置的一部分被移动到单独文件中,它可以由多个任务使用。 这些文件也保存在 SCM 中。 即使这样仍然需要 Jenkinsfile(或者任务中的流水线脚本)。  对于任务配置的每次保存操作,如果发生了变更,JobConfigHistory 将创建实际任务配置的副本。 只有当流水线配置作为脚本插入到任务配置页面时,该方法才适用于流水线任务。 JobConfigHistory 未检测到 Jenkinsfile 或共享库中的变更。 您必须使用 SCM 系统查看 Jenkinsfile 或共享库的变更。 在构建时间和对 Jenkinsfile 或共享库的变更之间找到相关性是复杂且耗时的。\n这个新问题不仅仅是 JobConfigHistory。 需要一个新的解决方案来检测流水线变更并显示 Jenkins 中的这些变更。 所以我们开发了流水线配置历史插件。\n在每个流水线运行期间,Jenkinsfile 和相关的共享库都保存在任务的构建目录中。 流水线配置历史插件将最近运行和前一次运行之间流水线文件的变更保存为历史事件。 因此,当流水线任务以成功的构建结束时,您可以检查任何使用的流水线文件是否发生了变更。 您还可以看到发生变更的构建。\n因为流水线配置可以由可能发生变更的多个文件组成,所以 diff 中只显示两个构建版本之间发生变更的文件。 这使得整个过程更加紧凑和有效:\n但有时您可能想要显示的不仅仅是流水线文件之间的差异。 您可能希望查看哪些流水线文件正在使用,或者这些文件在使用时的内容。 因此可以查看所有文件及其内容。 如果需要,您也可以下载:\n结论 我们在生产中成功地使用了流水线配置历史插件。 它从第一天起就帮助我们解决了由于流水线配置变更而出现的问题。 流水线配置历史插件不会替换任务配置历史插件。 插件有不同的用例。 很多时候,任务或流水线配置上的小变更也会产生很大的影响。 由于任务或流水线配置的变更与不同的构建行为之间的时间相关性,现在可以大大减少分析构建失败的时间和精力。 任务配置历史和流水线配置历史插件允许我们在咨询和解决问题方面为用户提供帮助。通过访问任务的配置历史,我们可以更快地解决问题。这些插件对我们的日常工作是必不可少的。\n",
        "auhtor": "pch-maintainers",
        "translator": "donhui",
        "original": "https://jenkins.io/blog/2019/07/15/pipeline-config-history-plugin/",
        "poster": "./2019-07-31-pipeline-config-history-plugin/sunset.jpg"
LinuxSuRen's avatar
LinuxSuRen 已提交
885
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
886
    {
887
        "uri": "https://jenkins-zh.cn/about/about-event-planning/",
888 889 890
        "title": "活动策划",
        "type": "about",
        "date": "2019-07-31 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
891
        "tags": [],
892 893 894
        "description": "社区组织活动策划",
        "content": " 本文讨论社区组织 meetup 、workshop 等活动策划的参考指引,方便社区其他地区组织者及志愿者借鉴使用。\n活动策划分为以下几步骤: - 活动地区及组织者确定 - 招募志愿者 - 活动任务分工认领 - 活动宣传\n1、活动地区及组织者确定 组织者需向 Jenkins 中文社区申请活动组织者得到许可后,才可以进行后续步骤。 - 确定活动地区 - 确定活动主题 - 确定大概活动日期\n2、招募志愿者 组织者可根据需要在公众号进行发布志愿者招募信息 - 活动策划志愿者 - UI 志愿者 - 现场活动志愿者\n志愿者采取主动报名的方式,报名方式可分为2种: - 社区内部报名 - 公众号发布招募信息,根据招募信息中的报名方式报名\n3、活动任务分工认领 活动主题确定后,如果有志愿者参与可根据下表进行任务分工认领:\n   任务分类 具体事项 完成情况 负责人 确认     场地 租赁与赞助、环境确认      赞助与礼品 赞助清单、礼品采购      讲师 讲师日期及演讲时长确认、ppt 收集      活动宣传 活动稿撰写、活动行及海报制作      活动议程 活动流程安排、日期提醒      场地布置 桌椅摆放、投影、白板      茶歇准备 茶歇采购、摆放      活动签到 参与者签到、礼品发放      活动拍摄 图片、视频拍摄及收集      抽奖活动 抽奖软件、抽奖环节安排      订餐安排 讲师与志愿者订餐       4、活动宣传 至少在活动举行前一个月完成活动宣传稿、活动行以及海报制作 - 首先在社区公众号发布活动通知 - 合作社区一并进行宣传 - 活动海报可在邻近活动日期进行发布 - 如果有精力可制作倒计时海报\n",
        "auhtor": "linan607",
LinuxSuRen's avatar
LinuxSuRen 已提交
895 896 897 898
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
899
    {
900
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-30-jenkins-meetup/",
901
        "title": "开源人线下见面会",
LinuxSuRen's avatar
LinuxSuRen 已提交
902
        "type": "wechat",
903 904 905 906 907
        "date": "2019-07-30 00:00:00 +0000 UTC",
        "tags": ["开源"],
        "description": "我们将从开源人精神、如何参与开源、开源与企业关系、开源社区存在的意义、996与开源关系等几个部分进行分享讨论。社区重于代码,你同意吗?",
        "content": " 本次活动是由 Jenkins 中文社区与“开源社”联合主办的一次关于如何参与开源的见会。\n大家共同探讨什么是开源精神、为什么以及如何参与开源、开源与个人以及企业之间的关系、开源社区存在的重要意义、996是否与开源背道而驰。\n我们的观点是:社区重于代码。是否与你的想法一致?欢迎来辩!\n分享嘉宾 赵晓杰 Jenkins 中文社区发起人\n热衷于传播开源理念、开源技术。多年研发经验,目前关注于 DevOps 领域,尤其是持续交付方面。\n刘天栋 Ted 开源社理事长暨联合创始人、Apache 软件基金会正式会员\n开源社理事长暨联合创始人, Apache 软件基金会正式会员,ASF孵化器项目委员会成员/导师,ASF 筹款委员会成员/赞助伙伴大使,中国信息通信研究院。云计算开源产业联盟.特聘开源治理个人顾问。于2014年10月联合创始开源社。于2018年当选 ASF 正式成员,随后加入 ASF 筹款委员会并成为赞助伙伴大使,2019年成为 ASF 孵化器项目委员会成员,并担任孵化项目(ECharts)导师。 曾历任微软中国战略业务总监、微软开放技术公司及微软亚太研发集团负责开源技术布道及开源社区发展工作;甲骨文(中国)渠道及联盟总监、甲骨文(中国) Linux 战略总监、甲骨文大中华区中间件事业部总经理;Turbolinux 亚太区副总裁等。\n慕睿涛 北京卓晟互联网络技术有限公司 CTO\n毕业于北京工业大学,2003年加入 Sun Microsystems,负责嵌入式 Java 虚拟机的研发。曾于2008年创建了 PSP 上的JavaME 模拟器项目——PSPKVM,在 PSP 自制软件社区有很高的普及度。目前在北京卓晟互联网络技术有限公司任 CTO ,创建并主持了 JOSH 开源项目,致力于为微小型物联网终端设备提供 Java 应用开发与运行环境。\n彭志雄 平安云 GitHub 产品专家\n13年IT行业工作经验,领域包括系统集成、售前支持和咨询、云计算和 DevOps 等业务。\n时间地点  日期 2019.8.24 地点 北京市朝阳区东直门外斜街56号 A座302  活动流程    时间 流程     13:00-13:30 签到   13:30-14:00 Jenkins 社区在国内的发展——赵晓杰   14:00-14:30 Apache 之道:从孵化器到顶级项目之路——刘天栋 Ted   14:30-14:45 茶歇   14:45-15:45 Panel 开源社区的发展和维护   15:45-16:00 茶歇   15:45-16:00 开源等于开放吗?——关于开源与开放之关系的思考——慕睿涛   16:00-16:30 用平安云 GitHub 转变企业软件开发模式——彭志雄   16:30-17:00 活动复盘    现场更有好礼相送  平安云赞助的保温杯   Jenkins 中文社区定制的笔、本以及贴纸  主办方 赞助企业 想更多地了解本次活动,请在 Jenkins 公众号后台回复“社区活动”,让我们社区的小伙伴把你拉进微信群。\n想报名的同学,请点击阅读原文。\n",
        "auhtor": "linan607",
LinuxSuRen's avatar
LinuxSuRen 已提交
908 909
        "translator": "",
        "original": "",
910
        "poster": "./2019-07-30-jenkins-meetup/shou.png"
LinuxSuRen's avatar
LinuxSuRen 已提交
911
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
912
    {
913
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-29-leveraging-jenkins-on-kubernetes/",
914
        "title": "在 Kubernetes 上使用 Jenkins ",
LinuxSuRen's avatar
LinuxSuRen 已提交
915
        "type": "wechat",
916 917 918 919 920 921 922 923
        "date": "2019-07-29 00:00:00 +0000 UTC",
        "tags": ["plugins", "pipeline", "Kubernetes", "ci", "cd"],
        "description": "Jenkins 是一个功能强大的自动化和 CI/CD 工具,可以成为 Kubernetes 流水线的重要组成部分",
        "content": " ​有几种方法可以在 DevOps 环境中管理您的云基础架构。 DevOps 是一种鼓励快速流动的应用程序开发以及促进 IT 团队开发、测试、发布过程无缝无缝衔接的方法。\nJenkins 通过自动化将持续集成(CI)和持续交付(CD)无缝集成到开发流程中来优化工作流程。\n可以使用 Kubernetes 中的 Jenkins pod 部署这些技术, Jenkins pod 可以根据团队的具体需求进行扩展。\nCI/CD 流水线 Jenkins 是 CI/CD 的同义词,它是自动化开发、部署应用程序和微服务的完美工具,目前是市场上最流行的自动化工具。 Jenkins 拥有1000多个插件,可以轻松地与其他系统(包括 Kubernetes )集成。插件不仅提供多系统集成,而且显著增强了 Jenkins 的能力,使 Jenkins 能够帮助您构建和部署几乎任何类型的项目。我们在另一篇文章中介绍了生活中最需要的20个 Jenkins 插件。\n​由于 Jenkins 和 Kubernetes 的原生兼容性,设置自己的 CI/CD 流水线非常容易。与基于 VM 的部署相比,在 Kubernetes 上部署 Jenkins 优势更明显。例如,获得按需拥有特定于 Jenkins slaves (代理)项目的能力,而不是让一个 vm 池空闲等待任务。它将使用 master-agent 体系结构来完全自动化微服务的创建和部署以及测试和部署所需的环境。\n​可以使用 Helm、kubectl 或 GUIs 部署 Jenkins ,以便将新的 pods 部署到集群中。安装后,下一步是为 K8s 配置 Jenkins 插件。我们需要配置系统设置,例如,代理在哪里找到 Jenkins master ,代理将使用的 Docker 镜像等。当然,将 Jenkins 配置为与 CI/CD 工作流一起工作也是至关重要的,包括设置测试和部署参数以及要如何设置 Jenkins 控制的集群。一旦 Jenkins 启动并运行,就可以实现一个完全自动化的连续交付环境。\n在 Jenkins 中设置一个流水线 ​让 Jenkins 启动只是一个开始,下一步是在 Jenkins 内配置 CI/CD 流水线。 你可以先运行 minikube service Jenkins ,然后使用其 Web UI 访问 Jenkins。\n​然后,您可以选择安装必要的插件。 根据您要创建的流水线,您可能需要下载并安装合适的插件,以实现流水线自动化以及更好的管理。必须使用 Kubernetes 插件。\n​另一个值得讨论的插件是 Kubernetes Continuous Deploy 插件,它专门为处理流水线的持续交付设计的。 该插件将处理为测试创建新的 pods 以及测试和部署之间的转换。\n​配置完所有插件后,重新启动 Jenkins。 Jenkins 提供的一个很好的功能能够自动执行这些手动更改,因此下次您配置 CI/CD 系统(例如,在基础结构迁移的情况下)时,不必再次通过手动更改。 您只需接收一个具有与以前相同配置和插件的实例。嵌入到 Jenkins Docker 镜像和 Jenkins 配置文件 config.xml 中的脚本 install_plugins.sh 实现了这一功能。\n​现在,您可以继续创建您的第一个流水线,为它分配凭据,并开始在流水线内部进行开发。记住, Jenkins 并不总是从本地存储中提取代码;您需要在第一次配置时手动发出推送请求。\n​创建第一个流水线,然后您可以通过优化 minikube 立即运行新应用程序。在大多数 CI/CD 工作流中,手动推送请求实际上很方便,因为现在您可以通过流水线更好地控制想要推送的代码。\n在不同的情况下推动变化 ​当您打开应用程序代码并对其进行更改时, Jenkins 不会立即更新部署包。相反,您必须提交更改并等待 Jenkins 提取这些更改(取决于代码签出的配置方式),然后才能执行其他操作。\n​在 Jenkins 用户界面上,有一个 Build now 命令用于运行新的构建。构建完成后,下次使用 Minikube 运行应用程序时,您将看到所做的更改。 Jenkins 流水线的配置方式使该工具非常有用。\n​例如,您可以使用 Jenkins 来支持多团队开发。 Jenkins 流水线作为代码运行,这意味着具有正确凭据的任何用户都可以提交更改并执行流水线中内置的流程。\n​它也非常通用。 如果服务器突然崩溃,流水线及其中的进程将自动恢复。 Jenkins 永远不会失去对它管理的集群的控制权,因此您可以使用 Jenkins完全消除对 CI / CD 环境的手动配置的需要。\n​我个人最喜欢的是 Jenkins 管理多个流水线的方式,管理员可以清楚地查看系统中的所有流水线。再加上暂停和恢复流水线的能力,管理微服务和大型项目的开发使用 Jenkins 非常有帮助。\n​另外的伟大的插件是流水线和多分支流水线,它帮助我们可视化 CI/CD 流。它允许在 repo 中定义一个 jenkins 文件,包括我们希望 jenkins 执行的所有步骤。不需要从 GUI 进行手动配置(可能只保留给管理员),并且允许开发人员灵活地控制给定项目/分支的流程。由于它在 Github 中,因此它也可以与任何其他应用程序库一起进行版本控制。\nJenkins 和 Kubernetes ​让我们回到我们的主要观点:在 Kubernetes 上使用 Jenkins 。从 Jenkins 工具的工作方式来看,很容易看出这种自动化度量如何完美地补充了 Kubernetes 。一旦配置了插件,每次触发新的构建/任务, Jenkins 都会在 K8s 中创建一个 Pod (通过设计用于执行该工作的按需代理)。一旦完成, Pod 将被销毁,从而避免了有固定的代理池等待任务执行的需要。如您所见, Kubernetes 为每个开发团队提供了强大的 CI/CD 基础架构,而 Jenkins 则大大简化了对该环境的管理。\n​这种组合能够在不同的情况下改进 CI/CD 工作流,包括在更大的开发项目中。如果你考虑到大量 Jenkins 插件的可用性,包括 Kubernetes 流水线、凭据以及目前已经可用的更多插件,您就会知道您有一个强大的 CI/CD 工具可以使用。甚至有能力将流水线中的非安装工作和材料工作分开;没道理不爱它?\n这篇文章最初发表在这里。\n",
        "auhtor": "Juan Ignacio Giro",
        "translator": "baobeizuoshoubuli",
        "original": "https://dzone.com/articles/leveraging-jenkins-on-kubernetes",
        "poster": "./2019-07-29-leveraging-jenkins-on-kubernetes/sea.jpg"
LinuxSuRen's avatar
LinuxSuRen 已提交
924
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
925
    {
926
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-15-let-s-celebrate-java-11-support/",
927 928 929 930 931 932 933 934 935 936 937 938
        "title": "让我们庆祝 Jenkins 对 Java 11的支持",
        "type": "wechat",
        "date": "2019-07-15 00:00:00 +0000 UTC",
        "tags": ["core", "developer", "java11", "community", "platform-sig"],
        "description": "本文是为了庆祝 Jenkins 对 Java 11的支持",
        "content": "  NOTE:这是由 Java 11支持团队准备的联合博客文章:Adrien Lecharpentier、Ashton Treadway、Baptiste Mathus、Jenn Briden、Kevin Earls、MaríaIsabelVilacides、Mark Waite、RamónLeón 和 Oleg Nenashev。\n  我们为此努力工作,现在就在这里。我们非常激动地宣布,从 Jenkins 2.164(2019年2月10日发布)和 LTS 2.164.1(ETA:3月14日)开始,在 Jenkins 中全面支持 Java 11。这意味着您现在可以使用 Java 11 JVM 运行 Jenkins master 和代理程序。\n从2018年6月开始,组织了许多活动来改进 Jenkins 代码库并添加 Java 11支持。除了这些事件之外,Core/Plugins 维护者和许多其他贡献者都在努力工作,确保他们发现并解决与 Java 11支持相关的尽可能多的问题。\n支持 Java 11的努力导致在 Jenkins 中创建了 JEP-211: Java 10+ support in Jenkins。它还促使平台特别兴趣小组的成立,以协调 Java 11工作和其他平台支持工作。\n庆祝活动 我们想花点时间感谢参与这些任务的每个人:代码贡献者、问题记者、测试人员、活动策划者和与会者以及社区中所有慷慨地为这项工作提供时间和支持的人。谢谢你们!\n以下是一些帮助完成此任务的贡献者(按字母顺序排列):\nAlex Earl, Alyssa Tong, Ashton Treadway, Baptiste Mathus, Carlos Sanchez, Daniel Beck, David Aldrich, Denis Digtyar, Devin Nusbaum, Emeric Vernat, Evaristo Gutierrez, Gavin Mogan, Gianpaolo Macario, Isabel Vilacides, James Howe, Jeff Pearce, Jeff Thompson, Jenn Briden, Jesse Glick, Jonah Graham, Kevin Earls, Ksenia Nenasheva, Kohsuke Kawaguchi, Liam Newman, Mandy Chung, Mark Waite, Nicolas De Loof, Oleg Nenashev, Oliver Gondža, Olivier Lamy, Olivier Vernin, Parker Ennis, Paul Sandoz, Ramón León, Sam Van Oort, Tobias Getrost, Tracy Miranda, Ulli Hafner, Vincent Latombe, Wadeck Follonier\n(如果我们错过了此列表中的任何人,我们深感抱歉。)\n指南 为了简单起见,以下是使用 Docker 镜像在 Java 11上启动 Jenkins 的方法。您可以通过为镜像的标签添加后缀来选择基于 Java 11的镜像-jdk11。如果要升级现有实例,请在升级之前阅读 Jenkins Java 版本升级从8到11。\n所以你可以在 Java 11上运行 Jenkins:\ndocker run -p 50000:50000 -p 8080:8080 jenkins/jenkins:2.164-jdk11  但是,和往常一样,您仍然可以使用其他方法启动 Jenkins。请参阅 Java 11上运行 Jenkins 的更详细文档。\n开发者指南 对于参与 Jenkins 开发的开发人员,您可以在 Java 11开发人员指南中找到有关开发和测试 Jenkins 以在 Java 11上运行的详细信息。\n此资源重新组合可能需要执行的修改,以验证 Java 11插件的兼容性。\n下一步是什么 尽管这是一项重大成就,但我们仍有工作要做。\n我们的首要任务是为 JenkinsFile Runner 项目添加 Java 11支持。从那里开始,我们将继续为 Jenkins X 项目和 Evergreen 项目提供 Java 11支持。\n所以,即使这对我们来说是个大问题,这也不是故事的结局。这是使Jenkins社区的用户,开发人员和成员受益的重要一步。\n参考链接  Running Jenkins on Java 11 https://wiki.jenkins.io/display/JENKINS/Known+Java+11+Compatibility+issues https://wiki.jenkins.io/display/JENKINS/Java+11+Developer+Guidelines JEP-211:Java 11 support in Jenkins  ",
        "auhtor": "alecharp",
        "translator": "yJunS",
        "original": "https://jenkins.io/blog/2019/03/11/let-s-celebrate-java-11-support/",
        "poster": "./2019-07-15-let-s-celebrate-java-11-support/c3bd32a48c96b4f10dad51a10f644233.png"
    },
    {
939
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-14-jenkins-pipeline-workshop/",
940 941 942 943 944 945 946
        "title": "持续交付落地实践工作坊",
        "type": "wechat",
        "date": "2019-07-14 00:00:00 +0000 UTC",
        "tags": ["jenkins", "pipeline"],
        "description": "Jenkins 中文社区2019第二场工作坊",
        "content": "Jenkins 中文社区第二次线下持续交付落地实践工作坊在召唤每一位希望学习并掌握持续交付技术的同学,就在 2019年7月27日(周六)。\nKubernetes 已经成为容器技术中必不可少的平台,甚至会作为未来的“操作系统”。相信每一次 IT 从业人员都有理由把 Kubernetes 掌握,本次活动首先由 Linux 基金会与 CNCF 基金会官方认证 Kubernetes CKA 培训讲师(LFAI)的孟凡浩为我们分享 Kubernetes 的入门介绍。\n之后,分享如何基于 Kubernetes 强大的平台下实践持续交付。\n在上次的工作坊实践中,我们首先完整地介绍了 Jenkins 的流水线功能,然后大家一起通过四个练习项目加强并巩固了 Jenkins 流水线 Jenkinsfile 文件的编写。\n上次练习的项目包括:\n 构建 Maven 项目 制品归档 构建 Docker 镜像 参数化构建,指定 Docker 镜像 Tag  过程中录制的视频,可以从我们的优酷地址上找到 https://i.youku.com/jenkinszh\n而对于参加本次工作坊实践活动的同学,可以根据自身的情况选择练习上面的题目或者下面进阶的题目:\n 构建 Maven 项目并发布到 Nexus 使用私有 Nexus 中的依赖进行构建 构建 Docker 镜像并推送到 Harbor 构建 Heml Charts 并推送到 Chartmuseum  我们期望每一位参加的同学都可以从中学习并掌握基于 Jenkins 的持续交付技术,助力你所在团队的 DevOps 实践。更多的实训项目请参考 https://jenkins-zh.cn/about/course/#17\n最后,让我们一起感谢京东云为我们本次活动提供的 Kubernetes 云计算资源。因此,每一位参加练习的同学,只需要带上自己的笔记本,以及 SSH 客户端即可。\n想更多地了解本次活动,请在 Jenkins 公众号后台回复“社区活动”,让我们社区的小伙伴把你拉进微信群。\n想报名的同学,请点击阅读原文。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
947 948
        "translator": "",
        "original": "",
949
        "poster": "pipeline-example.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
950 951
    },
    {
952
        "uri": "https://jenkins-zh.cn/about/branching-strategy/",
953 954
        "title": "分支策略",
        "type": "about",
955
        "date": "2019-07-09 19:56:04 +0800 +0800",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
956
        "tags": [],
957 958 959
        "description": "推荐使用的分支策略",
        "content": " 本文讨论分支策略主要是提供执行并行任务时的参考指引,方便社区贡献者借鉴使用。\n需要理解和注意以下几点: - 三个代码仓库 - 每个任务一个分支 - 分支策略\n三个 repo git 是一个分布式版本管理系统。以提交文章到 jenkins-infra/wechat 为例,在这个过程中,我们会涉及到三个代码仓库。 1. jenkins-infra/wechat repo,也就是 upstream repo,你需要 git remote add upstream 将其配置为 upstream repo 。 2. fork/wechat repo,如果你从这里 clone 的话,也就是对应的 origin repo 。 3. local repo,所有的分支管理都是从这里发起的。\n每个任务一个分支 每个任务一个分支的目的是,保证在 PR review/merge 的时候不会发生冲突。 换言之,PR review/merge 不存在先后关系,可以独立进行。 对于原创文章或翻译文章,每篇文章(包括资源文件)是一个独立的任务,每个任务对应一个分支。\n分支策略 假设已经完成 PR 提交操作(jenkins-infra/wechat:master \u0026lt;- fork/wechat:dev-01),下面是可能存在的相关分支。\njenkins-infra/wechat: master fork/wechat: master dev-01 local: master dev-01  这里的故事可以分为以下几步:\n 在 Github UI 上完成 fork 操作,所以,jenkins-infra/wechat:master 对应到 fork/wechat:master git clone 到本地,所以 fork/wechat:master 对应到 local:master 在本地创建 dev-01 分支 提交 commit,并 push 到 fork/wechat:dev-01 GitHub UI 发起 PR (jenkins-infra/wechat:master \u0026lt;- fork/wechat:dev-01)  这里需要注意的是,jenkins-infra/wechat:master 和 fork/wechat:master 经常会 不一致(jenkins-infra/wechat:master 是 source of truth ,会有很多 merge 来的 commits), 这并没有什么大的影响。\n有了上面的认识,下面就是一步一步的命令行,假设上面的 dev-01 已经被合并,需要新建 dev-02 分支执行新的任务:\n git checkout master git pull upstream master --rebase git checkout -b dev-02 (do something) git add . \u0026amp;\u0026amp; git commit -m 'do something' git push origin dev-02 # origin is your fork via Github UI (jenkins-infra/wechat:master \u0026lt;- fork/wechat:dev-02)  ",
        "auhtor": "donhui",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
960 961 962 963
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
964
    {
965
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-18-jenkins-weekly-release/",
966
        "title": "Jenkins 每周版更新",
LinuxSuRen's avatar
LinuxSuRen 已提交
967
        "type": "wechat",
968 969 970 971 972
        "date": "2019-07-09 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "本次更新的版本包括:2.180~2.184",
        "content": " 2.184 (2019-07-07)  注销时,移除过期的会话 cookies ,阻止头信息中的相关错误太大。 (issue 25046) 当运行在 Java 11 上时,增加缺失类相关的 telemetry 实验。 (issue 57223) 修复使用“记住我”时的性能问题(于 2.160 中退化) (issue 56243) 开发者:清理 AbstractCloudSlave 的构造器 (pull 4086)  2.183 (2019-06-30)  在 Jenkins 的 URL 配置增加对 IPv6 地址的支持。 (issue 58041) 更新 args4j 2.0.31 到 2.33。 (issue 57959) 开发者:允许插件为 CodeMirror 文本域控制提供 onBlur() 的支持。 (issue 58240) 开发者:使得 WindowsUtil 可以让插件使用。 (pull 4038) 内部:更新 maven-war-plugin 3.0.0 到 3.2.3 (issue 47127)  2.182 (2019-06-23)  当删除目录时,移除 Windows 下的只读标记。 (issue 57855) 更新 Remoting 3.29 到 3.33。 (issue 57959, issue 50095, issue 57713, 完整变更日志)  2.181 (2019-06-16)  插件管理界面中,允许对有可选依赖的插件禁用。 (issue 33843) 用于等待外部进程结束的线程池可能导致类加载溢出。 (issue 57725) 稳健性:当调度队列中的任务时有异常抛出可能会导致无法调度其他任务。 (issue 57805) 替换节点通道相关的部分异常栈为简单的消息。 (issue 57993) 更新 JNA 4.5.2 到 5.3.1,修复了在 AIX 上使用 OpenJDK 加载共享库的问题。 (issue 57515) 开发者:更新依赖 ant 1.9.2 到 1.9.14。 (pull 4053) 内部:使用 SpotBugs 代替 FindBugs 用于静态分析。 (pull 4062) 内部:为 hudson.model.UpdateSite#isDue 添加 synchronized 标记。 (issue 57466)  2.180 (2019-06-09)  由于 JNLP 节点在特定情况下无法连接云节点,Remoting 回退到 3.29(在版本 2.176 中退化) (issue 57759, issue 57713) 改善配置即代码对 ListView 的兼容性。 (issue 57121)  ",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
973 974
        "translator": "",
        "original": "",
975
        "poster": "“./2019-07-09-jenkins-release/great-wall.jpeg”"
LinuxSuRen's avatar
LinuxSuRen 已提交
976
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
977
    {
978
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-09-jenkins-release/",
979 980 981 982 983
        "title": "Jenkins 长期支持版更新",
        "type": "wechat",
        "date": "2019-07-09 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "本次更新的版本包括:2.164.2、2.164.3、2.176.1",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
984 985
        "content": " 2.176.1 (2019-06-10)  自 2.176 以来的变更:\n 恢复安装向导中用到的中文本地化资源。 (issue 57412) Robustness: 当 ComputerListener#onOnline() 发生运行时异常后不把节点设置为离线状态。 (issue 57111)  CLI 中通过参数 (-remoting option) 对远程模式的支持已经被移除。 (pull 3838, 博客发布)\n 移除符号 nonStoredPasswordParam 对密码参数定义的误导,因为,它会存储加密后的数据。 (issue 56776)\n 移除对 CCtray (cc.xml) 文件的默认支持。 要使用该功能,需要按照插件 CCtray XML Plugin。 (issue 40750)\n 增加 CLI 命令 stop-job 终止构建。 (issue 11888)\n 在日志配置中支持关闭一项日志记录器。 (issue 56200)\n 为 REST API 的响应增加运行参数过滤器。 (issue 56554)\n 构建结束后更新状态图标。 (issue 16750)\n 在 Jenkins 节点的界面上移除对 Java Web Start and JNLP 的误导性引用。 (pull 3998)\n 当涉及到以虚拟 SYSTEM 用户运行构建时,通知管理员潜在的不安全设置。 (issue 24513)\n 当运行在虚拟的 SYSTEM 认证下时,在构建日志中增加一条日志消息。 (pull 3908)\n 迁移所有中文本地化资源文件到 简体中文插件。 (pull 4008)\n 调整流刷新行为,使得运行在远程的节点上时有更好的性能。这可能会导致部分插件在节点机器上打印构建日志却不刷新输出时丢失消息。 通过 -Dhudson.util.StreamTaskListener.AUTO_FLUSH=true 可以让自由风格的构建回到之前的行为。 注意,流水线的构建总是期待远程刷新。 (pull 3961)\n Winstone 的版本从 5.1 更新到 5.2,使得 HTTPS cipher 为可配置的。 (issue 56659, issue 56591, 完整变更日志)\n 从核心中移除邮件相关的本地化字符串。确保你使用 Mailer Plugin 1.23。 (issue 55292)\n 如果工作空间已经被一个跨节点运行的流水线重连时使用了,那么,它将不会再给新的构建分配租期。 (issue 50504)\n 开发者:为了支持从任意插件中加载本地化资源,Stapler 的版本从 1.256 更新到 1.257。 增加接口 jenkins.PluginLocaleDrivenResourceProvider 用于让其他插件可以定制本地化资源的查找过程。 (JEP-216, 完整变更日志)\n 开发者:本地化库的版本从 1.24 更新到 1.26,使用插件可以覆盖查找本地化资源文件的逻辑。 (pull 3896, JEP-216, 完整变更日志)\n 开发者:为类似于单行 f:password 的多行文本凭据添加 Jelly UI 组件 f:secretTextarea。 (pull 3967, 在 Jenkins 中存储凭据)\n 开发者:SystemProperties 现在可以用于节点端的代码。参考 SystemProperties#allowOnAgent。 (pull 3961)\n  2.164.3 (2019-05-09)  有问题的 console notes 会使得 ConsoleNote#readFrom 抛出一个无意义的 NegativeArraySizeException 异常,并导致构建日志无法正常显示。 (issue 45661) 安装向导没有正确地对密码进行转义,导致遇到特殊字符后会有错误。 (issue 56856) 使得 Jenkins 经典界面中的表单提交按钮与 Firefox 即将发布的缺陷修复兼容。 (issue 53462, Firefox bug 1370630) 正确地刷新 Maven console annotator 的输出。 (issue 56995) 使得 Debian/Ubuntu 的启动脚本与 Java 11 兼容。 (issue 57096) 复用 Stapler 请求分发 telemetry。 (issue 57167)  2.164.2 (2019-04-10)  安全修复。 (安全公告) 运行在 Microsoft Docker 下的 Windows Server 2016 时,工作空间以及归档文件无法工作。(由 2.150.2 引入的缺陷回归) (issue 56114) 当丢弃不可读的指纹数据时避免 NullPointerException 。 (issue 43218)  ",
        "auhtor": "linuxsuren",
986 987
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
988
        "poster": "“./2019-07-09-jenkins-release/great-wall.jpeg”"
989 990
    },
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
991 992 993 994 995 996 997 998
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-08-wechat-answer-1/",
        "title": "Jenkins 中文社区技术交流微信群问题集之一",
        "type": "wechat",
        "date": "2019-07-08 00:00:00 +0000 UTC",
        "tags": ["pipeline"],
        "description": "群里讨论过的问题(使用方法、缺陷)太多,无法全部包含在一篇文章中",
        "content": " 申明:下文中的问题是群友发起的,回答则是由笔者收集整理的。\n1. 同一流水线,如何做某个阶段定时执行代码扫描 这个需求的意思是存在一条流水线,流水线中的阶段为:构建阶段 \u0026ndash;\u0026gt; 代码扫描阶段 \u0026ndash;\u0026gt; 发布测试环境阶段 \u0026ndash;\u0026gt; \u0026hellip; 而提问者希望当有代码提交时,就执行整条流水线。当到某个时间点时,就只执行扫描阶段。\n回答一 当代码没有变化,我们为什么要重复执行扫描呢?\n回答二 换成两个流水线,一个提交触发,一个定时触发\n回答三 一条流水线加个开关设置是否跳过扫描。\n2. 有人做过增量包构建么?  有人做过增量包构建么?问下要用哪些插件,怎么做? 经确认,提问人的需求是有一个代码仓库 x,然后 x 里有 a,b,c 三个模块,开发提交了 a 模块的代码,这时,只打包 a 模块的制品。\n 回答一 要做的是在流水线里判断提交代码中修改了哪个模块,然后执行你的 ant 命令指定构建某个模块就好了。代码 demo 如下:\npipeline{ agent any stages{ stage('build a'){ when{ changeset \u0026quot;a/**\u0026quot; } steps{ echo \u0026quot;build a\u0026quot; } } stage('build b'){ when{ changeset \u0026quot;b/**\u0026quot; } steps{ echo \u0026quot;build b\u0026quot; } } } }  回答二 增量包,四五年前我有过相关实践,构建工具也是 ant。记得当初是根据修改的文件路径,解析出 ant target 列表,然后根据事先声明好的依赖关系对它排序,然后执行 ant 构建命令,最后将生成的二进制包挑出来生成增量包,大致这么个思路。\n3. post 里如何指定 agent  请教一下,jenkinsfile中 post里面可以指定agent吗?\n 回答 post { always { node('master') { cleanWs() } } }  笔者注:node('\u0026lt;node\u0026gt;') 中的 \u0026lt;node\u0026gt; 可以是 agent 节点名称,也可以是 agent 的标签。\n4. windows 上 无法使用 curl  有些步骤是跑在 Windows 节点上,在 Windows 上又希望能发 http 请求。\n 回答 这时,应该使用 HTTPRequest 插件,它是平台无关的。\n4. 怎么把 slave 的内容 copy 到 master 机器上?  因为比如我用有一个 windows 节点,然后我代码拉取后,需要进行一些测试,测试完成后生成数据和 HTML 报告,这部分测试全都在节点上完成,我想把测试完成后到数据发到 master 上,然后由 master 生成 html 报告\n 回答 不确定,我是否理解正确。可以考虑这样做,把你现在的事情分成两个阶段,阶段一在 windows 上测试,然后将数据和 html 报告上传到某个地方,阶段二,将数据和报告下载回来,比如下载到 master 上。接着,想干嘛就干嘛了。\n5. httpRequest 如何发 POST 请求  httprequest这个插件 请求body这块一行一个参数?  回答 httpRequest authentication: credentialName, contentType: 'APPLICATION_JSON_UTF8', httpMode: 'POST', requestBody: \u0026quot;\u0026quot;\u0026quot;{\u0026quot;reportJson\u0026quot;: \u0026quot;111\u0026quot;,\u0026quot;id\u0026quot;: \u0026quot;111\u0026quot;,\u0026quot;executeNum\u0026quot;: 111}\u0026quot;\u0026quot;\u0026quot;, responseHandle: 'LEAVE_OPEN', url: \u0026quot;http://127.0.0.1/echo\u0026quot;  6. 我仓库特多,怎么设计流水线  我的仓库一共有4个 分别存放 代码 战斗脚本 资源 协议。4个代码仓库各有3个分支 名字都是对应的,比如1号仓库分支 master develop production. 2号仓库 也是这几个分支 以此类推 我拉取代码进行打包的时候 会拉取 4个仓库名字都叫 master 的分支 或者名字都叫 develop 的分支进行打包 现在问题就出在 我拉取4分仓库都叫 master 的分支的时候 拉取完代码后 最后一个仓库的代码会把前个仓库的代码覆盖掉,后来有老哥给了建议 用 dir 分别存到 workspace 下的好几个目录 现在遇到的问题是 我多分支流水线第一次启动时,会把1号仓库的代码直接拉到 workspace 下 我的问题就是可以不可在多分支流水线第一次启动时,不要拉取代码\n 回答 建立一条流水线,接受 gitlab 触发,然后根据触发请求中的数据,决定拉取哪个代码仓库。参考 Generic Webhook Trigger 插件。\n7. 流水线中如何指定工作目录  pipeline 中怎么指定这个流水线的工作目录,我在开头定义 WORKSPACE 但是没用\n 回答 8. 如何在 pipeline 中使用第三方 jar 包  请教下 pipeline 需要引用第三方 jar 包时,要放在哪里才能被 import 进来啊,我放到 classpath 下还是不行,总是提示找不到包。在本地执行 groovy,impor t进来没有问题\n 回答 把 jar 包放到 tomcat 安装 jenkins 的目录下的 lib 里貌似能解决。\n后记 如果读者朋友在使用 Jenkins 过程中也遇到各种问题,可关注Jenkins微信公众号。后台回复“微信群”入群。群里会有热心朋友回复。\n",
        "auhtor": "zacker330",
999 1000
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1001
        "poster": "./2019-07-08-wechat-answer-1/wechat.png"
1002 1003
    },
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-04-performance-testing-jenkins/",
        "title": "Jenkins 插件的微基准测试框架",
        "type": "wechat",
        "date": "2019-07-04 00:00:00 +0000 UTC",
        "tags": ["jmh", "plugins", "benchmark", "performance", "developer", "gsoc", "gsoc2019"],
        "description": "本文介绍了 Jenkins 插件的微基准测试框架以及如何在插件中运行基准测试",
        "content": " Jenkins 插件的微基准测试框架 作为我 Google 编程夏令营的一部分,我一直致力于改进角色策略插件(Role Strategy Plugin)的性能。 由于没有现有的方法来度量性能以及在 Jenkins 插件上做基准测试, 我在项目第一阶段的工作是创建一个框架在一个 Jenkins 实例中运行 Jenkins 插件中的基准测试。 为了让我们的工作更容易些,我们选择了 Java微基准测试工具来运行这些基准。 这使我们能够可靠地度量对时间要求严格的功能的性能,将有助于让 Jenkins 为每个人更快的运转。\n最近在 Jenkins 单元测试工具2.50中发布了微基准测试框架。 下面的博客文章展示了如何在插件中运行基准测试。\n介绍 该框架通过为 JMH 基准的每个 fork 启动一个临时的 Jenkins 实例来运行, 就像 Jenkins 测试工具中的 JenkinsRule。 基准测试是直接从 JUnit 测试运行的,它允许在运行过程中失败构建,并且很容易从 IDE 中运行基准测试,就像单元测试一样。 你可以很容易地通过使用 Java 方法或使用 Jenkins plugin:configuration-as-code:[配置即代码插件]来配置基准并将路径传递到 YAML 文件。\n要从您的插件运行基准测试,您需要做以下工作:\n 将所需的最低 Jenkins 版本升级到2.60.3或更高版本 将 Plugin-POM 升级到 ≥ 3.46 的版本或手动更新 Jenkins 测试工具到 ≥ 2.51 的版本  现在,要运行基准测试,您需要有一个包含 @Test 的基准测试运行程序,以便它可以像 JUnit 测试一样运行。 从测试方法内部,可以使用 JMH 提供的 OptionsBuilder 来配置基准。 例如:\npublic class BenchmarkRunner { @Test public void runJmhBenchmarks() throws Exception { ChainedOptionsBuilder options = new OptionsBuilder() .mode(Mode.AverageTime) .forks(2) .result(\u0026quot;jmh-report.json\u0026quot;); // Automatically detect benchmark classes annotated with @JmhBenchmark new BenchmarkFinder(getClass()).findBenchmarks(options); new Runner(options.build()).run(); } }  示例基准 现在,你可以编写第一个基准:\n无需任何特别的设置 @JmhBenchmark public class JmhStateBenchmark { public static class MyState extends JmhBenchmarkState { } @Benchmark public void benchmark(MyState state) { // benchmark code goes here state.getJenkins().setSystemMessage(\u0026quot;Hello world\u0026quot;); } }  使用配置即代码 要使用配置即代码,除了上面的依赖外,还需要在你的 pom.xml 添加如下内容:\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.jenkins\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;configuration-as-code\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.21\u0026lt;/version\u0026gt; \u0026lt;optional\u0026gt;true\u0026lt;/optional\u0026gt; \u0026lt;/dependency\u0026gt; \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;io.jenkins\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;configuration-as-code\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.21\u0026lt;/version\u0026gt; \u0026lt;classifier\u0026gt;tests\u0026lt;/classifier\u0026gt; \u0026lt;scope\u0026gt;test\u0026lt;/scope\u0026gt; \u0026lt;/dependency\u0026gt;  现在配置一个基准很简单,只需提供 YAML 文件的路径并指定包含基准状态的类。\n@JmhBenchmark public class SampleBenchmark { public static class MyState extends CascJmhBenchmarkState { @Nonnull @Override protected String getResourcePath() { return \u0026quot;config.yml\u0026quot;; } @Nonnull @Override protected Class\u0026lt;?\u0026gt; getEnclosingClass() { return SampleBenchmark.class; } } @Benchmark public void benchmark(MyState state) { Jenkins jenkins = state.getJenkins(); // jenkins is configured and ready to be benchmarked. // your benchmark code goes here... } }  更多示例 作为这个项目的一部分,在角色策略插件(Role Strategy Plugin)中创建了一些基准测试,它们展示了为各种情况配置实例。 你可以在这里找到它们。\n运行基准测试 从 Maven 运行基准测试 为了方便从 Maven 运行基准测试,创建了一个 Maven 配置文件来运行基准测试,并且可以从 Plugin-POM 3.45 版本开始使用。 然后你可以使用 mvn test -Dbenchmark 从命令行运行基准测试。\n在 ci.jenkins.io 运行基准测试 如果您的插件托管在 ci.jenkins.io 上,那么可以直接从 Jenkinsfile 轻松地运行基准测试。 通过在 Jenkinsfile 中的 buildPlugin() 步骤后使用 runBenchmarks() 方法,该步骤现在在 Jenkins 流水线库。 此函数还接受生成的 JMH 基准报告的路径作为可选的参数并存档基准结果。 在 pull request 构建中运行基准测试允许您不断地进行测试监视给定更改的性能影响。 例如,来自角色策略插件(Role Strategy Plugin)的 Jenkinsfile :\nbuildPlugin() runBenchmarks('jmh-report.json')  可视化基准测试结果 可以使用 plugin:jmh-report[JMH 报告插件]或将基准测试报告传递给 JMH 可视化工具 web 服务来可视化生成的基准报告(JSON格式)。 举个例子,这里有一些来自角色策略插件(Role Strategy Plugin)中基准测试的可视化报告:\n上面所看到的这些改进是通过对插件的一个小的 pull request 获得的,并展示了即使是看起来很小的更改也可以带来很大的性能改进。 微基准测试有助于找到这些热点,并估计更改的影响。\n一些提示与技巧  由于上面示例中的 BenchmarkRunner 类名不符合 Maven Surefire 插件的测试条件命名约定,基准测试不会干扰 JUnit 测试。 基准测试方法需要用 @Benchmark 进行注解,以便 JMH 检测它们。 当注解为 @JmhBenchmark 时,包含基准的类由 BenchmarkFinder 自动找到。 对 Jenkins 实例的引用可以通过 JmhBenchmarkState#getJenkins() 或通过 Jenkins.getInstance() 获得,就像您在其他情况下会做的那样。 JmhBenchmarkState 提供了 setup() 和 tearDown() 方法,根据您的基准测试的需求,可以重写这些方法来配置 Jenkins 实例。 由于 highmem 节点的可用性有限,基于 ci.jenkins.io 的基准测试目前被限流。 基准框架在 Jenkins 测试工具2.50中提供,建议使用2.51版本,因为它包含一些错误修复。  链接及反馈 如果您有任何反馈、评论或问题, 请通过角色策略插件(Role Strategy Plugin) Gitter 聊天室 或通过 Jenkins 开发者邮件列表随时与我联系。\n 演示幻灯片 在平台 SIG 会议中的示例 微基准测试框架的文档:  编写基准测试 (Jenkins 测试工具) 使用 JCasC 预配置基准 使用 Plugin POM profile 运行基准测试 在 ci.jenkins.io 上运行基准测试的构建步骤   ",
        "auhtor": "abhyudayasharma",
        "translator": "donhui",
        "original": "https://jenkins.io/blog/2019/06/21/performance-testing-jenkins/",
        "poster": "./2019-07-04-performance-testing-jenkins/reflection.jpg"
    },
    {
1017 1018 1019
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-10-phase-1-multibranch-pipeline-support-for-gitlab/",
        "title": "多分支流水线任务对 GitLab SCM 的支持",
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028
        "date": "2019-07-04 00:00:00 +0000 UTC",
        "tags": ["gitlab", "plugins", "pipeline", "credentials", "developer", "gsoc", "gsoc2019"],
        "description": "本文介绍了多分支流水线任务对 GitLab SCM 的支持",
        "content": " 这是在 GSoC 2019中的一个 Jenkins 项目。 我们正致力于增加多分支流水线任务和文件夹组织对 GitLab 的支持。 这个计划是创建以下插件: * GitLab API 插件 - 包装 GitLab Java APIs。 * GitLab 分支源插件 - 包括两个包: * io.jenkins.plugins.gitlabserverconfig - 管理服务器配置和 Web hooks 管理。理想情况下应该在另一个名为 GitLab Plugin 的插件中。 未来,这个包应该移动到新的插件中。 * io.jenkins.plugins.gitlabbranchsource - 为多分支流水线任务(包括 Merge Requests )和文件夹组织添加 GitLab 分支源。\n现状  完全支持自由风格的任务和流水线(单分支)任务。 部分支持多分支流水线任务(没有 MRS 检测)。 不支持 Gitlab 文件夹组织。  这个项目的目标  实现一个依赖于 Gitlab API 插件的轻量级 Gitlab 插件。 遵循3个独立插件的约定,即 GitLab 插件,GitLab API 插件,GitLab 分支源插件。 实现 Gitlab 分支源插件,支持多分支管道作业。 支持新的 Jenkins 特性,例如 Jenkins 代码即配置 (JCasC), 增量式工具。 清晰高效的设计。 支持新的 SCM 特性 APIs。 支持 Java 8 及更高版本。  构建插件 这个插件还没有二进制文件可用,因为这个插件还处于非常早期的 alpha 阶段,还没有为公众准备好。 如果您想尽早介入,可以尝试自己从源代码构建它。\n安装:  将源代码签出到您的本地机器上:\ngit clone https://github.com/baymac/gitlab-branch-source-plugin.git cd gitlab-branch-source-plugin  安装插件:\nmvn clean install mvn clean install -DskipTests # to skip tests  运行插件:\nmvn hpi:run # runs a Jenkins instance at localhost:8080 mvn hpi:run -Djetty.port=\u0026lt;port\u0026gt; # to run on your desired port number   如果您想用 Jenkins 服务器测试它,mvn clean install 之后在你的 Jenkins 实例中遵循以下步骤: 1. 选择 系统管理 2. 选择 插件管理 3. 选择 高级 选项卡 4. 在 上传插件 部分,选择 选择文件 5. 选择 $\u0026lt;root_dir\u0026gt;/target/gitlab-branch-source.hpi 6. 选择 上传 7. 选择 安装(无需重启)\n使用 假设插件安装已经完成。\n在 Jenkins 上设置 Gitlab 服务器配置  在 jenkins 上,选择 系统管理 选择 系统设置 向下滚动找到 GitLab 部分   4. 选择 Add GitLab Server | 选择 GitLab Server 5. 现在您将看到 GitLab 服务器配置选项。\n![gitlab-server](gitlab-server.png) 需要配置的字段有4个: * `Name` - 插件自动为您生成唯一的服务器名称。用户可能希望配置此字段以满足其需要,但应确保它足够唯一。我们建议保持原样。 * `Server URL` - 包含指向 Gitlab 服务器的 URL 。默认设置为 \u0026quot;https://gitlab.com\u0026quot; 。用户可以修改它以输入其 Gitlab 服务器 URL ,例如 https://gitlab.gnome.org/、http://gitlab.example.com:7990 等等。 * `Credentials` - 包含类型为 GitLab Personal Access Token 的凭据条目列表。当没有添加凭证时,它显示 \u0026quot;-none-\u0026quot; 。用户可以通过单击 \u0026quot;Add\u0026quot; 按钮添加凭证。 * `Web Hook` - 此字段是一个复选框。如果希望插件在与 Gitlab 项目相关的任务上设置 Webhook ,请选中此框。该插件监听相关 Gitlab 项目的 URL ,当 Gitlab 服务器中发生事件时,服务器将向设置 Web Hook 的 URL 发送事件触发器。如果您希望在 Gitlab 项目上持续集成(或持续交付),那么您可能希望自动设置它。   添加一个 Personal Access Token 凭据(自动生成 Personal Access Token 请参考下一个部分):\n 用户需要添加一个 GitLab Personal Access Token 类型凭证条目用来安全地将 token 保存在 Jenkins 内部。\n 在你的 GitLab 服务器生成一个 Personal Access Token  从右上角选择配置文件下拉菜单 选择 Settings 从左侧菜单选择 Access Token 输入一个名称 | 将 Scope 设置为 api,read_user,read_repository 选择 Create Personal Access Token 复制生成的 token  返回 Jenkins | 在凭据字段中选择 Add | 选择 Jenkins 设置 Kind 为 GitLab Personal Access Token 输入 Token 在 ID 处输入唯一的 id 输入人类可读的描述 选择 Add\n   测试连接:\n 在 Credentials 下拉列表选择你需要的 token 选择 Test Connection 它应该会返回 Credentials verified for user \u0026lt;username\u0026gt;  选择 Apply(在底部)\n GitLab 服务器现在在 Jenkins 设置好了\n  在 Jenkins 内创建个人访问令牌 或者,用户可以在 Jenkins 内部生成 Gitlab 个人访问令牌,并自动添加 Gitlab 个人访问令牌凭据到 Jenkins 服务器凭据。 1. 在 GitLab 部分的底部选择 Advanced 2. 选择 Manage Additional GitLab Actions 3. 选择 Convert login and password to token 4. 设置 GitLab Server URL 5. 有两个选项来生成令牌: * From credentials - 要选择已在的持久存储的用户名密码凭据,或添加用户名密码凭据来持久存储它。 * From login and password - 如果这是一次性的,那么您可以直接在文本框中输入凭据,并且用户名/密码凭据不会持久化。\n 设置完你的用户名密码凭据后,选择 Create token credentials. token 创建器将在 GitLab 服务器中为具有所需范围的给定用户创建个人访问令牌,并为 Jenkins 服务器中的相同用户创建凭据。 您可以返回 GitLab 服务器配置来选择生成的新凭证(首先选择 \u0026ldquo;-none-\u0026rdquo; ,然后将出现新的凭证)。出于安全原因,此令牌不显示为纯文本,而是返回一个 id 。 它是一个128位长的 UUID-4字符串(36个字符)。\n  配置即代码 没有必要在UI中浪费时间。 Jenkins 配置即代码 (JCasC) 或者简单地 配置即代码 插件允许你通过一个 yaml 文件配置 Jenkins。 如果你是新用户,你可以在这里了解更多关于 JCasC 的信息.\n添加配置 YAML: 这里有多种方式配置 JCasC yaml 文件来配置 Jenkins: * JCasC 默认情况下在 $JENKINS_ROOT 搜索一个名为 jenkins.yaml 的文件。 * JCasC 寻找一个环境变量 CASC_JENKINS_CONFIG ,其中包含配置 yaml 文件的路径。 * 一个包含一组配置文件的文件夹的路径,例如: /var/jenkins_home/casc_configs。 * 单个文件的完整路径,例如: /var/jenkins_home/casc_configs/jenkins.yaml。 * 一个指向 web 上提供的文件的 URL ,例如: https://\u0026lt;your-domain\u0026gt;/jenkins.yaml。 * 您还可以在 UI 中设置配置的 yaml 路径。转到 \u0026lt;your-jenkins-domain\u0026gt;/configuration-as-code。 输入 jenkins.yaml 的路径或 URL 并选择 Apply New Configuration。\n一个通过 jenkins.yaml 配置 GitLab 服务器的例子:\ncredentials: system: domainCredentials: - credentials: - gitlabPersonalAccessToken: scope: SYSTEM id: \u0026quot;i\u0026lt;3GitLab\u0026quot; token: \u0026quot;XfsqZvVtAx5YCph5bq3r\u0026quot; # gitlab personal access token unclassified: gitLabServers: servers: - credentialsId: \u0026quot;i\u0026lt;3GitLab\u0026quot; manageHooks: true name: \u0026quot;gitlab.com\u0026quot; serverUrl: \u0026quot;https://gitlab.com\u0026quot;  要获得更好的安全性,请参阅 JCasC 文档中的处理 secrets 部分。\n未来工作范围 GSoC 的第二阶段将用于开发 Gitlab 分支源插件。新功能正在开发中,但代码库不稳定,需要大量的错误修复。 一些功能(如多分支流水线任务)工作正常。在第二阶段结束时会有更多关于它的信息。\n问题跟踪 这个项目使用 Jenkins JIRA 来跟踪问题。你可以在 gitlab-branch-source-plugin 模块提交问题。\n致谢 这个插件是由 Google 编程夏令营 (GSoC)团队为 GitLab 支持多分支流水线而构建和维护的。 很多灵感来自于 GitLab 插件,Gitea 插件 及 GitHub 插件。\n我们的团队成员:baymac,LinuxSuRen, Marky,Joseph, Justin,Jeff。\n来自其他人的支持:Oleg,Greg,Owen。\n也感谢整个 Jenkins 社区提供的专业技术和灵感。\n链接  第一阶段示例 演示幻灯片 GitLab API 插件 GitLab 分支源插件 GitLab API 插件 Wiki 第一阶段的问题跟踪 博客  ",
        "auhtor": "baymac",
        "translator": "donhui",
        "original": "https://jenkins.io/blog/2019/06/29/phase-1-multibranch-pipeline-support-for-gitlab/",
        "poster": "./2019-07-10-phase-1-multibranch-pipeline-support-for-gitlab/tea.jpg"
    },
1029
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/07/2019-07-01-introducing-the-jenkins-templating-engine/",
        "title": "介绍 Jenkins 模板引擎",
        "type": "wechat",
        "date": "2019-07-01 00:00:00 +0000 UTC",
        "tags": ["JTE", "pipeline", "plugin", "pipeline-authoring"],
        "description": "这是 StevenTerrana 的客座帖子,他是 Booz Allen Hamilton 的首席技术专家,也是模板引擎插件的首席工程师。他参加了流水线设计特别兴趣小组",
        "content": " 在企业范围内实施 DevSecOps 实践具有挑战性。由于组织内的不同应用程序正在使用多种编程语言、自动化测试框架和安全遵从性安全合规工具,因此每个团队构建和维护流水线变得很难。\n无论应用程序使用哪个特定的技术栈,大多数流水线都将遵循相同的通用工作流。模板引擎插件(简写为 JTE ,用于 Jenkins 模板引擎)允许您通过创建不依赖于工具的模板化工作流来获取效率,每个团队都可以重用这些工作流。\n作为公共部门和私营部门客户的技术顾问,我们在 Booz Allen 发现,每个新项目都要从头开始建造 DevSecOps 流水线。通过开发 Jenkins 模板引擎,我们已经看到流水线开发从几个月减少到几天,现在我们可以重用工具集成,同时为 Jenkins 流水线带来新的治理级别。\n流水线模板 组织受益于让应用程序开发人员专注于他们最擅长的工作:构建应用程序。支持这个,意味着建立一个集中式的 DevOps 团队,负责维护平台基础设施,并创建开发团队使用的 CI/CD 流水线。\n随着基于微服务的体系结构的兴起,一个集中的 DevOps 团队可以同时支持许多不同的开发团队;所有这些团队都可能利用不同的编程语言和自动化测试工具。\n虽然开发团队之间的工具可能不同,但工作流通常是相同的:单元测试、静态代码分析、构建和发布制品、部署它,然后针对部署的应用程序执行不同类型的测试。\n 模板引擎插件允许您从每个被团队定义可继承通用工作流的存储库中删除 Jenkinsfile 。作为替代每个存储库需定义整个流水线,团队提供一个使用工作流的工具配置文件。\n JTE 实战 让我们通过一个简单的示例来演示模板的可重用性: 流水线模板例子:  unit_test() build() static_code_analysis()  模板利用库提供的步骤概述工作流团队必须实现的步骤。虽然模板的执行方式与任何其他 Jenkinsfile 都一样(这意味着支持标准的脚本化和声明性语法),但模板的目标应该是以纯英语的方式阅读,并避免任何技术实现。\n 通过这种方式利用模板,您可以将流水线的业务逻辑(应该在什么时候发生)与技术实现(实际将要发生什么)分开。其结果是一个 CI/CD 管道,当同时支持多个团队时,该流水线被证明非常容易管理。\n 此模板( unit_test 、 build 和 static_code_analysis )概述的步骤是专门命名的。通过这种方式,团队可以使用的不同库共享同一流水线。\n实现模板 使用模板引擎实现可共享流水线需要几个关键组件: 1. 流水线模板:概述要执行的工作流 2. 库:提供工作流步骤的技术实现 3. 配置文件:指定要使用的库及其配置\n步骤1、创建流水线配置存储库 流水线配置存储库用于存储团队继承的常见配置和流水线模板。\n这个示例流水线配置存储库稍后将被配置为治理层的一部分:JTE 的机制中允许您构建表示组织的层次结构配置。\n治理层包含三个方面: 1. 流水线模板 2. 库资源清单 3. 层的配置文件( pipeline_config.groovy )\n 治理层的流水线模板和配置文件存储在流水线配置存储库中。\n 在 Jenkins 中配置治理层时,您将为包含上述组件的存储库以及可以找到这些制品的基本目录提供源代码管理位置。\n步骤2、创建流水线模板 接下来,我们将为治理层创建一个 Jenkinsfile 。在 JTE 中, Jenkinsfile 是执行将使用的默认流水线模板。\nJenkinsfile unit_test() build() static_code_analysis()  步骤3、 创建库 模板引擎插件实现了一个版本的 Jenkins 共享库,以增强库的可重用性。库是源代码存储库中的根目录,并且该存储库已在治理层上配置为库源。\n在我们的示例中,流水线模板需要执行单元测试、打包制品和运行静态代码分析。\n假设我们有一些团队使用 Gradle ,一些团队使用 Maven 来构建和测试他们的应用程序,但是他们都将使用 SonarQube 来执行静态代码分析。\n在这个场景中,我们应该创建 gradle 、 maven 和 sonarqube 库。\n|- gradle/ \\-- build.groovy \\-- unit_test.groovy |- maven/ \\-- build.groovy \\-- unit_test.groovy |- sonarqube/ \\-- static_code_analysis.groovy  步骤4、实施步骤 实现库步骤与将常规全局变量作为默认 Jenkins 共享库的一部分写入完全相同。\n为了这个演示的目的,我们将让每个步骤打印出步骤名称和贡献库。\ngradle/build.groovy void call(){ println \u0026quot;gradle: build()\u0026quot; }   读更多关于 JTE 开发库。\n 步骤5、创建配置文件 JTE 的配置文件名为 pipeline_config.groovy 。\n在治理层,我们将建立一个配置文件,具体说明应用程序之间的共同配置。在此情况下,两种应用都是使用 sonarqube 库。\npipeline_config.groovy libraries{ merge = true // allow individual apps to contribute additional libraries sonarqube }  接下来,我们将创建另外两个表示 Maven 和 Gradle 应用程序的存储库。在这些存储库中,我们只需要一个特定的 pipeline_config.groovy 文件。\n这些存储库都包含应用程序 pipeline_config.groovy 配置文件。\nmaven app: pipeline_config.groovy libraries{ maven }  gradle app: pipeline_config.groovy libraries{ gradle }  步骤6、在 Jenkins 中配置治理层 既然我们有了流水线配置存储库和库源存储库,那么就可以在 Jenkins 中配置治理层:\n 上图中显示的配置可以在以下找到 Manage Jenkins \u0026gt;\u0026gt; Configure System 。\n通过模板引擎,您可以通过 Jenkins 中的文件夹表示此结构,从而创建与组织分类相匹配的流水线治理层次结构。\n 步骤7、为两个应用程序创建多分支流水线 当为每个应用程序创建多分支流水线项目时,模板引擎插件提供一个名为 Jenkins 模板引擎的新 Project Recognizer 。项目设置为在存储库中的所有分支使用模板引擎框架。。\n 您还可以为 GitHub 组织项目设置 Jenkins 模板引擎项目识别器,使您能够轻松地在整个 GitHub 组织中共享相同的流水线!\n 步骤8、运行流水线 就这样!现在,这两个应用程序将利用完全相同的流水线模板,同时具有选择工作流每个阶段应使用哪些工具的灵活性。\n下面是两个应用程序运行流水线的控制台日志的示例输出:\nGradle: [JTE] Obtained Template Configuration File pipeline_config.groovy from git https://github.com/steven-terrana/example-jte-configuration [JTE] Obtained Template Configuration File pipeline_config.groovy from git https://github.com/steven-terrana/example-jte-app-gradle.git [JTE] Loading Library sonarqube from git https://github.com/steven-terrana/example-jte-libraries.git [JTE] Loading Library gradle from git https://github.com/steven-terrana/example-jte-libraries.git ... [JTE] Obtained Template Jenkinsfile from git https://github.com/steven-terrana/example-jte-configuration [JTE][Step - gradle/unit_test] [Pipeline] echo gradle: unit_test() [JTE][Step - gradle/build] [Pipeline] echo gradle: build() [JTE][Step - sonarqube/static_code_analysis] [Pipeline] echo sonarqube: static_code_analysis() [Pipeline] End of Pipeline  Maven: [JTE] Obtained Template Configuration File pipeline_config.groovy from git https://github.com/steven-terrana/example-jte-configuration [JTE] Obtained Template Configuration File pipeline_config.groovy from git https://github.com/steven-terrana/example-jte-app-maven.git [JTE] Loading Library sonarqube from git https://github.com/steven-terrana/example-jte-libraries.git [JTE] Loading Library maven from git https://github.com/steven-terrana/example-jte-libraries.git ... [JTE] Obtained Template Jenkinsfile from git https://github.com/steven-terrana/example-jte-configuration [JTE][Step - maven/unit_test] [Pipeline] echo maven: unit_test() [JTE][Step - maven/build] [Pipeline] echo maven: build() [JTE][Step - sonarqube/static_code_analysis] [Pipeline] echo sonarqube: static_code_analysis() [Pipeline] End of Pipeline  模板引擎的好处 应用组织治理 利用模板引擎插件,您可以定义企业级的、经过批准的工作流,无论使用什么工具,团队都可以使用这些工作流。这种自上而下的方法使得在组织中扩展和执行 DevSecOps 原则变得非常容易。\n优化代码重用 实际上,组织中的每个团队都不需要反复思考如何做相同的事情。在 Booz Allen ,我们已经看到流水线开发时间从几个月减少到几天,因为我们不断地重复使用和扩展模板引擎库组合,作为解决方案交付平台的一部分。\n简化流水线可维护性 通常,DevOps 工程师会发现自己同时为多个开发团队构建和支持流水线。通过将工作流与技术实现分离,并将流水线定义合并到一个集中的位置,模板引擎插件允许 DevOps 工程师更快地扩展。\n参与进来! 模板引擎插件是开源的,并在 Jenkins 更新中心提供。\n我们总是感谢反馈和贡献!如果你有一个有趣的用例或者想问一些问题,可以试试 Gitter 上的模板引擎插件。\n高级功能  配置文件条件继承 外部化库配置 面向方面的生命周期钩子 多个流水线模板 默认步骤实现 配置文件 DSL 沙盒  更多资源 对于这个演示  Pipeline 配置存储库 示例库 Maven 存储库示例 Gradle 存储库示例  其他资源  模板引擎文档 源代码 Booz Allen 的 SDP 流水线库 博思艾伦咨询公司  ",
        "auhtor": "Steven Terrana",
        "translator": "linan607",
        "original": "https://jenkins.io/blog/2019/05/09/templating-engine/",
        "poster": "./2019-07-01-introducing-the-jenkins-templating-engine/JTE.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-26-using-active-choices-plugin-merge-jobs/",
        "title": "使用Active-Choices-Plugin插件将十个Job合成一个",
        "type": "wechat",
        "date": "2019-06-26 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "plugin"],
        "description": "使用Active-Choices-Plugin插件将十个Job合成一个",
1049
        "content": " 现在Spring Cloud越来越火爆,许多公司也都在如火如荼投入使用中,而微服务最大的一个特点,就是多,同一大项目之下,可能会被拆分成十几二十几个子服务,对于运维而言,可能也需要一个对应一个地在Jenkins中创建十几二十几个Job。\n刚刚还在一个博主的自我介绍里看到这样一句话:喜欢一切优雅的运维方式···\n于是,我一直在想着,通过一些合理的参数变幻,从而将刚刚提到的十几二十几个服务,汇集到一个Job当中就能完成。\n1,环境说明  主机:CentOS-7.5 Jdk:jdk1.8.0_192 Tomcat:8 Jenkins:2.177  如上环境的准备工作本文就不赘述了。\n2,安装插件。  官方地址:https://wiki.jenkins.io/display/JENKINS/Active+Choices+Plugin 安装方式:在Jenkins插件当中直接搜索即可安装。 功能说明:根据所选参数,自动调出对应参数所依赖的后续参数。  3,使用前介绍。 插件安装之后,可以在项目配置中的参数化配置中看到一些新增了的选项。\n 1,Active Choices Parameter(主动选择参数) Active Choices参数使用Groovy脚本或Scriptler目录中的脚本动态生成构建参数的值选项列表。 2,Active Choices Reactive Parameter(主动选择反应参数) 根据主动选择参数的选项而提供不同的对应值或者列表选项。 3,Active Choices Reactive Reference Parameter(主动选择反应参考参数) 根据主动选择参数的选项而展示对应参数的一些说明,与第二项的区别在于本参数只作为说明信息,而不能够作为变量往下传递。  可能刚刚这些说明都比较抽象,接下来容我通过项目实战,来对其进行一一解析。\n4,配置前分析。 优秀的插件,它的优秀之处,往往是需要我们结合生产实际,开动聪明的大脑,打破常规使用套路来成就的。\n因此,如何才能更好地应用插件的优秀功能,需要我们先对项目进行分析,从全局的眼光,判断项目前后该配置什么样的参数来进行联动。\n这里我说明一下我准备的实验项目情况,为了简便测试,我这里仅使用两个项目来进行举例,聪明的你也一定能够通过案例进行举一反三,将二合一推广为十合一的。\n两个项目的情况如下:\n1,eureka  Gitlab地址:git@192.168.10.0:ishangjie/ishangjie-eureka-server.git port:8761 包名:ishangjie-eureka-server-1.0.0.jar  2,user  Gitlab地址:git@192.168.10.0:ishangjie/ishangjie-user-service.git port:6666 包名:ishangjie-user-service-1.0.0.jar  从刚刚这些配置里边可以看出,有不少共同点,也有不少不同点,我们只需把眼光放在不同点上,通过一些统一的变量控制,就能达到二合一的目的。\n另外说明一点,这个项目已经部署在k8s环境当中,因此我的脚本内容也就展示成了k8s项目部署的流程了。\n5,创建项目。 首先创建一个自由风格的Jenkins项目,然后配置一下项目构建保存历史。\n6,字符参数。 添加一个名为branch的字符参数以用于控制代码分支的变量。\n7,选项参数。 添加一个名为mode的选项参数以用于控制部署或者回滚的变量。\n8,选择参数。 1,主动选择参数 首先添加一个主动选择参数,用于控制项目名称这个变量。\n Name:project Groovy Script:  return[ \u0026quot;eureka\u0026quot;, \u0026quot;user\u0026quot; ]  Description:选择对应的应用名称部署对应的应用。 Choice Type:Radio Buttons  2,主动选择反应参数 接着添加一个主动选择反应参数,用于控制项目类型这个变量。\nName:type - Groovy Script:\nA=[\u0026quot;server\u0026quot;] B=[\u0026quot;service\u0026quot;] if(project.equals(\u0026quot;eureka\u0026quot;)){ return A } else if(project.equals(\u0026quot;user\u0026quot;)){ return B }   Description:跟随项目的选择自动弹出对应类型 Choice Type:Single Select Referenced parameters:project  3,主动选择反应参数 然后再添加一个主动选择反应参数,用于控制项目端口这个变量。\n Name:port Groovy Script:  if(project.equals(\u0026quot;eureka\u0026quot;)){ return [\u0026quot;8761\u0026quot;] } else if (project.equals(\u0026quot;user\u0026quot;)){ return [\u0026quot;6666\u0026quot;] }  Description:跟随跟随项目的选择自动弹出对应端口 Choice Type:Single Select Referenced parameters:project  这样,对应的参数都创建完毕了,大概有以下几个小的注意点需要注意:\n 1,参数的名称将是整个构建流程使用的一个变量,因此起名的时候需要注意。 2,创建了一个主动选择参数,和两个主动选择反应参数,是因为我们的实际需求需要两个真实有效的参数,如果最后的port项选择了主动选择反应参考参数,那么到后边是无法显式使用的。 3,注意后两个跟随参数中的Referenced parameters,都需要填写主动参数的名称,才能够前后贯通,实现联动。  9,Git地址配置。 接着就该添加Git地址了,同样,这个地方也应该合理利用项目标准化的优势,合理应用变量来进行配置。\n具体如下图所示:\n10,执行脚本。 接下来就该通过脚本来完成构建的主要流程了。\n#!/bin/bash source /etc/profile # ##set color## echoRed() { echo $'\\e[0;31m'\u0026quot;$1\u0026quot;$'\\e[0m'; } echoGreen() { echo $'\\e[0;32m'\u0026quot;$1\u0026quot;$'\\e[0m'; } echoYellow() { echo $'\\e[0;33m'\u0026quot;$1\u0026quot;$'\\e[0m'; } ##set color## # version=`date +%Y%m%d%H%M%S` echo ------------------------------------- # 克隆项目并编译 echoGreen \u0026quot;开始进行mvn编译!\u0026quot; cd $WORKSPACE \u0026amp;\u0026amp; mvn clean install -DskipTests=true [ $? != 0 ] \u0026amp;\u0026amp; echoRed \u0026quot;请注意,在执行mvn编译时出错,故而退出构建,需开发同学自检代码!\u0026quot; \u0026amp;\u0026amp; exit 1 cd $WORKSPACE/target/ \u0026amp;\u0026amp; mv ishangjie-$project-$type-1.0.0.jar app.jar # 创建docker镜像 cat \u0026gt; run.sh \u0026lt;\u0026lt; EOF #!/bin/bash source /etc/profile java -jar /opt/app.jar --spring.profiles.active=test1 EOF chmod +x run.sh cat \u0026gt;Dockerfile \u0026lt;\u0026lt; EOF FROM 192.168.10.1/public/jdk:1.8 MAINTAINER eryajf \u0026lt;liqilong@edspay.com\u0026gt; ENV LANG en_US.UTF-8 ADD app.jar /opt/app.jar ADD run.sh / EXPOSE $port ENTRYPOINT [ \u0026quot;sh\u0026quot;, \u0026quot;-c\u0026quot;, \u0026quot;/run.sh\u0026quot; ] EOF # 构建镜像 echoGreen \u0026quot;开始构建当次镜像!\u0026quot; docker build -t 192.168.10.1/isj/$project:$version . [ $? != 0 ] \u0026amp;\u0026amp; echoRed \u0026quot;请注意,在执行镜像构建时出错,故而退出构建,请联系运维同学处理!\u0026quot; \u0026amp;\u0026amp; exit 1 # 上传到docker私服 echoGreen \u0026quot;开始将镜像push到私服!\u0026quot; docker push 192.168.10.1/isj/$project:$version [ $? != 0 ] \u0026amp;\u0026amp; echoRed \u0026quot;请注意,在执行镜像上传时出错,故而退出构建,请联系运维同学处理!\u0026quot; \u0026amp;\u0026amp; exit 1 docker rmi 192.168.10.1/isj/$project:$version #更新镜像 echoGreen \u0026quot;开始将最新镜像部署到远端!\u0026quot; rancher kubectl set image deployment/isj-$project isj-$project=192.168.10.1/isj/$project:$version -n isj-wfw [ $? != 0 ] \u0026amp;\u0026amp; echoRed \u0026quot;请注意,在执行镜像更新时出错,故而退出构建,请联系运维同学处理!\u0026quot; \u0026amp;\u0026amp; exit 1 echoGreen \u0026quot;部署完成!\u0026quot;  针对这个脚本有几点简单说明:\n 1,因为应用到了颜色输出,因此记得在构建环境当中开启color颜色输出。 2,尽量在关键地方添加一下判断,然后输出明了的内容以提高生产效率,比如编译有问题,直接退出构建,输出开发自检,如果是后边构建问题,同样退出构建,输出联系运维解决。 3,巧用cat的EOF特性,从而也可以将不同的变量控制进来。 4,尽量将所有构建过程的内容都写到Jenkins这里来,以便于后期问题排查与分析。 5,因为这是实验,因此没有添加回滚功能,如果添加的话,就针对mode参数做一个判断即可。  11,构建后操作。 因为是多个项目在同一个WORKSPACE下工作,因此,为了避免出现不可预知问题,这里添加了构建后清空WORKSPACE的选项。\n12,效果展示。 一切配置完成之后,就可以尝试一下点击构建了。\n好了,这就是本期的分享,当然,关于这个插件,这里也只是介绍了其中一种一个思路,可能还有很多种其他的方案,期待各位发挥思维发掘更多妙用。\n",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1050
        "auhtor": "eryajf",
1051 1052
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1053
        "poster": "./2019-06-26-使用Active-Choices-Plugin插件将十个Job合成一个/the_one.jpg"
1054 1055
    },
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-17-10-courses-to-learn-devops-engineering-in-depth/",
        "title": "10节课带你深入学习 DevOps 工程",
        "type": "wechat",
        "date": "2019-06-17 00:00:00 +0000 UTC",
        "tags": ["devops", "docker", "git", "AWS"],
        "description": "对那些想要涉足 DevOps 领域的工程师来说,这些多样的课程提供了一个很好的开始",
        "content": " DevOps 现在真的很热门,对于杰出的工程师和 DevOps 专业人员来说有许多工作机会。 如果你想成为一名 DevOps 工程师,那么你来对地方了。在本文中,我将分享一下最好的在线培训课程, 让你成为 DevOps 专业人员。\nDevops 最重要的优势,它可以帮助你更好地发布软件并且利用现代自动化工具对环境和软件开发过程中提供更多控制。这就是 DevOps 专业人员需求呈指数增长的原因。除了 Data Science 和 Machine Learning 外,它也是薪酬最高的 IT 工作之一。\n根据 Glassdoor 的数据,DevOps 的工程师每年的收入从105000美元到146000美元不等。这意味着,如果你正在寻找加薪或想在美好年纪从事一些令人兴奋的工作赚更多的钱,学习 DevOps 可能是一个不错的选择。\n学习像 Jenkins 这样的持续集成工具和像 Docker 这样的容器以及一般的 DevOps 技能,在技术领域获得了巨大的动力。这与几年前的移动应用程序开发类似。\n公司希望新的开发人员能够管理 Web 应用程序的整个生命周期。这意味着开发和部署应用程序。\n为了成为一名有效的 DevOps 工程师,您必须扩展对软件开发中使用的不同工具的知识,包括构建工具(如 Maven、 Ant 和 Gradle )、单元测试工具(如 Junit 和 Selenium )、部署工具(如 Docker )、监控工具(如 New Relic )、基础设施自动化工具(如 Chef 和 Puppet )、源代码控制工具,如 Git 和 Github,以及持续集成工具,如 Jenkins 和 TeamCity。这些课程为基本的 DevOps 工具提供了很好的介绍。\n十节面向经验丰富的开发人员 DevOps 课程 在不浪费更多时间的情况下,这里列出了一些学习 DevOps 的最佳课程以及在软件开发和部署过程中实现自动化所需的基本工具。\n1.学习路径:现代 DevOps DevOps 以一种全新的方式看待软件开发。您可以实现自动化,构建基础结构服务器的配置,然后解决自动化、连续部署、容器和监控方面的问题。\nGit、Docker 和 Puppet 是现代 DevOps 世界中最重要的工具,本课程将向您介绍这三种工具。\n简而言之,这是一门很好的入门课程,适用于系统管理员、开发人员和 IT 专业人员等 DevOps 领域的新手,还提供了对基本 DevOps 工具的良好概述。\n2.面向 DevOps 和开发者的 Docker 技术 Docker 是 DevOps 最重要的技术之一。它允许您将组件捆绑在一起,并将它们部署在任何平台(如 Linux 或 Windows )上的容器上。\n本课程涵盖了 Docker 软件的所有基础知识,并向您传授了开发和部署 Docker 现代应用程序所需的一切知识。\n3.Jenkins,从小白到专家:成为一名 DevOps JenKins 大师 Jenkins 可能是 DevOps 工程师进行持续集成工作的最重要工具。\n对于 DevOps 专业人员,具备持续检查、持续集成、持续部署的知识,且知道它们之间的区别是十分必要的。\n本课程涵盖了有关 Jenkins 的所有基础知识,并向您传授建立 Jenkins 构建管道所需的所有知识,从持续检查(构建、测试和静态分析)开始,一直到持续部署(待部署和生产)。\n4.学习 DevOps:完整的 Kubernetes 课程 当谷歌十年前开始运行容器时,没有人能够达到这种基础设施的灵活性和效率。利用这些知识,谷歌发布了 Kubernetes 作为一个免费的开源项目。\n如今,Kubernetes 被那些希望获得跟谷歌一样效率和速度的小公司和大企业使用。本课程将教您如何在 Kubernetes 上运行、部署、管理和维护容器化的 Docker 应用程序。\n5.学习 DevOps:持续发布更好的软件 这是关于 Udemy 的 DevOps 的最完整的课程之一,它将教授您 DevOps 工程师使用的大多数基本工具和技术。\n本课程面向这样的软件工程师和系统管理员:他们希望提供更好的软件,并帮助您在交付和部署过程中更好地使用 Git、Vagrant、Chef、Ansible、Jenkins、Docker 和 Kubernetes 这些工具。\n6.DevOps 课程的 Docker:从开发到生产 本课程向您展示了通过 Docker,您可以构建什么以及如何进行构建。除此之外,你还将学习 Docker 的基本知识!我们将一起讨论开发和部署多服务 Flask 和 Ruby on Rails 应用程序。\n7.学习 DevOps:使用 TerraForm 实现基础设施自动化 基础设施自动化是 DevOps 的一个重要组成部分。像 Ansible、Chef、Puppet 等工具都很有用,但 TerraForm 最近更受欢迎,如果您正在或即将成为一个 Ops/DevOps,您需要掌握这些工具,这就是本在线课程将帮助您的地方。\nTerraform 开始于相同的规则、基础设施即代码,但更专注于基础结构本身的自动化。您的整个云基础设施(实例、卷、网络、IP)在 TerraForm 中被描述。\n在本课程中,您将学习如何通过 TerraForm 以及 AWS、Packer、Docker、ECR、ECS 和 Jenkins 来实现自动化基础设施。\n8.使用 AWS codepipeline、Jenkins 和 AWS codedeploy 的 DevOps 如果您对什么是持续集成(CI)或持续交付/持续部署(CD)感到困惑,以及如何使用 Amazon Web 服务(如 AWS 和Jenkins)进行 DevOps,那么这是适合您的课程。\n在本课程中,您将学习必要的DevOps技能,以及在AWS云中的持续集成和持续交付。\n9.DevOps:用 Jenkins pipelines, Maven, Gradle 进行 CI/CD 本在线 DevOps 课程将教您如何使用 Jenkins 及它的一些插件(尤其是流水线插件),来构建复杂的持续集成和持续交付流水线。\n本课程旨在向您传授 Jenkins 的经验,并建立 DevOps 流水线,即使您几乎没有经验,也可以帮助您实现这些 DevOps 实践,从而简化您的开发过程。\n总之,用 Java、Gradle、Maven、AtdiPrand 和 Sqitch 构建的持续集成、持续交付和 DevOps 流水线是一个伟大的过程。\n10.用 Docker, Jenkins, GIT, Vagrant, 和 Maven 完成 DevOps 如果您正在寻找一个实践 DevOps 课程,它不仅可以向您解释 DevOps 工程师的角色,而且可以提供关于基本 DevOps 工具的实践经验,那么这是您的课程。\n它提供了一个关于 DevOps 基本技术的完整教程。您将通过实践指导学习 Docker Mastery、Jenkins、Git、Vagrant 和 Maven。\n正如我所说,对优秀的 DevOps 工程师和软件开发人员的需求呈指数级增长,市场上没有足够的 DevOps 专业人员来支持这一需求。\n这意味着这是一个学习 DevOps 并进入这个更负责任、高薪和令人兴奋的领域的绝佳机会。如果你打算在2019年成为一名 DevOps 工程师,那么这些课程是一个很好的起点。\n如果你喜欢这些 DevOps 课程,请与你的朋友和同事分享。如果您有任何问题或反馈,请留言。\n",
        "auhtor": "Javin Paul",
        "translator": "linan607",
        "original": "https://dzone.com/articles/10-courses-to-learn-devops-in-2019",
        "poster": "./2019-06-17-10-courses-to-learn-devops-engineering-in-depth/devops.jpg"
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1068
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1069 1070 1071 1072 1073 1074
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-14-setup-jenkins-ci-in-30-minutes/",
        "title": "30分钟搞定 Jenkins CI",
        "type": "wechat",
        "date": "2019-06-14 00:00:00 +0000 UTC",
        "tags": ["jenkins", "ci"],
        "description": "设置新的 Jenkins CI,以便可以开始测试新的 Jenkins 插件",
1075
        "content": " 你想在本地设置中使用 Jenkins CI 进行实验吗?在本文中,我们将设置一个本地 Jenkins CI 服务,为一个简单的 Spring Boot Maven 项目创建一个构建工作,并将创建的 Docker 镜像推送到 DockerHub。这将是一个本地实验的设置,但如果你想尝试一个 Jenkins 插件,它会非常方便。\n1.先决条件 开始之前,我们需要以下先决条件:\n 我们使用了 Ubuntu 18.04; 必须安装 Docker,有关安装说明,请参见此处; 我们需要在 Docker registry 来推送我们的 Docker 镜像。最简单的方法是在DockerHub上创建一个帐户。你可以免费创建帐户。也不会收到垃圾广告邮件; 构建工作的 Spring Boot 应用程序。我们将使用前一篇文章中的 Spring Boot MVC 应用程序。源代码可以在GitHub上找到,相应的Docker图像可以在DockerHub上找到。该应用程序包含 http://localhost:8080/hello 上的一个 HTTP 端点,并只返回一条 Hello Kubernetes 欢迎消息。  2.运行 Jenkins CI 我们将使用 Jenkins CI Docker 官方镜像运行 Jenkins 服务。完整的文档可以在这里找到。用以下命令启动容器:\n$ docker run -p 8080:8080 --name myjenkins -v jenkins_home:/var/jenkins_home -v jenkins_downloads:/var/jenkins_home/downloads jenkins/jenkins:lts  让我们来仔细看看我们正在做什么:\n -p 8080:8080:我们将内部 Jenkins 端口(冒号后)映射到外部端口,该端口可从我们的 Docker 主机访问; \u0026ndash;name myjenkins:我们为容器提供一个名称;否则,Docker将为你生成一个名称。最好给它起个名字;这样,你可以轻松地启动和停止容器; -v jenkins_home:/var/jenkins_home:我们希望将内部 Jenkins 主目录(冒号之后)映射到 Docker 主机上的一个目录。通过这种方式,Jenkins 数据将被保存在我们的主机上,这让我们有机会备份数据; -v jenkins_downloads:/var/jenkins_home/downloads:我们需要在Jenkins中安装额外的工具; 因此,我们创建一个目录来复制 *.tar.gz 文件。在这篇文章的后面,我们将清楚地知道我们将使用目录做什么; jenkins/jenkins:lts:要使用的 Docker 镜像。我们将使用 LTS 版本,但如果你愿意,也可以使用不太稳定的版本。在撰写本文时,v2.150.1 是 LTS 版本。 在此之后,你可以通过其名称停止和启动容器:  $ docker stop myjenkins $ docker start myjenkins  3.配置 Jenkins 以供首次使用 一旦容器启动后,我们就可以访问 Jenkins Web 控制台了。当然,我们需要知道 Jenkins 实例的 IP 地址。因此,请执行以下命令:\n$ docker inspect myjenkins  这将显示一些 JSON 输出。转到该 Networks 部分,参数 IPAddress 显示我们的 Jenkins IP 地址(在我们的例子中为172.17.0.3):\n\u0026quot;Networks\u0026quot;: { \u0026quot;bridge\u0026quot;: { \u0026quot;IPAMConfig\u0026quot;: null, ... \u0026quot;IPAddress\u0026quot;: \u0026quot;172.17.0.3\u0026quot;, ... \u0026quot;DriverOpts\u0026quot;: null } }  Jenkins Web 控制台可通过浏览器访问 http://172.17.0.3:8080/。\n这将向我们显示以下页面:\n我们使用临时密码,启动容器后在控制台输出中显示:\n************************************************************* ************************************************************* ************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: f586346583e04fa78e2cc8edbf7566e1 This may also be found at: /var/jenkins_home/secrets/initialAdminPassword ************************************************************* ************************************************************* *************************************************************  输入临时密码后,将显示一个页面,在这里我们可以选择要安装的默认插件集或自定义插件集。我们将选择默认设置。\n现在,坐等插件安装好:\n接下来,创建第一个管理员用户:\n最后,配置 Jenkins 实例:\n太棒了!Jenkins 现在已经准备好可以使用了:\n4.安装所需的工具 我们的构建需要在 Jenkins 中提供一些工具。我们需要 JDK11,Maven 和 Docker。在下一节中,我们将展示如何在容器中使用这些属性。\n在启动容器期间,我们在容器中创建了 /var/jenkins_home/downloads 的挂载卷。首先,我们将验证是否可以从容器中访问此路径。执行以下命令:\n$ docker exec -it myjenkins ls -l /var/jenkins_home/downloads total 0  如上所述返回0个结果时,那么我们就可以继续了。否则,你必须检查在启动容器期间是否输入正确。\n4.1 安装 JDK 11 我们将使用 Adopt OpenJDK 11,可在此处下载。我们必须将下载的 *.tar.gz 文件复制到已安装在主机上的卷 jenkins_home/downloads 中。为了检索我们机器上的路径,我们再次执行 docker inspect 命令,就像以前检索Jenkins IP地址一样。这一次,转到分段 Mounts:\n\u0026quot;Mounts\u0026quot;: [ ... { \u0026quot;Type\u0026quot;: \u0026quot;volume\u0026quot;, \u0026quot;Name\u0026quot;: \u0026quot;jenkins_downloads\u0026quot;, \u0026quot;Source\u0026quot;: \u0026quot;/var/lib/docker/volumes/jenkins_downloads/_data\u0026quot;, \u0026quot;Destination\u0026quot;: \u0026quot;/var/jenkins_home/downloads\u0026quot;, ... } ],  在我们的示例中,卷位于 /var/lib/docker/volumes/jenkins_downloads/_data 上。将 *.tar.gz 文件复制到此位置。\n跳转到 Manage Jenkins – Global Tool Configuration 和 *JDK 安装部分*。单击 Add JDK 按钮。默认情况下,java.sun.com 会添加安装程序。我们不会使用这个,所以删除它并添加一个 Extract *.zip/*.tar.gzinstaller。根据下面的屏幕截图填写字段。二进制存档的路径是 file:/var/jenkins_home/downloads/OpenJDK11U-jdk_x64_linux_hotspot_11.0.1_13.tar.gz。Label 留空是很重要的;否则,JDK的安装将失败。\n跳转到 *Manage Jenkins – Configure System*,到 Global properties 部分并启用 *环境变量*。为其添加环境变量 JAVA_HOME 并填充路径 /var/jenkins_home/tools/hudson.model.JDK/JDK11/jdk-11.0.1+13。\n4.2 安装 Maven 我们将使用 Maven 3.6.0,可以在这里下载。安装过程与 JDK 安装相同:下载 *.tar.gz 文件并将其复制到 jenkins_home/downloads。\n转到 Manage Jenkins – Global Tool Configuration 和 Maven 安装部分。单击 Add Maven 按钮。默认情况下,Apache 会添加安装程序。我们不会使用这个,所以删除它并添加一个 Extract *.zip/*.tar.gzinstaller。根据下面的屏幕截图填写字段。二进制存档的路径是 file:/var/jenkins_home/downloads/apache-maven-3.6.0-bin.tar.gz。Label 留空是很重要的;否则,Maven 的安装将失败。将子目录设置为 apache-maven-3.6.0 也很重要;否则,Maven 主目录没有正确设置,mvn 可执行文件将无法找到。\n4.3 配置 Docker 在 Docker 内部安装 Docker 不是一个好主意,请参阅本文。因此,我们将使用宿主机的 Docker 安装,并将宿主机的 Docker 套接字挂载到容器。实际上,这也不是一个好主意,但是对于我们的 Jenkins 实验环境来说,这是可以的,但是出于安全原因,永远不要以这种方式暴露 Docker 套接字。\n我们删除现有的容器(这不是有害的,因为我们的所有数据都保存在我们的主机上,我们不会丢失任何数据),然后使用 -v /var/run/docker.sock:/var/run/docker.sock 重新启动容器。\n$ docker rm myjenkins $ docker run -p 8080:8080 --name myjenkins -v /var/run/docker.sock:/var/run/docker.sock -v jenkins_home:/var/jenkins_home -v jenkins_downloads:/var/jenkins_home/downloads jenkins/jenkins:lts  为了使其工作,我们还必须设置 docker.sock 的权限给 jenkins 用户。默认情况下,它被挂载为 root,因此,由于 Permission Denied 错误,我们的构建将失败。\n以 root 身份登录 Docker 容器:\n$ docker exec -it -u root myjenkins  检查权限 docker.sock,这表明它拥有者 root:\n$ ls -l /var/run/docker.sock srw-rw---- 1 root 999 0 Jan 6 11:45 /var/run/docker.sock  让 jenkins 成为新所有者,并再次列出权限:\n$ chown jenkins: /var/run/docker.sock $ ls -l /var/run/docker.sock srw-rw---- 1 jenkins jenkins 0 Jan 6 11:45 /var/run/docker.sock  现在,jenkins 是所有者,我们不会再得到 Permission Denied 的错误。\n为了将 Docker 镜像推入 Docker registry,我们需要通过 settings.xml 将凭据提供给 Maven。我们可以通过配置文件提供程序插件轻松地提供 settings.xml。去 Manage Jenkins – Manage plugins 并安装插件(不重启安装)。\n转到 *Manage Jenkins – Managed files*,然后单击 *Add a new Config*。创建 Global Maven settings.xml 并使用 DockerHub 帐户凭据添加以下部分:\n\u0026lt;servers\u0026gt; \u0026lt;server\u0026gt; \u0026lt;id\u0026gt;docker.io\u0026lt;/id\u0026gt; \u0026lt;username\u0026gt;docker_username\u0026lt;/username\u0026gt; \u0026lt;password\u0026gt;docker_password\u0026lt;/password\u0026gt; \u0026lt;/server\u0026gt; \u0026lt;/servers\u0026gt;  5.创建构建工作 最后要做的是创建我们的构建工作。转到 Jenkins CI 主页,然后单击 *New Item*。我们将把构建工作命名为 *MyKubernetesPlanet*,并选择一个 *Freestyle Project*。\n在构建工作的配置部分,我们转到 Source Code Management 部分,并填写 Git URL https://github.com/mydeveloperplanet/mykubernetesplanet.git 和 branch */feature/jenkinsci。\n在 Build 部分,我们添加了一个 Invoke top-level Maven targets 的构建步骤。我们将调用以下 Maven 目标来构建我们的应用程序并将 Docker 镜像推送到 Docker registry:\n$ clean install dockerfile:push  我们还需要设置之前创建的 Maven版本 和 *全局配置文件*。\n手动为我们的工作启动构建,这将创建 jar 文件,创建我们的 Docker 镜像,并将其推送到 Docker registry。\n6.结论 在本文中,我们提供了一种让 Jenkins 实例运行的快速方法,包括执行 Maven 构建、创建 Docker 镜像并将其推入 Docker registry 的构建作业。请注意,这不是一种安全的方法,但是对于实验用例来说,它并没有太大的危害。现在我们已经有了一个完全运行的 Jenkins 实例,我们可以使用它来测试新的 Jenkins 插件。\n",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
        "auhtor": "Gunter Rotsaert",
        "translator": "yJunS",
        "original": "https://dzone.com/articles/setup-jenkins-ci-in-30-minutes",
        "poster": "./2019-06-15-setup-jenkins-ci-in-30-minutes/788b731c3a30bba88e622c162ec0ea54.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-10-jenkins-pipeline-workshop/",
        "title": "还在苦恼不会写 Jenkins 流水线?来场工作坊!",
        "type": "wechat",
        "date": "2019-06-10 00:00:00 +0000 UTC",
        "tags": ["jenkins", "pipeline"],
        "description": "Jenkins 中文社区2019第一场工作坊",
        "content": "前段时间,Jenkins 中文社区建了一个“Jenkins 中文社区技术交流”的微信群。\n群里不温不火,不时有人抛出几个关于 Jenkins 流水线的问题。比如以下聊天记录:\n而这些问题都共同说明另一个问题:Jenkins 的流水线的普及度还很低。大家都苦恼着不知道如何写 Jenkins 流水线呢。\n所以,Jenkins 中文社区决定6月22日组织一场工作坊,手把手教大家如何写 Jenkins pipeline。工作坊内容包括: * 流水线基础讲解及其练习。 * 流水线高级部分讲解及其练习。 * 案例实战(注意啦,可是有案例的。不是虚的。)\n问题来了?谁是这次工作坊的教练呢?\n赵晓杰:jenkinsci Contributor,Jenkins 中文社区发起人。\n想参加的同学,请点击阅读原文报名参加。\n如果无法现场参加的同学可以发邮件至 events@mail.jenkins-zh.cn 申请 ZOOM 网络会议接入。另,我们鼓励由一人申请,并组织好其他人一起参与。这样多人一起进行工作坊,效果更佳。申请邮件中写明:申请人所在公司、地点、参与人数。\n对了想入伙加群?很简单,Jenkins 公众号后台回复“微信群”,扫码入群。趁现在群没满,你懂的!~\n",
        "auhtor": "jenkins-zh-robot",
1090 1091
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1092
        "poster": "pipeline-example.png"
LinuxSuRen's avatar
LinuxSuRen 已提交
1093
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1094
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1095 1096 1097 1098 1099 1100 1101 1102
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-09-github-share/",
        "title": "在线分享 - 作为一名开源贡献者是如何使用 GitHub 的?",
        "type": "wechat",
        "date": "2019-06-09 00:00:00 +0000 UTC",
        "tags": ["在线分享"],
        "description": "这是一场开源事业有缘人的在线分享、交流会",
        "content": " 本次在线分享活动,是由 Jenkins 中文社区与开源社共同发起,旨在向每一位有意了解、参与开源社区活动的朋友们普及 GitHub 的使用。\nGitHub 作为全球最大、最为专业的开源社交平台,不仅仅是研发或者技术相关岗位人员的专利,文案、市场相关同学同样可以利用这个 有着无限潜力的开源平台来为开源事业贡献自己的一份绵薄之力。\n社区重于代码,这是很多资深开源人士的共同观点。除了可以在 GitHub 上托管我们的源代码之外,到底还可以让 GitHub 为大家所在的 开源社区、项目提供哪些便利的服务呢?除了如何使用 GitHub 以外,这也是我希望与大家分享、共同探讨的。\n分享人 瑞克,Jenkins 中文社区发起人,热衷于传播开源理念、开源技术。多年研发经验, 目前关注于 DevOps 领域,尤其是持续交付方面。\n分享概要  GitHub 基本介绍  常用功能 开源礼仪  非技术类使用概要  熟悉一个项目 了解如何做贡献 常规的贡献流程  更高效的实践经验  Git 基本介绍 客户端利器 hub 的几种模式  互动环节  合作企业 平安云 GitHub\n报名 感兴趣的同学,请及时点击“阅读原文“进行报名,名额有限。我们会在活动前通过邮件的方式告知参与链接。\n活动时间为:2019年6月14日 19:00~20:00\n注意事项 为了能够让大家能够共同完成一次高效的在线分享活动,请各位准备参加的同学仔细阅读下面的事项:\n 提前安排好时间,找一个安静的环境 检查网络是否通畅 准备好你的问题或者疑问 安装好客户端 https://github.com/github/hub 有任何技术细节、疑问,请关注 Jenkins 公众号,回复:微信群  ",
        "auhtor": "linuxsuren",
1103 1104
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1105
        "poster": "./github.jpg"
LinuxSuRen's avatar
LinuxSuRen 已提交
1106
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1107
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1108 1109
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-05-devops-challenges-in-2019-how-to-overcome-them/",
        "title": "2019年 DevOps 面临的挑战以及如何战胜它们",
1110
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1111 1112 1113 1114 1115 1116 1117 1118
        "date": "2019-06-05 00:00:00 +0000 UTC",
        "tags": ["devops"],
        "description": "新的 DevOps 采用者应该意识到他们在使用 DevOps 时会面临的一些挑战",
        "content": " 随着 DevOps 逐渐成为主流,许多团队都在问自己应该从哪里开始采用 DevOps , 他们将在此过程中面临哪些挑战,以及如何解决那些挑战。 每年都有越来越多的公司希望从传统的瀑布式方法转向 DevOps 。\n许多软件开发公司将 DevOps 看作是一个公司在效率方面所能达到的顶峰,并且这有点难。 应对挑战可能大大降低你的生产力,同时适应 DevOps 方法会导致各种自动化工具和开发过程之间缺乏协调。\n在本文中,我们将讨论 DevOps 在2019年面临的一些重大挑战,以及可以采取哪些措施来战胜它们。\n关注遗留的应用程序和系统 DevOps 团队面临的第一个和主要挑战涉及到遗留应用程序的构建, 这些应用程序是在没有考虑 DevOps 的情况下构建的。 这似乎看起来有益无害,但这对于转变来说是相当棘手的。 即使你关注使用 DevOps 的新应用程序和系统,你也需要维护这些遗留系统。\n对于遗留应用程序的转变这里还有其他原因。 一开始,你需要努力逐步将淘汰它们,或者逐渐将客户转移到使用 DevOps 系统维护的新版本。 否则,你可以尝试创建一个新的系统来维护遗留的应用程序,它不会干扰你的 DevOps 系统。 你也可以使用 Scala 性能度量工具,比如 AppOptics ,它有助于逐步淘汰非 DevOps 系统。\n选择适合的项目 对于一个新的 DevOps 团队来说,为每个新项目选择 DevOps 似乎很明智,但事实并非总是如此。 DevOps 不是强制性的,因为如果没有正确地实现 DevOps ,有时会降低整个生产过程的速度。 因此,在选择要使用 DevOps 的项目时,你应该非常勤奋。 在考虑 DevOps 是否必要时,最好记住 DevOps 是一种运营策略,并不总是适合的。\n如果你正在努力快速规模化的软件,并从其敏捷性中获得更快的速度,那么 DevOps 是一个明智的选择。 同样地,DevOps 并不是一直起作用,所以不应该把它当作解决所有问题的首选解决方案。 例如,如果你正在使用一个较旧的系统,那么最好坚持使用旧的方法和流程,因为不可能总是为这些方法和流程找到自动化的系统。\n除此之外,规划和设计工作被认为不适合 DevOps ,因为进行设计和 UX 是处理流程的更成功的方法,而不是不断改进。\n性能测试 有一点没有改变,那就是随着用户期望的提高,对广泛测试的需求也在增加。 多亏了 DevOps ,现在可以更快地创建和发布产品了,但是你不应该在发布之前对足够的产品测试作出牺牲。\nDevOps 擅长多种事情,但是就 bug 而言,它也有一些限制。 幸运的是,有大量的工具,例如 Tricentis 和 Zephyr ,可以帮助你确保发布的产品的最高性能。\n难以捉摸的人的问题 通过对 DevOps 的各种研究,许多团队还在与一个叫做\u0026rdquo;人的问题\u0026rdquo;的挑战作斗争,这真是一个奇迹。 当开发人员创建一个 DevOps 无法启动的环境时,问题就会在开发人员和管理人员之间出现。 这种问题始于缺乏经验,因为许多团队只是因为新奇事物综合症而采用 DevOps ,最终会经历灾难。\n另一个障碍可能是缺乏糟糕的领导,因为 DevOps 团队需要有足够的自由来为项目做出战略决策。 在强大领导的支持下,你可以通过培训整个开发和运营团队来进行 DevOps 工作。\n2019年DevOps的前景如何? DevOps 有望在2019年占据开发者心目中的最高位置,原因显而易见。 DevOps 方法为自动化和不断改进找到了空间,这在现代技术世界中是至关重要的。\n正如我们上面所讨论的,在接下来的一年里,仍然有许多挑战威胁着许多团队 DevOps 的成功。 如果你正在考虑 DevOps 或寻找更好的方法来改进策略并接受上述挑战, 那么你可以通过适当的耐心和承诺更好地解决这些问题。不断学习!\n",
        "auhtor": "Herman Morgan",
        "translator": "donhui",
        "original": "https://dzone.com/articles/devops-challenges-in-2019-how-to-overcome-them",
        "poster": "./2019-06-05-devops-challenges-in-2019-how-to-overcome-them/xian.jpg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1119
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1120
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1121 1122 1123 1124 1125 1126 1127 1128
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-29-jenkins-release/",
        "title": "Jenkins 2.176~2.178版本更新",
        "type": "wechat",
        "date": "2019-05-29 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "Jenkins 每周更新版2.176~2.178更新内容",
        "content": " 2.178 (2019-05-20)  将 jmDNS 从3.4.0-jenkins-3更新到3.5.5,以防止不必要的 DNS 组播错误消息。 (issue 25369) 将 WinP 从1.27更新到1.28,以修复 Windows 优雅进程关闭逻辑中缺少 DLL 和控制台窗口闪烁的问题。 (issue 57477, 完整的变更日志) 确保独立的插件(插件曾经是 Jenkins 本身的一部分功能)在 Jenkins 启动时(需要时)作为已经存在的其他插件的隐含依赖项安装。 这简化了不使用更新中心的特殊安装场景的兼容性,例如当 Jenkins 从预先打包了一些插件的 Docker 镜像运行时。 (issue 57528) 将脚本安全插件的捆绑版本与最新的安全警告一起更新,在不太可能的情况下,它确实是从 WAR 而不是更新中心安装的。 (pull 4000)  2.177 (2019-05-12)  支持在流水线或其它任务类型的 fingerprint() 构建步骤中设置排除和区分大小写。 (文档, pull 3915) 允许通过不同的阴影构建球区分新任务、禁用的任务和中止构建的任务。 (pull 3997) 将 Windows 代理安装程序从1.10.0更新到1.11,当在 .NET 4.6 或更新版本运行时,在代理下载时启用 TLS 1.2。 (issue 51577, 完整的变更日志) 将 Winstone-Jetty 从5.2更新到5.3以更新 Jetty 到 9.4.18。 (pull 4016, 完整的变更日志, Jetty 9.4.18变更日志, Jetty 9.4.17变更日志, Jetty 9.4.16变更日志) 恢复安装向导使用的中文本地化资源。(在2.176中回归)。 (issue 57412) 健壮性:对于 ComputerListener#onOnline() 中的运行时异常,不要将代理脱机。 (issue 57111) 由于排除筛选,不要为存档制品中不包含的文件记录指纹。 (issue 41696) 开发者:使 UserSeedProperty 对插件开发人员可用。 (pull 4018) 开发者:添加对 titleClassMethod 的支持(从流水线中的 symbol-hetero-list )到 f:hetero-list. (issue 56379)  2.176 (2019-05-05)  在 2.175 中有些插件可能会失败,并会有一个与序列化 FilePath 有关的错误。 现在,这已被降级为警告。 插件更新仍然应该被用来修正潜在的错误。 (issue 57244) 添加 stop-job CLI命令,该命令允许中止构建。 (issue 11888) 将 Remoting 从3.29更新到3.30,以修复一些较小的问题。 (issue 51004, issue 57107, issue 46515, 完整的变更日志) 将所有中文本地化资源迁移到本地化:中文(简体)插件。 (pull 4008) 当 Jenkins#addNode 或 Nodes#addNode 实际替换现有节点时,NodeListener#onCreated 被调用。 (issue 57273) 开发者:在 classpath 中包含 CLI 模块生成的源文件。 (pull 4006)  ",
        "auhtor": "donhui",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1129 1130
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1131
        "poster": "“./2019-05-29-jenkins-release/qingshanlake.jpg”"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1132 1133
    },
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1134 1135 1136 1137 1138 1139
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-28-jenkins-pipeline-shared-lib-unit-test/",
        "title": "如何对 Jenkins 共享库进行单元测试",
        "type": "wechat",
        "date": "2019-05-28 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "包括该单元测试框架的原理介绍",
1140
        "content": " Jenkins 共享库是除了 Jenkins 插件外,另一种扩展 Jenkins 流水线的技术。通过它,可以轻松地自定义步骤,还可以对现有的流水线逻辑进行一定程度的抽象与封装。至于如何写及如何使用它,读者朋友可以移步附录中的官方文档。\n对共享库进行单元测试的原因 但是如何对它进行单元测试呢?共享库越来越大时,你不得不考虑这个问题。因为如果你不在早期就开始单元测试,共享库后期可能就会发展成如下图所示的“艺术品”——能工作,但是脆弱到没有人敢动。\n[图片来自网络,侵权必删]\n这就是代码越写越慢的原因之一。后人要不断地填前人有意无意挖的坑。\n共享库单元测试搭建 共享库官方文档介绍的代码仓库结构 (root) +- src # Groovy source files | +- org | +- foo | +- Bar.groovy # for org.foo.Bar class +- vars | +- foo.groovy # for global 'foo' variable | +- foo.txt # help for 'foo' variable +- resources # resource files (external libraries only) | +- org | +- foo | +- bar.json # static helper data for org.foo.Bar  以上是共享库官方文档介绍的代码仓库结构。整个代码库可以分成两部分:src 目录部分和 vars 目录部分。它们的测试脚手架的搭建方式是不一样的。\nsrc 目录中的代码与普通的 Java 类代码本质上没有太大的区别。只不过换成了 Groovy 类。\n但是 vars 目录中代码本身是严重依赖于 Jenkins 运行时环境的脚本。\n接下来,分别介绍如何搭建它们的测试脚手架。\n测试 src 目录中的 Groovy 代码 在对 src 目录中的 Groovy 代码进行单元测试前,我们需要回答一个问题:使用何种构建工具进行构建?\n我们有两种常规选择:Maven 和 Gradle。本文选择的是前者。\n接下来的第二个问题是,共享库源代码结构并不是 Maven 官方标准结构。下例为标准结构:\n├── pom.xml └── src ├── main │ ├── java │ └── resources └── test ├── java └── resources  因为共享库使用的 Groovy 写的,所以,还必须使 Maven 能对 Groovy 代码进行编译。\n可以通过 Maven 插件:GMavenPlus 解决以上问题,插件的关键配置如下:\n\u0026lt;configuration\u0026gt; \u0026lt;sources\u0026gt; \u0026lt;source\u0026gt; \u0026lt;!-- 指定Groovy类源码所在的目录 --\u0026gt; \u0026lt;directory\u0026gt;${project.basedir}/src\u0026lt;/directory\u0026gt; \u0026lt;includes\u0026gt; \u0026lt;include\u0026gt;**/*.groovy\u0026lt;/include\u0026gt; \u0026lt;/includes\u0026gt; \u0026lt;/source\u0026gt; \u0026lt;/sources\u0026gt; \u0026lt;testSources\u0026gt; \u0026lt;testSource\u0026gt; \u0026lt;!-- 指定单元测试所在的目录 --\u0026gt; \u0026lt;directory\u0026gt;${project.basedir}/test/groovy\u0026lt;/directory\u0026gt; \u0026lt;includes\u0026gt; \u0026lt;include\u0026gt;**/*.groovy\u0026lt;/include\u0026gt; \u0026lt;/includes\u0026gt; \u0026lt;/testSource\u0026gt; \u0026lt;/testSources\u0026gt; \u0026lt;/configuration\u0026gt;  同时,我们还必须加入 Groovy 语言的依赖:\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.codehaus.groovy\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;groovy-all\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${groovy-all.version}\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt;  最终目录结构如下图所示: 然后我们就可以愉快地对 src 目录中的代码进行单元测试了。\n测试 vars 目录中 Groovy 代码 对 vars 目录中的脚本的测试难点在于它强依赖于 Jenkins 的运行时环境。换句话说,你必须启动一个 Jenkins 才能正常运行它。但是这样就变成集成测试了。那么怎么实现单元测试呢?\n经 Google 发现,前人已经写了一个 Jenkins 共享库单元测试的框架。我们拿来用就好。所谓,前人载树,后人乘凉。\n这个框架叫:Jenkins Pipeline Unit testing framework。后文简称“框架”。它的使用方法如下:\n 在 pom.xml 中加入依赖: xml \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.lesfurets\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;jenkins-pipeline-unit\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.1\u0026lt;/version\u0026gt; \u0026lt;scope\u0026gt;test\u0026lt;/scope\u0026gt; \u0026lt;/dependency\u0026gt;  写单元测试\n// test/groovy/codes/showme/pipeline/lib/SayHelloTest.groovy // 必须继承 BasePipelineTest 类 class SayHelloTest extends BasePipelineTest { @Override @Before public void setUp() throws Exception { // 告诉框架,共享库脚本所在的目录 scriptRoots = [\u0026quot;vars\u0026quot;] // 初始化框架 super.setUp() } @Test void call() { // 加载脚本 def script = loadScript(\u0026quot;sayHello.groovy\u0026quot;) // 运行脚本 script.call() // 断言脚本中运行了 echo 方法 // 同时参数为\u0026quot;hello pipeline\u0026quot; assertThat( helper.callStack .findAll { c -\u0026gt; c.methodName == 'echo' } .any { c -\u0026gt; c.argsToString().contains('hello pipeline') } ).isTrue() // 框架提供的方法,后面会介绍。 printCallStack() } }    创建单元测试时,注意选择 Groovy 语言,同时类名要以 Test 结尾。\n  改进 以上代码是为了让读者对共享库脚本的单元测试有更直观的理解。实际工作中会做一些调整。我们会将 extends BasePipelineTest 和 setUp 方法抽到一个父类中,所有其它测试类继承于它。  此时,我们最简单的共享库的单元测试脚手架就搭建好了。\n但是,实际工作中遇到场景并不会这么简单。面对更复杂的场景,必须了解 Jenkins Pipeline Unit testing framework 的原理。由此可见,写单元测试也是需要成本的。至于收益,仁者见仁,智者见智了。\nJenkins Pipeline Unit testing framework 原理 上文中的单元测试实际上做了三件事情: 1. 加载目标脚本,loadScript 方法由框架提供。 2. 运行脚本,loadScript 方法返回加载好的脚本。 3. 断言脚本中的方法是否有按预期执行,helper 是 BasePipelineTest 的一个字段。\n从第三步的 helper.callStack 中,我们可以猜到第二步中的script.call() 并不是真正的执行,而是将脚本中方法调用被写到 helper 的 callStack 字段中。从 helper 的源码可以确认这一点:\n/** * Stack of method calls of scripts loaded by this helper */ List\u0026lt;MethodCall\u0026gt; callStack = []  那么,script.call() 内部是如何做到将方法调用写入到 callStack 中的呢?\n一定是在 loadScript 运行过程做了什么事情,否则,script 怎么会多出这些行为。我们来看看它的底层源码:\n/** * Load the script with given binding context without running, returning the Script * @param scriptName * @param binding * @return Script object */ Script loadScript(String scriptName, Binding binding) { Objects.requireNonNull(binding, \u0026quot;Binding cannot be null.\u0026quot;) Objects.requireNonNull(gse, \u0026quot;GroovyScriptEngine is not initialized: Initialize the helper by calling init().\u0026quot;) Class scriptClass = gse.loadScriptByName(scriptName) setGlobalVars(binding) Script script = InvokerHelper.createScript(scriptClass, binding) script.metaClass.invokeMethod = getMethodInterceptor() script.metaClass.static.invokeMethod = getMethodInterceptor() script.metaClass.methodMissing = getMethodMissingInterceptor() return script }  gse 是 Groovy 脚本执行引擎 GroovyScriptEngine。它在这里的作用是拿到脚本的 Class 类型,然后使用 Groovy 语言的 InvokerHelper 静态帮助类创建一个脚本对象。\n接下来做的就是核心了:\nscript.metaClass.invokeMethod = getMethodInterceptor() script.metaClass.static.invokeMethod = getMethodInterceptor() script.metaClass.methodMissing = getMethodMissingInterceptor()  它将脚本对象实例的方法调用都委托给了拦截器 methodInterceptor。Groovy 对元编程非常友好。可以直接对方法进行拦截。拦截器源码如下:\n/** * Method interceptor for any method called in executing script. * Calls are logged on the call stack. */ public methodInterceptor = { String name, Object[] args -\u0026gt; // register method call to stack int depth = Thread.currentThread().stackTrace.findAll { it.className == delegate.class.name }.size() this.registerMethodCall(delegate, depth, name, args) // check if it is to be intercepted def intercepted = this.getAllowedMethodEntry(name, args) if (intercepted != null \u0026amp;\u0026amp; intercepted.value) { intercepted.value.delegate = delegate return callClosure(intercepted.value, args) } // if not search for the method declaration MetaMethod m = delegate.metaClass.getMetaMethod(name, args) // ...and call it. If we cannot find it, delegate call to methodMissing def result = (m ? this.callMethod(m, delegate, args) : delegate.metaClass.invokeMissingMethod(delegate, name, args)) return result }  它做了三件事情: 1. 将调用方法名和参数写入到 callStack 中 2. 如果被调用方法名是被注册了的方法,则执行该方法对象的 mock。下文会详细介绍。 3. 如果被调用方法没有被注册,则真正执行它。\n需要解释一个第二点。并不是所有的共享库中的方法都是需要拦截的。我们只需要对我们感兴趣的方法进行拦截,并实现 mock 的效果。\n写到这里,有些读者朋友可能头晕了。笔者在这里进行小结一下。\n 因为我们不希望共享库脚本中的依赖于 Jenkins 运行时的方法(比如拉代码的步骤)真正运行。所以,我们需要对这些方法进行 mock。在 Groovy 中,我们可以通过方法级别的拦截来实现 mock 的效果。 但是我们又不应该对共享库中所有的方法进行拦截,所以就需要我们在执行单元测试前将自己需要 mock 的方法进行注册到 helper 的 allowedMethodCallbacks 字段中。methodInterceptor拦截器会根据它来进行拦截。\n 在 BasePipelineTest 的 setUp 方法中,框架注册了一些默认方法,不至于我们要手工注册太多方法。以下是部分源码:\nhelper.registerAllowedMethod(\u0026quot;sh\u0026quot;, [Map.class], null) helper.registerAllowedMethod(\u0026quot;checkout\u0026quot;, [Map.class], null) helper.registerAllowedMethod(\u0026quot;echo\u0026quot;, [String.class], null)  registerAllowedMethod 各参数的作用: * 第一个参数:要注册的方法。 * 第二参数:该方法的参数列表。 * 第三参数:一个闭包。当该访问被调用时会执行此闭包。\n以上就是框架的基本原理了。接下来,再介绍几种场景。\n几种应用场景 环境变量 当你的共享库脚本使用了 env 变量,可以这样测试:\nbinding.setVariable('env', new HashMap()) def script = loadScript('setEnvStep.groovy') script.invokeMethod(\u0026quot;call\u0026quot;, [k: '123', v: \u0026quot;456\u0026quot;]) assertEquals(\u0026quot;123\u0026quot;, ((HashMap) binding.getVariable(\u0026quot;env\u0026quot;)).get(\u0026quot;k\u0026quot;))  binding 由 BasePipelineTest 的一个字段,用于绑定变量。binding 会被设置到 gse 中。\n调用其它共享库脚本 比如脚本 a 中调用到了 setEnvStep。这时可以在 a 执行前注册 setEnvStep 方法。\nhelper.registerAllowedMethod(\u0026quot;setEnvStep\u0026quot;, [LinkedHashMap.class], null)  希望被 mock 的方法能有返回值 helper.registerAllowedMethod(\u0026quot;getDevOpsMetadata\u0026quot;, [String.class, String.class], { return \u0026quot;data from cloud\u0026quot; })  后记 不得不说 Jenkins Pipeline Unit testing framework 框架的作者非常聪明。另外,此类技术不仅可以用于单元测试。理论上还可以用于 Jenkins pipeline 的零侵入拦截,以实现一些平台级特殊的需求。\n附录  共享库官方文档:https://jenkins.io/zh/doc/book/pipeline/shared-libraries/ 本文示例代码:https://github.com/zacker330/jenkins-pipeline-shared-lib-unittest-demo JenkinsPipelineUnit:https://github.com/jenkinsci/JenkinsPipelineUnit  ",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1141
        "auhtor": "zacker330",
1142 1143
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1144
        "poster": "poster.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1145
    },
1146
    {
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-27-docs-sig-announcement/",
        "title": "Jenkins 文档特别兴趣小组",
        "type": "wechat",
        "date": "2019-05-27 00:00:00 +0000 UTC",
        "tags": ["documentation", "docs", "community"],
        "description": "Jenkins 宣布成立文档特别兴趣小组",
        "content": " 我们很高兴地宣布 Jenkins 文档特别兴趣小组的成立。 文档特别兴趣小组鼓励贡献者和外部社区创建和 review Jenkins 文档。\n更多详情和计划,请参见:文档特别兴趣小组简介。\n我能帮什么忙呢? Jenkins 文档特别兴趣小组希望从以下方面得到您的帮助:\n review 及修复 打开的 bug 报告 review Jenkins 文档 pull requests review Jenkins X 文档 pull requests  我该如何修复文档 bug? 关于如何为 Jenkins 文档做贡献的说明,请参见站点仓库中的 CONTRIBUTING 文件。 按照说明文件,提交 pull requests 以供 review 。\n关于如何为 Jenkins X 文档做贡献的说明,请参见站点仓库中的 Jenkins X 文档站点。 按照说明文件,提交 pull requests 以供 review 。\n我该如何评估 pull request? Jenkins 项目的 pull requests 会在 Jenkins 文档仓库进行 review 。 使用您的凭据登录到 GitHub,向 pull requests 中添加评论。\nJenkins X 项目的 pull requests 会在 Jenkins X 档仓库进行 review 。 使用您的凭据登录到 GitHub,向 pull requests 中添加评论。\n",
        "auhtor": "markewaite",
        "translator": "donhui",
        "original": "https://jenkins.io/blog/2019/05/11/docs-sig-announcement/",
        "poster": "./2019-05-27-docs-sig-announcement/Jenkins_Needs_You-02.png"
    },
    {
1160 1161 1162
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-24-achieve-cicd-with-jenkins-x-kubernetes-and-spring/",
        "title": "使用 Jenkins X、Kubernetes 和 Spring Boot 实现 CI/CD",
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1163
        "date": "2019-05-24 00:00:00 +0000 UTC",
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516
        "tags": ["jenkins-x", "k8s", "kubernetes", "ci", "cd", "spring boot"],
        "description": "通过使用 Jenkins X 和 Kubernetes 来改进 Spring Boot 应用程序,使 Jenkins X 成为 CI/CD 过程的关键部分。",
        "content": " 过去五年中的变化,如迁移到公有云以及从虚拟机向容器的转变,已经彻底改变了构建和部署软件的意义。\n以 Kubernetes 为例。Google 于2014年开源,现在所有主流的公有云供应商都支持它\u0026mdash;它为开发人员提供了一种很好的方式,可以将应用程序打包到 Docker 容器中,并部署到任意 Kubernetes 集群中。\n使用 CI/CD、Kubernetes 和 Jenkins X 进行高性能开发 在技术上,高性能团队几乎总是成功的必要条件,而持续集成、持续部署(CI/CD)、小迭代以及快速反馈是构建模块。为你的云原生应用程序设置 CI/CD 可能比较困难。通过自动化所有内容,开发人员可以花费宝贵的时间来交付实际的业务。\n如何使用容器、持续交付和 Kubernetes 成为高效团队?这就是 Jenkins X 的切入点。\n“Jenkins X 的理念是为所有开发人员提供他们自己的海军航海管家,可以帮助你航行持续交付的海洋。” - James Strachan\nJenkins X 帮助你自动化你在 Kubernetes 中的 CI/CD - 你甚至不需要学习 Docker 或 Kubernetes!\nJenkins X 能做什么? Jenkins X 在 Kubernetes 上自动安装,配置和升级 Jenkins 和其他应用程序(Helm,Skaffold,Nexus 等)。它使用 Docker 镜像、Helm 图表和流水线来自动化应用程序的 CI/CD。它使用 GitOps 来管理环境之间的升级,并通过在拉取请求和生产时对其进行评论来提供大量反馈。\nJenkins X 入门 要安装 Jenkins X,首先需要在你的机器或云供应商上安装 jx 二进制文件。从 Google Cloud 可以获得300美元的积分,所以我决定从那里开始。\n在 Google Cloud 上安装 Jenkins X 并创建群集 浏览到cloud.google.com并登录。如果你还没有帐户,请注册免费试用。转到控制台(右上角有一个链接)并激活 Google Cloud shell。将以下命令复制并粘贴到 shell 中。\ncurl -L https://github.com/jenkins-x/jx/releases/download/v1.3.79/jx-linux-amd64.tar.gz | tar xzv sudo mv jx /usr/local/bin  注意:Google Cloud Shell 将在一小时后终止在你的主目录之外所做的任何更改,因此你可能必须重新运行这些命令。好消息是它们将在你的历史中,所以你只需要向上箭头并进入。你也可以删除上面的 sudo mv 命令,并将以下内容添加到 .bashrc 中。\nexport PATH=$PATH:.  使用以下命令在 GKE(Google Kubernetes Engine)上创建集群。你可能必须为你的帐户启用 GKE。\njx create cluster gke --skip-login  如果系统提示你下载 helm,请确认你要安装。系统将提示你选择 Google Cloud Zone。我建议选择一个靠近你的位置。我选择 us-west1-a,因为我住在 Denver, Colorado 附近。对于 Google Cloud Machine 类型,我选择了 n1-standard-2 并使用了 min(3)和 max(5)个节点数的默认值。\n对于 GitHub 名称,键入你自己的(例如 mraible)和你在 GitHub 上注册的电子邮件(例如 matt.raible@okta.com)。我试图使用 oktadeveloper(一个 GitHub 组织),但我无法使其工作。\n注意:如果你的帐户启用了两步认证,则 GitHub 集成将失败。如果你希望成功完成该过程,则需要在 GitHub 上禁用它。\n当提示安装 ingress controller 时,按 Enter 键 确定。再次按 Enter 键选择默认 domain。\n系统将提示你创建 GitHub API Token。单击 提供的 URL 并将其命名为 “Jenkins X”。将 token 值复制并粘贴回控制台。\n在安装完成后喝杯咖啡、饮料或做一些俯卧撑。可能需要几分钟。\n下一步是将 API token 从 Jenkins 复制到你的控制台。按照控制台中提供的说明进行操作。\n完成后,运行 jx console 并单击链接以登录到 Jenkins 实例。单击 Administration 并升级 Jenkins 及其所有插件(插件管理器 \u0026gt; 滚动到底部并选择全部)。如果未能执行此步骤,将无法从 GitHub pull request 到 Jenkins X CI 进程。\n创建一个 Spring Boot 应用程序 当我第一次开始使用 Jenkins X 时,我尝试导入现有项目。即使我的应用程序使用了 Spring Boot,但是根目录中没有 pom.xml,所以 Jenkins X 认为它是一个 Node.js 应用程序。出于这个原因,我建议首先创建一个空白的 Spring Boot 应用程序,以保证 Jenkins X 正确创建。\n从 Cloud Shell 创建一个简单的 Spring Boot 应用程序:\njx create spring -d web -d actuator  此命令使用 Spring Initializr,因此系统会提示你进行一些选择。以下是我的选择:\n   QUESTION ANSWER     Language java   Group com.okta.developer   Artifact okta-spring-jx-example    提示:为你的 artifact name 选取一个简洁的名称将减轻你的痛苦。Jenkins X 对于版本名称有53个字符的限制,oktadeveloper/okta-spring-boot-jenkinsx-example 将会使它超过两个字符。\n为 git 用户名、初始化 git 和提交消息都选择默认值。如果你不想使用个人帐户,可以选择要使用的组织。运行以下命令以查看应用程序的 CI/CD 流水线。\njx get activity -f okta-spring-jx-example -w  运行 jx console,单击生成的链接,然后导航到你的项目(如果你想要一个更富视觉效果的视图)。\n此过程将执行一些任务:\n 为你的项目创建一个版本。 为演示环境项目创建 pull request。 将其自动部署到演示环境,以便你可以查看它的运行情况。  Merge status checks all passed so the promotion worked! Application is available at: http://okta-spring-jx-example.jx-staging.35.230.106.169.nip.io   注意:由于 Spring Boot 默认情况下不提供欢迎页面,所以打开上面的 URL 时将返回404。\n使用 Jenkins X 将 Spring Boot 应用程序部署到生产环境中 默认情况下,Jenkins X 只会自动部署到演示环境。你可以手动改进从演示到生产使用:\njx promote okta-spring-jx-example --version 0.0.1 --env production  你可以使用 jx edit environment 更改生产环境,以使用自动部署。\n既然你已经知道如何使用 Jenkins X 和一个简单的 Spring Boot 应用程序,让我们来看看如何通过一个更实际的示例使其工作。\n保护你的 Spring Boot 应用程序并添加 Angular PWA 在过去的几个月里,我写了一系列有关使用 Ionic/Angular 和 Spring Boot 构建 PWA(渐进式 Web 应用程序)的博文。\n 使用 Okta 保护你的加密货币财富跟踪 PWA 使用 Okta(而不是本地存储)安全地存储用户的数据 使用 WireMock、Jest、Protractor 和 Travis CI 测试 Spring Boot API 和 Angular 组件的 Hitchhiker 指南 将你的 Spring Boot + Angular PWA 部署为一个 Artifact 这是该系列的最后一篇博客文章。我相信这是一个真实应用程序的很好的例子,因为它有许多单元和集成测试,包括与 Protractor 的端到端测试。让我们看看如何使用 Jenkins X 和 Kubernetes 自动化生产路径!  克隆刚刚从GitHub创建的Spring Boot项目(确保在URL中更改{yourUsername}):\ngit clone https://github.com/{yourUsername}/okta-spring-jx-example.git okta-jenkinsx  在邻近目录中,将创建的具有 Spring Boot + Angular 的项目克隆为一个 artifact:\ngit clone https://github.com/oktadeveloper/okta-spring-boot-angular-auth-code-flow-example.git spring-boot-angular  在终端中,导航到 okta-jenkinsx 并删除不再需要的文件:\ncd okta-jenkinsx rm -rf .mvn src mvnw* pom.xml  结果应该是包含以下文件的目录结构:\n$ tree . . ├── charts │ ├── okta-spring-jx-example │ │ ├── Chart.yaml │ │ ├── Makefile │ │ ├── README.md │ │ ├── templates │ │ │ ├── deployment.yaml │ │ │ ├── _helpers.tpl │ │ │ ├── NOTES.txt │ │ │ └── service.yaml │ │ └── values.yaml │ └── preview │ ├── Chart.yaml │ ├── Makefile │ ├── requirements.yaml │ └── values.yaml ├── Dockerfile ├── Jenkinsfile └── skaffold.yaml 4 directories, 15 files  将 spring-boot-angular 所有文件复制到 okta-jenkinsx。\ncp -r ../spring-boot-angular/* .  使用 Travis CI 测试此应用程序时,我运行了 npm install 作为该过程的一部分。使用 Jenkins X,使用一个容器(例如 maven 或者 nodejs)保存所有内容更简单,因此在 frontend-maven-plugin(在 holdings-api/pom.xml)中添加执行以运行 npm install (提示:你将需要执行 id==’npm install' 添加到现有的pom.xml中)。\n现在是 okta-jenkinsx 在 IntelliJ IDEA、Eclipse、Netbeans 或 VS Code 等 IDE 中作为项目打开目录的好时机!\n\u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;com.github.eirslett\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;frontend-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${frontend-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;workingDirectory\u0026gt;../crypto-pwa\u0026lt;/workingDirectory\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;install node and npm\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;install-node-and-npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;nodeVersion\u0026gt;${node.version}\u0026lt;/nodeVersion\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;npm install\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;generate-resources\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt;install --unsafe-perm\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; ... \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt;  注意:--unsafe-perm 标志是必要的,因为 Jenkins X 以 root 用户身份运行构建。我从 node-sass 的故障排除说明中找到了这个解决方案。\n增加 Actuator 并关闭 HTTPS Jenkins X 依靠 Spring Boot 的 Actuator 进行健康检查。这意味着如果你不将其包含在你的项目中(或有 /actuator/health 防护),Jenkins X 会报告你的应用程序启动失败。\n将 Actuator starter 作为依赖项添加到 holdings-api/pom.xml 中:\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt;  你还需要允许访问其运行健康检查。Jenkins X 将部署你的应用程序在一个 NGINX 服务器中,因此你也需要强制关闭 HTTPS,否则你将无法访问你的应用程序。修改 holdings-api/src/main/java/.../SecurityConfiguration.java 以允许 holdings-api/src/main/java/.../SecurityConfiguration.java 和删除 requiresSecure()。\npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers(\u0026quot;/**/*.{js,html,css}\u0026quot;); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and() .authorizeRequests() .antMatchers(\u0026quot;/\u0026quot;, \u0026quot;/home\u0026quot;, \u0026quot;/api/user\u0026quot;, \u0026quot;/actuator/health\u0026quot;).permitAll() .anyRequest().authenticated(); } }  调整 Dockerfile 和 Jenkinsfile 中的路径 由于此项目构建在子目录而不是根目录中,因此请更新 ./Dockerfile 以查找 holdings-api 文件。\nFROM openjdk:8-jdk-slim ENV PORT 8080 ENV CLASSPATH /opt/lib EXPOSE 8080 # copy pom.xml and wildcards to avoid this command failing if there's no target/lib directory COPY holdings-api/pom.xml holdings-api/target/lib* /opt/lib/ # NOTE we assume there's only 1 jar in the target dir # but at least this means we don't have to guess the name # we could do with a better way to know the name - or to always create an app.jar or something COPY holdings-api/target/*.jar /opt/app.jar WORKDIR /opt CMD [\u0026quot;java\u0026quot;, \u0026quot;-jar\u0026quot;, \u0026quot;app.jar\u0026quot;]  你还需要更新 Jenkinsfile,以便它可以运行 holdings-api 目录中的任何 mvn 命令。也添加 -Pprod 配置文件。例如:\n// in the 'CI Build and push snapshot' stage steps { container('maven') { dir ('./holdings-api') { sh \u0026quot;mvn versions:set -DnewVersion=$PREVIEW_VERSION\u0026quot; sh \u0026quot;mvn install -Pprod\u0026quot; } } ... } // in the 'Build Release' stage dir ('./holdings-api') { sh \u0026quot;mvn versions:set -DnewVersion=\\$(cat ../VERSION)\u0026quot; } ... dir ('./holdings-api') { sh \u0026quot;mvn clean deploy -Pprod\u0026quot; }  这应该足以让这个应用程序与 Jenkins X 一起使用。但是,除非你有一个 Okta 帐户并相应地配置它,否则你将无法登录它。\n为什么使用Okta? 简而言之,我们使标识管理比你可能习惯的更简洁、更安全、更具可扩展性。Okta 是一种云服务,允许开发人员创建、编辑和安全存储用户帐户和用户帐户数据,并将其与一个或多个应用程序相连接。我们的 API 使你能够:\n 对用户进行身份验证和授权 存储关于用户的数据 执行基于密码和社交登录 使用多重身份验证保护应用程序 了解更多!查看我们的产品文档 你心动了吗?注册一个永远免费的开发者帐户,当你完成后,请返回,以便我们可以通过 Spring Boot 和 Jenkins X 了解有关 CI/CD 的更多信息!  在 Okta 中为 Spring Boot 应用程序创建一个 Web 应用程序 完成设置过程后,登录到你的帐户并导航到 Applications \u0026gt; Add Application。单击 Web 和 下一步。在下一页中,输入以下值并单击 Done (必须单击 Done,然后编辑以修改注销重定向 URI)。\n 应用名称: Jenkins X 默认 URI: http://localhost:8080 登录重定向 URI: http://localhost:8080/login 注销重定向 URI: http://localhost:8080 打开 holdings-api/src/main/resources/application.yml 并将你 org/app 中的值粘贴到其中。  okta: client: orgUrl: https://okta.okta.com token: XXX security: oauth2: client: access-token-uri: https://okta.okta.com/oauth2/default/v1/token user-authorization-uri: https://okta.okta.com/oauth2/default/v1/authorize client-id: {clientId} client-secret: {clientSecret} resource: user-info-uri: https://okta.okta.com/oauth2/default/v1/userinfo   你将注意到 token 值是 xxx。这是因为我更喜欢从环境变量中读取它,而不是签入源代码控制。你可能也想为你的客户密钥执行此操作,但我只是为了简洁而做一个属性。要创建 API token:\n 导航到 API \u0026gt; Tokens ,然后单击 Create Token 为令牌命名(例如 “Jenkins X”),然后将其值设置为 OKTA_CLIENT_TOKEN 环境变量。 你需要在组织的用户配置文件中添加一个 holdings 属性,以便将你的加密货币存储在 Okta 中。导航到 Users \u0026gt; Profile Editor。点击 Profile 表格中的第一个配置文件。你可以通过其 Okta 标识来识别它。单击 Add Attribute 并使用以下值:   显示名称: Holdings 变量名: holdings 描述: Cryptocurrency Holdings 执行这些步骤后,你应该能够导航到 http://localhost:8080, 并在运行以下命令后登录:  cd holdings-api ./mvnw -Pprod package java -jar target/*.jar   在 Jenkins X 中存储 Secrets 在本地存储环境变量非常简单。但是你如何在 Jenkins X 中做到这一点?看看它的凭证功能就知道了。下面是使用方法:\n 在 Google Cloud Shell 上运行 jx console,以获取 Jenkins X 网址 单击该链接,登录,然后单击顶部的 Administration 单击 Credentials \u0026gt; (global) \u0026gt; Add Credentials(在左侧) 从下拉列表中选择 Secret text,并为 ID 输入 OKTA_CLIENT_TOKEN 将 Okta API token 复制/粘贴到 Secret 字段中 当你在里面,添加 secrets:OKTA_APP_ID、E2E_USERNAME 和 E2E_PASSWORD。第一个是你创建的 Jenkins X OIDC 应用程序的 ID。您可以通过在 Okta 上导航到您的应用程序并从 URL 复制值来获得它的值。该 E2E-* 密钥应该是要用来运行终端到终端(Protractor)测试的凭证。你可能想为此创建一个新用户。  你可以通过将这些值添加到 environment 顶部附近的部分来访问 Jenkinsfile 中的这些值 。\nenvironment { ORG = 'mraible' APP_NAME = 'okta-spring-jx-example' CHARTMUSEUM_CREDS = credentials('jenkins-x-chartmuseum') OKTA_CLIENT_TOKEN = credentials('OKTA_CLIENT_TOKEN') OKTA_APP_ID = credentials('OKTA_APP_ID') E2E_USERNAME = credentials('E2E_USERNAME') E2E_PASSWORD = credentials('E2E_PASSWORD') }  将环境变量转移到 Docker 容器 要将 OKTA_CLIENT_TOKEN 环境变量转移到 Docker 容器,请查看:\nsh \u0026quot;make preview\u0026quot;  并将其更改为:\nsh \u0026quot;make OKTA_CLIENT_TOKEN=\\$OKTA_CLIENT_TOKEN preview\u0026quot;  此时,你可以创建分支,提交更改,并验证 Jenkins X 中的所有内容是否正常工作。\ncd .. git checkout -b add-secure-app git add . git commit -m \u0026quot;Add Bootiful PWA\u0026quot; git push origin add-secure-app  打开浏览器并导航到 GitHub 上的存储库并创建 pull request。创建后它应该如下所示。\n如果你的 pull request 测试通过,你应该能看到一些绿色标记和 Jenkins X 的评论,说明你的应用程序在预览环境中可用。\n如果你单击此处链接并尝试登录,则可能会从 Okta 得到一个错误,指出重定向 URI 尚未列入白名单。\n在 Okta 中自动添加重定向 URI 当你在 Okta 中创建应用程序并在本地运行它们时,很容易知道应用程序的重定向 URI 将是什么。对于这个特定的应用程序,它们将 http://localhost:8080/login 用于登录,http://localhost:8080 用于注销。当您进入生产环境时,URL通常也是众所周知的。但是,使用 Jenkins X,URL 是动态的,并根据你的 pull request 编号动态创建的。\n要使用 Okta 进行此操作,你可以创建一个 Java 类,该类与 Okta API 进行交互。创建 holdings-api/src/test/java/.../cli/AppRedirectUriManager.java 并使用以下代码完善它。\npackage com.okta.developer.cli; import com.okta.sdk.client.Client; import com.okta.sdk.lang.Collections; import com.okta.sdk.resource.application.OpenIdConnectApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @SpringBootApplication public class AppRedirectUriManager implements ApplicationRunner { private static final Logger log = LoggerFactory.getLogger(AppRedirectUriManager.class); private final Client client; @Value(\u0026quot;${appId}\u0026quot;) private String appId; @Value(\u0026quot;${redirectUri}\u0026quot;) private String redirectUri; @Value(\u0026quot;${operation:add}\u0026quot;) private String operation; public AppRedirectUriManager(Client client) { this.client = client; } public static void main(String[] args) { SpringApplication.run(AppRedirectUriManager.class, args); } @Override public void run(ApplicationArguments args) { log.info(\u0026quot;Adjusting Okta settings: {appId: {}, redirectUri: {}, operation: {}}\u0026quot;, appId, redirectUri, operation); OpenIdConnectApplication app = (OpenIdConnectApplication) client.getApplication(appId); String loginRedirectUri = redirectUri + \u0026quot;/login\u0026quot;; // update redirect URIs List\u0026lt;String\u0026gt; redirectUris = app.getSettings().getOAuthClient().getRedirectUris(); // use a set so values are unique Set\u0026lt;String\u0026gt; updatedRedirectUris = new LinkedHashSet\u0026lt;\u0026gt;(redirectUris); if (operation.equalsIgnoreCase(\u0026quot;add\u0026quot;)) { updatedRedirectUris.add(loginRedirectUri); } else if (operation.equalsIgnoreCase(\u0026quot;remove\u0026quot;)) { updatedRedirectUris.remove(loginRedirectUri); } // todo: update logout redirect URIs with redirectUri (not currently available in Java SDK) app.getSettings().getOAuthClient().setRedirectUris(Collections.toList(updatedRedirectUris)); app.update(); System.exit(0); } }  该类使用 Spring Boot 的 CLI(命令行接口)支持,这使得可以使用 Exec Maven 插件调用它。要添加对 Maven 运行它的支持,请在 holdings-api/pom.xml 进行以下修改 。\n\u0026lt;properties\u0026gt; ... \u0026lt;exec-maven-plugin.version\u0026gt;1.6.0\u0026lt;/exec-maven-plugin.version\u0026gt; \u0026lt;appId\u0026gt;default\u0026lt;/appId\u0026gt; \u0026lt;redirectUri\u0026gt;override-me\u0026lt;/redirectUri\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;!-- dependencies --\u0026gt; \u0026lt;build\u0026gt; \u0026lt;defaultGoal\u0026gt;spring-boot:run\u0026lt;/defaultGoal\u0026gt; \u0026lt;finalName\u0026gt;holdings-app-${project.version}\u0026lt;/finalName\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;!-- existing plugins --\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.codehaus.mojo\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;exec-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${exec-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;add-redirect\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;java\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;mainClass\u0026gt;com.okta.developer.cli.AppRedirectUriManager\u0026lt;/mainClass\u0026gt; \u0026lt;classpathScope\u0026gt;test\u0026lt;/classpathScope\u0026gt; \u0026lt;arguments\u0026gt; \u0026lt;argument\u0026gt;appId ${appId} redirectUri ${redirectUri}\u0026lt;/argument\u0026gt; \u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt;  然后更新 Jenkinsfile 以在构建镜像之后添加一段 mvn exec:java 供运行。\ndir ('./charts/preview') { container('maven') { sh \u0026quot;make preview\u0026quot; sh \u0026quot;make OKTA_CLIENT_TOKEN=\\$OKTA_CLIENT_TOKEN preview\u0026quot; sh \u0026quot;jx preview --app $APP_NAME --dir ../..\u0026quot; } } // Add redirect URI in Okta dir ('./holdings-api') { container('maven') { sh ''' yum install -y jq previewURL=$(jx get preview -o json|jq -r \u0026quot;.items[].spec | select (.previewGitInfo.name==\\\\\u0026quot;$CHANGE_ID\\\\\u0026quot;) | .previewGitInfo.applicationURL\u0026quot;) mvn exec:java@add-redirect -DappId=$OKTA_APP_ID -DredirectUri=$previewURL ''' } }  提交并推送你的更改,应用程序应该更新为 http://{yourPreviewURL}/login 的重定向 URI。你需要手动为 http://{yourPreviewURL} 添加一个注销重定向 URI, 因为 Okta 的 Java SDK 目前不支持此功能。\n要将你的 pull request 上传到演示环境,请将其合并,并将主分支推送到演示环境。不幸的是,你将无法登录。这是因为没有进程使用你的 Okta 应用程序注册登台站点的重定向 URI。如果手动添加 URI,一切都应该有效。\n在 Jenkins X 中运行 Protractor 测试 对我来说,弄清楚如何在 Jenkins X 中运行端到端测试是最难的。我首先添加了一个新的 Maven 配置文件,它允许我使用 Maven 而不是 npm 运行测试。\n注意:要使此配置文件起作用,你需要将 http://localhost:8000/login 登录重定向 URI 添加到你的应用程序,并将 http://localhost:8000 作为注销重定向URI。\n\u0026lt;profile\u0026gt; \u0026lt;id\u0026gt;e2e\u0026lt;/id\u0026gt; \u0026lt;properties\u0026gt; \u0026lt;!-- Hard-code port instead of using build-helper-maven-plugin. --\u0026gt; \u0026lt;!-- This way, you don't need to add a redirectUri to Okta app. --\u0026gt; \u0026lt;http.port\u0026gt;8000\u0026lt;/http.port\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;build\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;pre-integration-test\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;start\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt; \u0026lt;argument\u0026gt;--server.port=${http.port}\u0026lt;/argument\u0026gt; \u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;post-integration-test\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;stop\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;com.github.eirslett\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;frontend-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${frontend-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;workingDirectory\u0026gt;../crypto-pwa\u0026lt;/workingDirectory\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;webdriver update\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;pre-integration-test\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt;run e2e-update\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;ionic e2e\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;integration-test\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;environmentVariables\u0026gt; \u0026lt;PORT\u0026gt;${http.port}\u0026lt;/PORT\u0026gt; \u0026lt;CI\u0026gt;true\u0026lt;/CI\u0026gt; \u0026lt;/environmentVariables\u0026gt; \u0026lt;arguments\u0026gt;run e2e-test\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; \u0026lt;/profile\u0026gt;  提示:你可能会注意到,我必须为 e2e-update 和 e2e-test 分两次不同的执行。我发现运行 npm e2e 与 frontend-maven-plugin 不兼容,因为它只调用其他 npm run 命令。看来你需要在使用 frontend-maven-plugin 时直接调用二进制文件。\n这里使用的不是 TRAVIS 环境变量,而是 CI 变量。此更改需要更新 crypto-pwa/test/protractor.conf.js 来匹配。\nbaseUrl: (process.env.CI) ? 'http://localhost:' + process.env.PORT : 'http://localhost:8100',  进行这些更改,你应该能够运行 ./mvnw verify -Pprod,e2e 以在本地运行端到端测试。请注意,你需要将 E2E_USERNAME 和 E2E_PASSWORD 定义为环境变量。\n当我第一次在 Jenkins X 中尝试这个功能时,我发现 jenkins-maven 代理没有安装 Chrome。我发现很难安装并发现 jenkins-nodejs 预安装了 Chrome 和 Xvfb。当我第一次尝试它时,我遇到以下错误:\n[21:51:08] E/launcher - unknown error: DevToolsActivePort file doesn't exist  此错误是由 Chrome on Linux 问题引起的 。我发现解决办法是在 Protractor 的 chromeOptions 中指定 -disable-dev-shm-usage。我还添加了一些推荐的额外标志。我特别喜欢 --headless,在本地运行时,因此浏览器不会弹出并妨碍我。如果我想实时看到这个过程,我可以快速删除该选项。\n如果你希望在 Jenkins X 上看到项目的 Protractor 测试运行,则需要修改 crypto-pwa/test/protractor.conf.js 以指定以下内容 chromeOptions:\ncapabilities: { 'browserName': 'chrome', 'chromeOptions': { 'args': ['--headless', ''--disable-gpu', '--no-sandbox', '--disable-extensions', '--disable-dev-shm-usage'] } },  然后向 Jenkinsfile 添加一个新的 Run e2e tests 阶段,该阶段位于 “CI 构建”和“构建发布”阶段之间。如果有帮助,你可以看到最终的 Jenkins 文件。\nstage('Run e2e tests') { agent { label \u0026quot;jenkins-nodejs\u0026quot; } steps { container('nodejs') { sh ''' yum install -y jq previewURL=$(jx get preview -o json|jq -r \u0026quot;.items[].spec | select (.previewGitInfo.name==\\\\\u0026quot;$CHANGE_ID\\\\\u0026quot;) | .previewGitInfo.applicationURL\u0026quot;) cd crypto-pwa \u0026amp;\u0026amp; npm install --unsafe-perm \u0026amp;\u0026amp; npm run e2e-update Xvfb :99 \u0026amp; sleep 60s DISPLAY=:99 npm run e2e-test -- --baseUrl=$previewURL ''' } } }  完成所有这些更改后,创建一个新分支,签入你的更改,并在 GitHub 上创建一个 pull request。\ngit checkout -b enable-e2e-tests git add . git commit -m \u0026quot;Add stage for end-to-end tests\u0026quot; git push origin enable-e2e-tests  我确实需要做一些额外的调整才能通过所有的 Protractor 测试:\n 在 crypto-pwa/e2e/spec/login.e2e-spec.ts 中,我无法通过 should show a login button 测试,所以我忽略了它,将 it(…) 改为 xit(…)。 在同一个文件中,我将2000 ms 超时更改为5000 ms,将5000 ms 超时更改为30000 ms。 在 crypto-pwa/test/protractor.conf.js 中,我将 defaultTimeoutInterval 更改为 600000。 第一次运行时测试可能会失败,因为未为新预览环境配置注销重定向URI。更新 Okta 应用程序的注销重定向 URI 以匹配你的 PR 的预览环境 URI,重新 pull request 测试,一切都应该通过!  你可以在 GitHub 上的此示例中找到已完成应用程序的源代码 。\n了解有关 Jenkins X、Kubernetes 和 Spring Boot 的更多信息 要了解有关 Spring Boot、Jenkins X 和 Kubernetes 的更多信息,请查看以下资源:\n Deploy Your Secure Spring Boot + Angular PWA as a Single Artifact Build a Basic CRUD App with Angular 5.0 and Spring Boot 2.0 Introducing Jenkins X: a CI/CD solution for modern cloud applications on Kubernetes Kubernetes The Hard Way by Kelsey Hightower 如果你在 Kubernetes 上运行生产应用程序,我建议你研究 Jenkins X.它提供了一种在相同环境中进行 CI/CD 的方法,快速迭代并为你的客户更快地交付业务价值。  Jenkins X 还包括一个 DevPods 功能,可以在笔记本电脑上进行开发时,可以自动部署保存。我不确定 DevPods 是否适用于需要具有生产转换步骤的 JavaScript 应用程序。我宁愿让 webpack 和 Browsersync 在几秒钟内刷新我的本地浏览器,而不是等待几分钟创建并部署 Docker 镜像到 Kubernetes。\n要获得 Jenkins X 的精彩概述和演示,请观看 James Strachan 在2018年6月的 Virtual JUG 会议上为 Kubernetes 发布的 Jenkins X: Continuous Delivery。\n如果你有任何疑问,请在下面添加评论,在 Twitter 上发帖,或在我们的开发者论坛 上发帖提问。要获得有关未来博客文章和开发人员智慧的通知,你可以在Twitter上关注我的整个团队。\n使用 Jenkins X 和 Kubernetes 将 CI/CD 添加到 Spring Boot 应用程序中,最初于2018年7月11日发布到 Okta 开发人员博客。\n",
        "auhtor": "Matt Raible",
        "translator": "yJunS",
        "original": "https://dzone.com/articles/achieve-cicd-with-jenkins-x-kubernetes-and-spring",
        "poster": "../05/2019-05-24-achieve-cicd-with-jenkins-x-kubernetes-and-spring/cicd.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-23-chinese-localization/",
        "title": "Jenkins 中文本地化的重大进展",
        "type": "wechat",
        "date": "2019-05-23 00:00:00 +0000 UTC",
        "tags": [],
        "description": "Jenkins 中文社区大事件",
        "content": " 我从2017年开始,参与 Jenkins 社区贡献。作为一名新成员,翻译可能是帮助社区项目最简单的方法。 本地化的优化通常是较小的改动,你无需了解项目完整的上下文, 甚至都不需要在任务跟踪系统中添加任务。 但很快,就遇到了一些问题,那就是并没有以中文为母语的人帮助 review 我的 PR。因此,有时候, 我提交的 PR 过很久才能够被合并到 master 中。\n后来,有贡献者告诉我,可以在邮件列表中发一份邮件来描述当前遇到的问题,然后大家来讨论如何解决。 后来,我才了解到,在邮件列表中公开地讨论社区里的事情, 正是开源社区的做事风格。任何人都可以发表自己的观点, 我们并不受某个公司的限制,大家共同作出一致的决定。下面,我想与各位分享一下我们讨论后得出的一些成果。\nJEP-216 JEP 是 Jenkins Enhancement Proposoals 的缩写,也就是 Jenkins 增强提议。所有针对 Jenkins 社区的增强或者改进的想法都可以通过这样的一种 提议机制来推动,特别兴趣小组(SIG)就是其中的一项提议。JEP-216 是关于 改进本地化的一项提议。\n在之前,所有语言的本地化资源文件都是集中保存在 Jenkins Core 以及各个插件中的。而在 该提议中,每个语言都可以有一个单独的本地化插件,例如:简体中文插件。 终于,经过半年多的时间, 本地化支持插件和 简体中文插件已经可以支持各种类型的本地化资源文件(包括: Messages、属性以及帮助文件等)。从 插件网站上, 你可以看到 简体中文插件已经有超过1.3万的安装量,而且还在持续增长中。到目前为止,我们已经把 Jenkins Core 里所有简体中文的资源文件 迁移到了简体中文插件中,具体可以查看 PR-4008。\n我相信,这对于每一位 Jenkins 的中文用户都是一件意义重大的事情,Jenkins 中文社区也会努力带给大家带来更好的使用体验。当然, 我们欢迎并期待任何一位有志参与开源社区的朋友!\n在享受成果的同时,请与我一起感谢社区里为此作出重要贡献的朋友们。在 Daniel Beck 的帮助下,完成了“本地化支持插件”的发布; 在 Liam Newman 的帮助下完成了 JEP-216, 当然还包括社区中很多参与到中文本地化工作的贡献者。\n中文本地化特别兴趣小组 我们相信,这个特别兴趣小组能够给 Jenkins 的中文用户带来更好的使用体验,并聚集更多来自中国的贡献者。这里的贡献者,并不只是开发者的专利和特权, 实际上开源社区需要很多有不同技能的人加入,包括当不仅限于:测试、运维、文档工程师 甚至是设计师、市场运营等等。不管你是尚未毕业的在校学生, 还是懵懂初入职场,或者已经是具有多年丰富的从业经历,在这里 都是平等、公开的。\n该组会负责维护 Jenkins 官方中文站点,通过微信公众号在国内宣传和推广 Jenkins 社区及其技术。 我们会发布官方博客文章、实际案例、原创文章、Jenkins 版本发布,还有 Jenkins Meetup 或者其他的线上线下活动。 我们的官方公众号自半年前开通以来,已经有超过一千八百多位 Jenkins 的用户关注,并可以从这里及时获取最新的官方咨讯信息。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“great-wall.jpeg”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-22-jacoco-coverage-for-functional-test/",
        "title": "基于 Jenkins + JaCoCo 实现功能测试代码覆盖率统计",
        "type": "wechat",
        "date": "2019-05-22 00:00:00 +0000 UTC",
        "tags": ["jenkins", "jacoco", "ci", "coverage"],
        "description": "本文对 JaCoCo 进行简要介绍,并借助 Jenkins 实现功能测试代码覆盖率统计",
        "content": " 使用 JaCoCo 统计功能测试代码覆盖率? 对于 JaCoCo,有所了解但又不是很熟悉。 \u0026ldquo;有所了解\u0026rdquo;指的是在 CI 实践中已经使用 JaCoCo 对单元测试代码覆盖率统计: 当代码 push 到代码仓库后,用 JaCoCo 进行单元测试代码覆盖率统计,并将相应数据推送到 SonarQube。 \u0026ldquo;不是很熟\u0026rdquo;指的是应用场景也仅限于此,并未进行过多研究与实践。\n前不久,有测试同事提出,想要在实际测试时,用 JaCoCo 统计功能测试代码覆盖率。 其主要目的是在经过功能测试后,通过查看代码覆盖率统计的相关指标,增强对软件质量的信心。 经查阅资料,证明这是可行的。\n由于对 JaCoCo 不甚了解,于是查阅官网资料对 JaCoCo 进一步了解。\n进一步了解 JaCoCo JaCoCo,即 Java Code Coverage,是一款开源的 Java 代码覆盖率统计工具。 它由 EclEmma 团队根据多年来使用和集成现有库的经验教训而创建。\nJaCoCo 愿景 JaCoCo 应该为基于 Java VM 的环境中的代码覆盖率分析提供标准技术。 重点是提供一个轻量级的、灵活的、文档良好的库,以便与各种构建和开发工具集成。\nJaCoCo 产品功能  指令(C0)、分支(C1)、行、方法、类型和圈复杂度的覆盖率分析。 基于 Java 字节码,因此也可以在没有源文件的情况下工作。 通过基于 Java agent 的实时检测进行简单集成。其他集成场景(如自定义类加载器)也可以通过 API 实现。 框架无关性:平稳地与基于 Java VM 的应用程序集成,比如普通 Java 程序、OSGi 框架、web 容器或 EJB 服务器。 兼容所有已发布的 Java 类文件版本。 支持不同的 JVM 语言。 支持几种报告格式( HTML、XML、CSV )。 远程协议和 JMX 控件,以便在任何时间点从覆盖率 agent 请求执行数据 dump 。 Ant 任务,用于收集和管理执行数据并创建结构化覆盖报告。 Maven 插件,用于收集覆盖信息并在Maven构建中创建报告。  非功能特性  使用简单和与现有构建脚本和工具集成。 良好的性能和最小的运行时开销,特别是对大型项目。 轻量级实现,对外部库和系统资源的依赖性最小。 全面的文档。 完整文档化的 API ( JavaDoc ) 和用于与其他工具集成的示例。 回归测试基于 JUnit 测试用例,具有完整的功能测试覆盖率。  对 JaCoCo 可以与现有构建脚本和工具进行集成这里做进一步说明: 官方提供了 Java API、Java Agent 、CLI、Ant 、Maven、Eclipse 这几种集成方式; 第三方提供了诸如与 Gradle、IDEA、Jenkins 等其它工具的集成方式。\n抛开理论,开始实践 JaCoCo 不仅支持统计本地服务的代码覆盖率,也支持统计远程服务的代码覆盖率。 单元测试覆盖率统计就是统计本地服务的代码覆盖率,代码和运行的服务在一台机器上,笔者这里通过使用 JaCoCo Maven 插件完成的。 而功能测试代码覆盖率统计则是统计远程服务的代码覆盖率,代码和运行的服务一般不在一台机器上,这里需要借助 JaCoCo Java agent 实现。 \u0026gt; 备注:实际上,JaCoCo Maven 插件也使用了 JaCoCo Java agent,不过用户不需要直接关系 Java agent 及其选项,Maven 插件都透明地处理了。\n1、下载 JaCoCo 分发包 可以从 JaCoCo 官网下载分发包,也可以从 Maven 仓库(中央仓库或私服)下载。 分发包的 lib 目录下,包括以下库:\n2、Java 应用启动脚本添加 jacocoagent 相关 JVM 参数 需要将 jacocoagent.jar 推送到部署应用的服务器上,笔者这里用 Ansible 进行了批量推送。 Java 应用启动脚本需要加入类似下面的 JVM 参数:\nJAVA_OPTS=\u0026quot;$JAVA_OPTS -javaagent:/path/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=$IP,port=$JACOCO_PORT\u0026quot;  这样在应用成功启动后,会暴露一个 TCP 服务,客户端可以连接到这个服务并获取执行数据文件。\n相关属性说明如下: - append:其中 append=false 表示 dump 每次会生成一个新的执行数据文件,如果 append=true,dump 时则会将数据追加到已存在的执行数据文件。 其中 output=tcpserver 表示 agent 监听来自被 adrress 和 port 属性指定的TCP 端口的连接,执行数据被写到这个连接; - output:如果 output=tcpclient 则表示在启动时,agent 连接到被 adrress 和 port 属性指定的TCP 端口,执行数据被写到这个连接; 如果 output=file 则表示在 JVM 终止时,执行数据被写到被 destfile 属性指定的文件。output 默认值为 file 。 - address:当 output 为 tcpserver 时绑定到的 IP 地址或主机名,或者当 output 为 tcpclient 时连接到的 IP 地址或主机名。 在 tcpserver 模式下,值为“*”导致代理只接受本机地址上的连接。address 默认值为 127.0.0.1 。 - port:当 output 方式为 tcpserver 时绑定到该端口,或者当 output 方式为 tcpclient 时连接到该端口。 在 tcpserver 模式下,端口必须可用,这意味着如果多个 JaCoCo agent 在同一台机器上运行,则必须指定不同的端口。port 默认值为 6300 。\n3、创建及配置 Jenkins Pipeline 任务 Jenkins 任务大致有几个步骤:拉取代码,构建,dump 应用执行数据( jacoco.exec ),解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)。 拉取代码这里无需多说,配置下从代码仓库(SVN/Git)和分支地址就可以了,比较简单。 构建这里用了 Jenkins Pipeline Maven Integration Plugin ,笔者这里所用的 Maven 命令是 mvn clean package -Dmaven.test.skip=true 。 dump 应用执行数据这里有多种方式:Ant、CLI、Maven,因为Java 应用是用 Maven 构建的,这里选择了 Maven Jacoco Plugin。 解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)笔者这里使用了 Jenkins Jacoco Plugin。\nJenkins Pipeline 案例如下:\npipeline { agent any tools { jdk 'JDK1.8' } stages { stage('Checkout'){ steps{ git branch: '${GIT_BRANCH}', credentialsId: 'xxx-xxx-xx-xx-xxx', url: '${GIT_URL}' } } stage('Build') { steps{ withMaven(maven: 'maven'){ sh \u0026quot;mvn clean package -Dmaven.test.skip=true\u0026quot; } } } stage('DumpFromServer'){ steps { withMaven(maven: 'maven'){ sh 'mvn org.jacoco:jacoco-maven-plugin:0.8.4:dump -Djacoco.address=${SERVER_IP} -Djacoco.port=${JACOCO_PORT}' } } } stage('JacocoPublisher') { steps { jacoco() } } } }  JaCoCo 覆盖率报告,部分截图如下:\n总结 笔者所实现的方式并未覆盖任何场景,但是大同小异,相关工具的使用详情可以查看官网文档,因为它是最全面的。 笔者希望这个实践能给有类似诉求的同行一些参考,当然笔者也希望能够和大家互相交流。 同时笔者的 JaCoCo 实践之路并未结束,可能在使用的过程中会有一些问题需要解决, 后续也将考虑使用 Jenkins API 为需要统计功能测试代码覆盖率的 Java 应用实例自动生成一个对应的 Jenkins 任务, 并在 Java 应用实例销毁后,对相应的 Jenkins 任务进行清理等其它功能。\n参考  https://www.eclemma.org/jacoco/index.html https://www.jacoco.org/jacoco/trunk/doc/integrations.html https://www.jacoco.org/jacoco/trunk/doc/agent.html https://www.jacoco.org/jacoco/trunk/doc/counters.html https://www.eclemma.org/jacoco/trunk/doc/mission.html  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "“./2019-05-22-jacoco-coverage-for-functional-test/hangzhou.jpg”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-20-jenkins-ansible-springboot/",
        "title": "使用 Jenkins + Ansible 实现 Spring Boot 自动化部署101",
        "type": "wechat",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": ["jenkins", "ansible", "springboot"],
        "description": "实现 Spring Boot 最基本的流水线",
        "content": " 本文要点: 1. 设计一条 Spring Boot 最基本的流水线:包括构建、制品上传、部署。 1. 使用 Docker 容器运行构建逻辑。 1. 自动化整个实验环境:包括 Jenkins 的配置,Jenkins agent 的配置等。\n1. 代码仓库安排 本次实验涉及以下多个代码仓库:\n% tree -L 1 ├── 1-cd-platform # 实验环境相关代码 ├── 1-env-conf # 环境配置代码-实现配置独立 └── 1-springboot # Spring Boot 应用的代码及其部署代码  1-springboot 的目录结构如下:\n% cd 1-springboot % tree -L 1 ├── Jenkinsfile # 流水线代码 ├── README.md ├── deploy # 部署代码 ├── pom.xml └── src # 业务代码  所有代码,均放在 GitHub:https://github.com/cd-in-practice\n2. 实验环境准备 笔者使用 Docker Compose + Vagrant 进行实验。环境包括以下几个系统: * Jenkins * 1 Jenkins master,全自动安装插件、默认用户名密码:admin/admin。 * Jenkins agent * 2 Jenkins agent 运行在 Docker 容器中,共启动两个。 * Artifactory * 1 一个商业版的制品库。笔者申请了一个 30 天的商业版。\n使用 Vagrant 是为了启动虚拟机,用于部署 Spring Boot 应用。如果你的开发机器无法使用 Vagrant,使用 VirtualBox 也可以达到同样的效果。但是有一点需要注意,那就是网络。如果在虚拟机中要访问 Docker 容器内提供的服务,需要在 DNS 上或者 hosts 上做相应的调整。所有的虚拟机的镜像使用 Centos7。\n另,接下来笔者的所有教程都将使用 Artifactory 作为制品库。在此申明,笔者没有收 JFrog——研发 Artifactory 产品的公司——任何广告费。 笔者只是想试用商业产品,以便了解商业产品是如何应对制品管理问题的。\n启动 Artifactory 后,需要添加 “Virtual Repository” 及 “Local Repository”。具体请查看 Artifactory 的官方文档。如果你当前使用的是 Nexus,参考本教程,做一些调整,问题也不大。\n如果想使用已有制品库,可以修改 1-cd-platform 仓库中的 settings-docker.xml 文件,指向自己的制品库。\n实验环境近期的总体结构图如下:\n之所以说是“近期的”,是因为上图与本篇介绍的结构有小差异。本篇文章还没有介绍 Nginx 与 Springboot 配置共用,但是总体不影响读者理解。\n3. Springboot 应用流水线介绍 Springboot 流水线有两个阶段: 1. 构建并上传制品 2. 部署应用\n流水线的所有逻辑都写在 Jenkinsfile 文件。接下来,分别介绍这两个阶段。\n3.1 构建并上传制品 此阶段核心代码:\ndocker.image('jenkins-docker-maven:3.6.1-jdk8') .inside(\u0026quot;--network 1-cd-platform_cd-in-practice -v $HOME/.m2:/root/.m2\u0026quot;) { sh \u0026quot;\u0026quot;\u0026quot; mvn versions:set -DnewVersion=${APP_VERSION} mvn clean test package mvn deploy \u0026quot;\u0026quot;\u0026quot; }  它首先启动一个装有 Maven 的容器,然后在容器内执行编译、单元测试、发布制品的操作。\n而 mvn versions:set -DnewVersion=${APP_VERSION} 的作用是更改 pom.xml 文件中的版本。这样就可以实现每次提交对应一个版本的效果。\n3.2 部署应用  注意: 这部分需要一些 Ansible 的知识。\n 首先看部署脚本的入口 1-springboot/deploy/playbook.yaml:\n--- - hosts: \u0026quot;springboot\u0026quot; become: yes roles: - {\u0026quot;role\u0026quot;: \u0026quot;ansible-role-java\u0026quot;, \u0026quot;java_home\u0026quot;: \u0026quot;{{JAVA_HOME}}\u0026quot;} - springboot  先安装 JDK,再安装 Spring Boot。JDK 的安装,使用了现成 Ansible role: https://github.com/geerlingguy/ansible-role-java。\n重点在 Spring Boot 部署的核心逻辑。它主要包含以下几部分:\n 创建应用目录。 从制品库下载指定版本的制品。 生成 Systemd service 文件(实现服务化)。 启动服务。  以上步骤实现在 1-springboot/deploy/roles/springboot 中。\n流水线的部署阶段的核心代码如下:\ndocker.image('williamyeh/ansible:centos7').inside(\u0026quot;--network 1-cd-platform_cd-in-practice\u0026quot;) { checkout([$class: 'GitSCM', branches: [[name: \u0026quot;master\u0026quot;]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: \u0026quot;env-conf\u0026quot;]], submoduleCfg: [], userRemoteConfigs: [[url: \u0026quot;https://github.com/cd-in-practice/1-env-conf.git\u0026quot;]]]) sh \u0026quot;ls -al\u0026quot; sh \u0026quot;\u0026quot;\u0026quot; ansible-playbook --syntax-check deploy/playbook.yaml -i env-conf/dev ansible-playbook deploy/playbook.yaml -i env-conf/dev --extra-vars '{\u0026quot;app_version\u0026quot;: \u0026quot;${APP_VERSION}\u0026quot;}' \u0026quot;\u0026quot;\u0026quot; }  它首先将配置变量仓库的代码 clone 下来,然后对 playbook 进行语法上的检查,最后执行 ansible-playbook 命令进行部署。--extra-vars 参数的 app_version 用于指定将要部署的应用的版本。\n3.3 实现简易指定版本部署 在 1-springboot/Jenkinsfile 中实现了简易的指定版本部署。核心代码如下: 1. 流水线接受参数\nparameters { string(name: 'SPECIFIC_APP_VERSION', defaultValue: '', description: '') }   如果指定了版本,则跳过构建阶段,直接执行部署阶段 groovy stage(\u0026quot;build and upload\u0026quot;){ // 如果不指定部署版本,则执行构建 when { expression{ return params.SPECIFIC_APP_VERSION == \u0026quot;\u0026quot; } } // 构建并上传制品的逻辑 steps{...} }  之所以说是“简易”,是因为部署时只指定了制品的版本,并没有指定的部署逻辑和配置的版本。这三者的版本要同步,部署才真正做到准确。  4. 配置管理 所有的配置项都放在 1-env-conf 仓库中。Ansible 执行部署时会读取此仓库的配置。\n将配置放在 Git 仓库中有两个好处: 1. 配置版本化。 2. 任何配置的更改都可以被审查。\n有好处并不代表没有成本。那就是开发人员必须开始关心软件的配置(笔者发现不少开发者忽视配置项管理的重要性。)。\n本文重点不在配置管理,后面会有文章重点介绍。\n5. 实验环境详细介绍 事实上,整个实验,工作量大的地方有两处:一是 Spring Boot 流水线本身的设计;二是整个实验环境的自动化。读者朋友之所以能一两条简单的命令就能启动整个实验环境,是因为笔者做了很多自动化的工作。笔者认为有必要在本篇介绍这些工作。接下来的文章将不再详细介绍。\n5.1 解决流水线中启动的 Docker 容器无法访问 http://artifactory 流水线中,我们需要将制品上传到 artifactory(settings.xml 配置的仓库地址是 http://artifactory:8081),但是发现无法解析 host。这是因为流水线中的 Docker 容器所在网络与 Docker compose 创建的网络不同。所以,解决办法就是让流水线中的 Docker 容器加入到 Docker compose 的网络。\n具体解决办法就是在启动容器时,加入参数:--network 1-cd-platform_cd-in-practice\n5.2 Jenkins 初次启动初始化 在没有做任何设置的情况启动 Jenkins,会出现一个配置向导。这个过程必须是手工的。笔者希望这一步也是自动化的。Jenkins 启动时会执行 init.groovy.d/目录下的 Groovy 脚本。\n5.3 虚拟机中如何能访问到 http://artifactory ? http://artifactory 部署在 Docker 容器中。Spring Boot 应用的制品要部署到虚拟机中,需要从 http://artifactory 中拉取制品,也就是要在虚拟机里访问容器里提供的服务。虚拟机与容器之间的网络是不通的。那怎么办呢?笔者的解决方案是使用宿主机的 IP 做中转。具体做法就是在虚拟机中加一条 host 记录:\nmachine.vm.provision \u0026quot;shell\u0026quot; do |s| s.inline = \u0026quot;echo '192.168.52.1 artifactory' \u0026gt;\u0026gt; /etc/hosts\u0026quot; end  以上是使用了 Vagrant 的 provision 技术,在执行命令 vagrant up 启动虚拟机时,就自动执行那段内联 shell。192.168.52.1 是虚拟宿主机的 IP。所以,虚拟机里访问 http://artifactory:8081 时,实际上访问的是 http://192.168.52.1:8081。\n网络结构可以总结为下图:\n后记 目前遗留问题: 1. 部署时制品版本、配置版本、部署代码版本没有同步。 2. Springboot 的配置是写死在制品中的,没有实现制品与配置项的分离。\n这些遗留问题在后期会逐个解决。就像现实一样,经常需要面对各种遗留项目的遗留问题。\n附录  使用 Jenkins + Ansible 实现自动化部署 Nginx:https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-25-jenkins-ansible-nginx/ 简单易懂 Ansible 系列 —— 解决了什么:https://showme.codes/2017-06-12/ansible-introduce/  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "./2019-05-20-jenkins-ansible-springboot/poster.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-20-translation-norms/",
        "title": "转载规范及声明",
        "type": "wechat",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": ["spec"],
        "description": "为了保护本站文章的原创性,请规范转载,违者必究",
        "content": " 转载声明 首先感谢大家对 Jenkins 中文社区内容的认可。传播有道,我们希望每一篇文章的发声不仅能被看见,也都能得到尊重。因此,若需转载本社区的文章,请先获取本社区授权,未经授权禁止转载。如未经许可私自转载,我们会有专人负责沟通进行整改,对于不听劝解的将会被添加到社区官网的黑名单中以作公示。\n如需转载,请仔细阅读并遵守以下转载须知: 1. 本站发文均于Jenkins 中文社区首发,然后由微信公众号、CSDN、简书、开源中国、掘金等渠道发出 2. 不论通过何种渠道获得本站文章,若想要转载,均可在文章下方留言,获得授权后方可进行在转载 3. 文章转载首行,需添加本文转自 [Jenkins 中文社区],Jenkins 中文社区需加入链接 http://jenkins-zh.cn 4. 转载文章标题不得进行修改 5. 转载文章内容不得做任何修改,如有文章内容问题,请与本社区相关联系人沟通后,再进行下一步处理 6. 为了保护作者权益,作者署名必须保留 7. 如是微信公众号转载,请在获得授权的情况下,使用微信的转载功能进行转载 8. 文章在推送三天后方可进行转载\n",
        "auhtor": "yJunS",
        "translator": "",
        "original": "",
        "poster": "./2019-05-20-translation-norms/banquan.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-17-from-jenkins-to-jenkins-x/",
        "title": "从 Jenkins 到 Jenkins X",
        "type": "wechat",
        "date": "2019-05-17 00:00:00 +0000 UTC",
        "tags": ["jenkins", "jenkins x", "kubernetes", "devops", "ci", "cd"],
        "description": "这是一个关于 dailymotion 从 Jenkins 到 Jenkins X 的旅程,我们遇到的问题,以及我们是如何解决它们的故事",
        "content": " 这是一个关于 dailymotion 从 Jenkins 到 Jenkins X 的旅程,我们遇到的问题,以及我们是如何解决它们的故事。\n我们的上下文 在 dailymotion ,我们坚信 devops 最佳实践,并且在 Kubernetes 投入了大量投资。 我们的部分产品已经部署在 Kubernetes 上,但并不是全部。 因此,当迁移我们的广告技术平台的时候,我们想要完全采用“ Kubernetes 式”——或者云原生,以追随技术趋势! 这意味着要重新定义整个 CI/CD 流水线,从静态/永久环境迁移,转向动态按需分配环境。 我们的目标是授权给我们的开发人员,缩短我们的上线时间以及降低我们的运营成本。\n对于新的 CI/CD 平台我们的初始需求是: - 尽可能避免从零开始:我们的开发人员已经习惯使用 Jenkins 和声明式流水线,并且它们可以很好地满足我们当前的需求。 - 以公有云基础设施为目标——Google 云平台和 Kubernetes 集群 - 与 gitops 方法论兼容——因为我们喜欢版本控制、同行评审和自动化\n在 CI/CD 生态系统中有相当多的参与者,但是只有一个符合我们的需求,Jenkins X ,它基于 Jenkins 和 Kubernetes ,原生支持预览环境和 gitops\nKubernetes 之上的 Jenkins Jenkins X 的设置相当简单,并且在他们的官方网站上已经有很好的文档(译注:译者曾对 Jenkins X 文档中文本地化做了一些贡献,同时也期待更多的人参与以完善中文文档)。 由于我们已经使用了 Google Kubernetes Engine (GKE),所以 jx 命令行工具自己创建了所有东西,包括 Kubernetes 集群。 这里有一个小小的*哇哦效果*,在几分钟内获得一个完整的工作系统是非常令人印象深刻的。\nJenkins X 提供了很多快速入门和模板来增加*哇哦效果*, 然而,在 dailymotion ,我们已经有了带有 Jenkins 流水线的仓库,我们想要重用它们。 我们决定以\u0026rdquo;艰难的方式\u0026rdquo;做事情,并重构我们的声明式流水线,使它们与 Jenkins X 兼容。\n实际上,这一部分并不针对 Jenkins X ,而是基于 Kubernetes 插件在 Kubernetes 上运行 Jenkins 。 如果您习惯使用“经典的” Jenkins ,即在裸金属或虚拟机上运行静态代理,那么这里的主要更改是,每次构建都将在自己的短暂的 pod 上执行。 流水线的每个步骤都可以指定应该在 pod 的哪个容器上执行。 在插件的源代码中有一些流水线的例子。 在这里,我们的\u0026rdquo;挑战\u0026rdquo;是定义容器的粒度,以及它们将包含哪些工具:需要足够的容器,以便我们可以在不同流水线之间重用它们的镜像,但也不能太多,以控制维护量——我们不想花时间重新构建容器镜像。\n以前,我们通常在 Docker 容器中运行大多数流水线步骤,当我们需要自定义步骤时,我们在运行中的流水线中构建它,就在运行它之前。 虽然它比较慢,但是易于维护,因为所有内容都是在源代码中定义的。 例如,升级 Go 运行时的版本可以在一个 pull-request 中完成。 因此,要预先构建容器镜像听起来像是给现有设置增加了更多的复杂性。 它还有几个优点:仓库之间的重复更少,构建速度更快,并且不会因为某些第三方托管平台宕机而出现更多构建错误。\n在 Kubernetes 上构建镜像 这些天将给我们带来一个有趣的话题:在 Kubernetes 集群中构建容器镜像。\nJenkins X 附带了一组\u0026rdquo;构建打包\u0026rdquo;,使用 \u0026ldquo;Docker in Docker\u0026rdquo; 从容器内部构建镜像。 但是随着新的容器运行时的到来,Kubernetes 推出了它的容器运行时接口( CRI ),我们想要探索其他的选择。 Kaniko 是最成熟的解决方案,符合我们的需求/技术栈。 我们很兴奋……\n……直到我们遇到两个问题: - 第一个问题对我们来说是一个阻塞问题:多阶段构建不起作用。 多亏了谷歌,我们很快发现我们不是唯一受到影响的人,而且目前还没有解决办法。 然而,Kaniko 是用 Go 开发的,而我们是 Go 开发人员,所以……为什么不看看源代码呢? 事实证明,一旦我们理解了问题的根本原因,修复就很容易了。 Kaniko 维护者是很愿意帮忙的,并且快速地合并了修复,所以一天之后一个被修复的 Kaniko 镜像就已经可用了。 - 第二个问题是,我们不能使用同一个 Kaniko 容器构建两个不同的镜像。 这是因为 Jenkins 并没有按照预期的方式使用 Kaniko ——因为我们需要先启动容器,然后再运行构建。 这一次,我们找到了一个针对谷歌的解决方案:声明我们所需要的尽可能多的 Kaniko 容器来构建镜像,但是我们不喜欢它。 所以回到源代码,再一次,一旦我们理解了根本原因,修复就很容易了。\n我们测试了一些解决方案来为 CI 流水线构建定制的\u0026rdquo;工具\u0026rdquo;镜像, 最后,我们选择使用一个单个仓库,每个分支对应一个 Dockerfile 和镜像。 因为我们将源代码托管在 Github 上,并且使用 Jenkins Github 插件来构建我们的仓库, 所以它可以构建我们所有的分支,并为 webhook 事件上的新分支创建新的任务,这使得管理起来很容易。 每个分支都有自己的 Jenkinsfile 声明式流水线,使用 Kaniko 构建镜像,并将其推入我们的容器注册中心。 这对于快速添加新镜像或编辑现有的镜像非常有用,因为我们知道 Jenkins 会处理好所有的事情。\n声明所需资源的重要性 我们在之前的 Jenkins 平台中遇到的一个主要问题来自静态的代理/执行器,在高峰时间有时构建队列很长。 Kubernetes 之上的 Jenkins 使这个问题很容易解决,主要是在 Kubernetes 集群上运行时,它能支持集群自动伸缩。 集群将根据当前负载简单地添加或删除节点。 但这是基于所请求的资源,而不是基于所观察到的使用的资源。 这意味着,作为开发人员,我们的工作是在构建 pod 模板中定义所需的资源( CPU 和内存)。 然后 Kubernetes 调度程序将使用此信息找到一个匹配的节点来运行 pod ——或者它可能决定创建一个新的节点。 这真是太好了,因为我们不再有长构建队列。 但相反,我们需要谨慎地定义我们所需资源的恰当数量,并在更新流水线时更新它们。 由于资源是在容器级别定义的,而不是在 pod 级别定义的,所以处理起来有点复杂。 但是我们不关心限制,只关心请求。 pod 的请求只是所有容器请求的相加。 因此,我们只是将整个 pod 的资源请求写在第一个容器上——或者 jnlp 容器上——它是默认的容器。 下面是我们使用的一个 Jenkinsfile 的例子, 也是我们如何声明请求的资源的例子:\npipeline { agent { kubernetes { label 'xxx-builder' yaml \u0026quot;\u0026quot;\u0026quot; kind: Pod metadata: name: xxx-builder spec: containers: - name: jnlp  Jenkins X 上的预览环境 现在我们已经拥有了所有的工具,并且能够为我们的应用程序构建一个镜像, 我们准备下一步:将它部署到\u0026rdquo;预览环境\u0026rdquo;!\nJenkins X 通过重用现有的工具——主要是 Helm ,使得部署预览环境变得很容易, 只要你遵循一些约定,例如用于镜像标签的值的名称。 最好是从\u0026rdquo;包\u0026rdquo;中提供的 Helm charts 复制/粘贴。 如果你不熟悉 Helm ,它基本上是一个 Kubernetes 应用程序包管理器。 每个应用程序都打包为一个 \u0026ldquo;chart\u0026rdquo; ,然后可以通过使用 helm 命令行工具作为一个 \u0026ldquo;release\u0026rdquo; 被部署。 预览环境是通过使用 jx 命令行工具进行部署的,该工具负责部署 Helm chart ,并以评论的形式,将所公开服务的 URL 添加到 Github pull-request 中。 这一切都非常好,而且对于我们第一个使用纯 http 的 POC 来说很有效。 但现在是2018年(译注:作者是在2018年写的这篇文章),没有人再使用 http 了。 让我们加密吧! 多亏了 cert-manager,当在 kubernetes 中创建 ingress 资源时,我们可以自动为我们的新域名获得一个 SSL 证书。 我们试图在我们的设置中启用 tls-acme 标志——与 cert-manager 进行绑定,但是它不起作用。 这给了我们一个机会来看看 Jenkins X 的源代码——它也是用 Go 开发的。 稍作修复之后都好了, 现在我们可以使用 let\u0026rsquo;s encrypt 提供的自动化证书来享受安全的预览环境。\n我们在预览环境中遇到的另一个问题与上述环境的清理有关。 每个打开一个 pull-request ,就创建一个预览环境,因此在 pull-request 被合并或关闭时应该删除预览环境。 这由 Jenkins X 设置的 Kubernetes 任务来处理,它删除了预览环境所使用的名称空间。 问题是这个任务不会删除 Helm release ——所以,比如如果您运行 helm list,您仍然会看到一个很大的旧的预览环境列表。 对于这个问题,我们决定改变使用 Helm 部署预览环境的方式。 Jenkins X 团队已经写过关于 Helm 和 Tiller ( Helm 的服务器端组件)的这些问题, 因此,我们决定使用 helmTemplate 特性标志,只使用 Helm 作为模板渲染引擎,并使用 kubectl 处理生成的资源。 这样,我们就不会用临时预览环境\u0026rdquo;污染\u0026rdquo; Helm releases 列表。\nGitops 应用到 Jenkins X 在初始化 POC 的某个阶段,我们对我们的设置和流水线感到满意,并希望将我们的 POC 平台转变为准生产的平台。 第一步是安装 SAML 插件以设置 OKTA 集成——以允许内部用户登录。 它运行得很好,几天后,我注意到我们的 OKTA 集成已经不再存在了。 我正忙着做其他事情,所以我只是问我的同事他是否做了一些改变,然后继续做其他事情。 但几天后再次发生时,我开始调查。 我注意到的第一件事是 Jenkins Pod 最近重新启动过。 但是我们有一个持久化的存储,我们的任务仍然在那里,所以是时候仔细看看了! 事实证明,用于安装 Jenkins 的 Helm chart 有一个启动脚本, 它从 Kubernetes configmap 重置了 Jenkins 配置。 当然,我们不能像在虚拟机上管理 Jenkins 那样管理在 Kubernetes 中运行的 Jenkins !\n因此,我们没有手动编辑 configmap ,而是后退一步,查看全局。 这个 configmap 本身由 jenkins-x-platform 管理, 因此升级平台将重置我们的自定义更改。 我们需要将我们的\u0026rdquo;定制\u0026rdquo;存储在安全的地方并跟踪我们的更改。 我们可以用 Jenkins X 的方式,用一个 umbrella chart 来安装/配置一切, 但是这种方法有一些缺点:它不支持 \u0026ldquo;secret\u0026rdquo; —— 我们将一些敏感的值存储在我们的 Git 仓库中—— 它\u0026rdquo;隐藏\u0026rdquo;了所有的 sub-charts 。 所以,如果我们列出所有已安装的 Helm releases ,我们将只看到一个。 但是还有其他基于 Helm 的工具,它们更对 Gitops 更友好。 Helmfile 就是其中之一,它通过 helm secrets 插件和 sops为 secrets 提供了原生支持。 我现在不会详细介绍我们的设置,但别担心,这将是我下一篇博客文章的主题!\n迁移 我们故事的另一个有趣的部分是从 Jenkins 到 Jenkins X 的实际迁移。 以及我们如何使用两个构建系统处理仓库。 首先,我们设置新的 Jenkins 来只构建 \u0026ldquo;jenkinsx\u0026rdquo; 分支, 并且更新了旧的 Jenkins 的配置来构建除 \u0026ldquo;jenkinsx\u0026rdquo; 分支之外的所有分支。 我们计划在 \u0026ldquo;jenkinsx\u0026rdquo; 分支中准备新的流水线,并将其合并以进行迁移。 对于我们的初始化 POC ,它工作得很好,但是当我们开始使用预览环境时, 我们必须创建新的 PR ,而这些 PR 不是基于新的 Jenkins 构建的,因为分支限制。 因此,我们选择在这两个 Jenkins 实例上构建一切, 但对于旧的 Jenkins 使用 Jenkinsfile 文件名,对于新的 Jenkins 使用 Jenkinsxfile 文件名。 迁移之后,我们将更新此配置并重命名文件,但这是值得的, 因为它使我们能够在两个系统之间进行平滑的转换,并且每个项目都可以自己迁移,而不会影响其他项目。\n我们的目的地 所以,Jenkins X 为大家准备好了吗?老实说,我不这么认为。 并非所有功能和所支持的平台—— Git 托管平台或 Kubernetes 托管平台——都足够稳定。 但是,如果您准备投入足够的时间来深入研究,并选择适合您的使用场景的稳定特性和平台, 那么您将能够使用 CI/CD 等所需的一切来改进您的流水线。 这将缩短您的上线时间,降低您的成本,如果您对测试也很认真,那么请对您的软件质量充满信心。\n一开始,我们说这是我们从 Jenkins 到 Jenkins X 的旅程。但我们的旅程并未结束,我们还在旅行中。 部分原因是我们的目标仍在移动:Jenkins X 仍处于大的发展阶段,而且它本身正在朝着 Serverless 的方向前进, 目前正在使用 Knative 构建 的路上。 它的目的地是云原生 Jenkins 。 它还没有准备好,但是您已经可以预览它的外观了。\n我们的旅程还将继续,因为我们不希望它结束。 我们现在的目的地并不是我们的最终目的地,而是我们不断进化的一个步骤。 这就是我们喜欢 Jenkins X 的原因:因为它遵循相同的模式。 那么,你在等待什么来开始你自己的旅程呢?\n 译注:译者曾对 Jenkins X 文档中文本地化做了一些贡献,同时也期待更多的人在 Jenkins X 旅程中, 能够参与到 Jenkins 中文社区以完善 Jenkins X 的中文文档。\n ",
        "auhtor": "Vincent Behar",
        "translator": "donhui",
        "original": "https://medium.com/dailymotion/from-jenkins-to-jenkins-x-604b6cde0ce3",
        "poster": "“./2019-05-20-from-jenkins-to-jenkins-x/journey.jpeg”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-16-cloud-agnostic-automated-cicd-for-k8s/",
        "title": "与云无关的用于 Kubernetes 的自动化 CI/CD ",
        "type": "wechat",
        "date": "2019-05-16 00:00:00 +0000 UTC",
        "tags": ["cd", "ci", "kubernetes"],
        "description": "请看看您可能想要用来设置与云无关的生产和开发环境的一些工具和流程。",
        "content": " 在本文中,我想讨论一种在云环境中为 Kubernetes 工作负载实现自动化端到端 CI/CD 的方法。 这里可能有其它解决方案,而像 AWS、Microsoft Azure 和 GCP 这样的云提供商也提供了自己的一套框架,以实现与 Kubernetes 相同的目标。\n它的部署模型的核心是 Rancher,Rancher 负责为托管在不同云环境和裸机环境中的多个 Kubernetes 集群提供集中管理与运营的能力。 根据应用程序和业务需要,这里提到的工具可以替换为自己选择的工具。\n在详细介绍之前,这里有张部署模型的快照:\n持续集成组件 我们使用 JIRA、BitBucket、Bamboo 和 Nexus 作为自动化持续集成组件。 需求和用户故事来自 JIRA ; 开发人员将他们的代码放进 BitBucket ; 代码被代码评审工具和静态分析工具构建与集成,Bamboo 生成的 Docker 镜像被推送到 Nexus。 这些镜像会经过特定的容器安全检查。\n当你有许多微服务/应用程序需要构建时,那么处理 Kubernetes 集群工作负载的部署、升级和回滚可能会复杂。 版本控制是我们需要考虑的另一个挑战。 Helm 有助于克服这些大多数挑战,并使部署变得简单。\n如果你想知道你是否需要有一个 chart 将所有 deployments 包含在其中, 或者允许每个应用程序和微服务都有一个单独的 chart , 那么我们希望将这些 charts 放到特定的应用程序或微服务的仓库中, 这样我们就不需要有单独的仓库来维护 Helm 制品。 这就省去了为实际的代码和 Helm 模板维护两个独立仓库的工作。 开发人员可以对任何应用程序代码更改所需的模板更改有更多的控制权。\nNexus 作为 Docker 镜像和 Helm chart(使用的是 Helm Nexus 插件)的仓库。 每次成功构建应用程序后,镜像和 chart 都是可用的并被推送到 Nexus 。\n持续部署组件 为了实现与云无关的准备,我们选择了 Terraform ,因为它易于学习并易于部署。 我们发现对于准备后的配置管理/维护活动, Terraform 并不是非常有用,所以我们还放置了一些 Ansible 脚本。 我们也曾考虑 Ansible 用于准备,但是使用 Terraform 可以让我们更好地控制启动实例, 这些实例可以作为 Rancher Server/节点,并且可以被自动的添加到自动伸缩组中。 我们使用启动脚本功能实现了这一点。\n我们认为可以将为 AWS 编写的大多数 Terraform 脚本重用到 Azure 中,但事实并非如此。 我们必须做出相当大的改变。\n我们部署了一个运行在三个不同实例上的高可用的 Rancher Server ,前面有一个 NGINX Server 来为这三个实例做负载均衡。 部署是使用 Terraform 和启动脚本完成的。 脚本使用 RKE ( Rancher Kubenetes 引擎)和 Rancher API 调用来启动集群(高可用的 Rancher Server )。\nRancher 提供了各种选项来在不同的云提供商上添加 Kubernetes 集群。 您可以从选项中进行选择,使用托管的 Kubernetes 提供商,或者使用基础设施提供商的节点或自定义节点。 在这个场景中,我们选择使用 AWS 和 Azure 上的自定义节点,而不是托管的 Kubernetes 提供商。 这帮助我们向自动伸缩组添加一组工作节点,并使用集群自动伸缩器进行节点伸缩。\n所有这些都是通过启动脚本和 Rancher API 调用自动完成的,因此任何通过 ASG (和自动伸缩器)添加的新节点都会自动注册为一个 Rancher/Kubernetes 节点。 通过启动脚本自动执行的一些活动包括: - 安装和配置所需的 Docker 版本 - 在所有实例上安装和配置 Zabbix 代理(稍后将在监控中使用) - 安装所需的 GlusterFS 客户端组件 - 安装所需的 kubectl 客户端 - 后端数据库集群所需的任何其他自定义配置 - 自动挂载额外的 EBS 卷和 GlusterFS 卷 - 为 Rancher 代理/Kubernetes 节点运行 Docker 容器并附加特定的角色( etcd/controlplane/worker ) - 检查以确保 Rancher 代理可用、启动和运行。\nGlusterFS 被考虑可以处理 EBS 和 Azure 中不可用的 ReadWriteMany 磁盘卷类型。 这对于我们部署的许多应用程序都是必需的。\n一个 ELK stack ( ElasticSearch、Logstash 和 Kibana )使用 Helm charts 部署在 Kubernetes 上, 并被配置为通过 logstash 推送容器日志、审计和其他自定义日志。\nHAProxy 和 NGINX 被用于两个不同的目的。 NGINX 是在 Rancher Server HA 设置期间所提供的默认 ingress controller 。 这用于三个 Rancher Server 的负载均衡。 我们在 Kubernetes 集群上部署了一个 HAProxy Ingress Controller, 这样我们就可以通过这些特定的节点(其 IPs 映射到特定的 FQDNs)暴露应用程序的 end points 。 HAProxy ingress controller 被部署为 daemonset ,因此对于任何额外的负载,节点的数量会基于自动伸缩组和自动伸缩器自动增加。\n持续监控组件 我们部署了 Prometheus、Grafana 和 Alertmanager 套件,用于容量规划以及监控 Rancher/Kubernetes 集群的状态。 这再次通过 Rancher Helm Chart Provisioner 部署。 我们也可以通过常规的/稳定的 Helm charts 来部署它。 它确实有助于我们监控和收集开发环境中诸如 CPU、内存利用率和 IO 操作之类的指标,并据此为 staging 环境和生产环境进行容量规划。\n我们还在集群上部署了 Zabbix Server,它用于为部署的所有节点监控各种操作系统级别的和应用程序特定的指标和警告。 这包括任何后端数据库集群节点、Kubernetes 节点、Rancher servers、文件服务器或通过 Terraform 提供的任何其他服务器。 Zabbix Server 被配置为节点/代理自动注册,以便通过自动缩放组或自动缩放器添加到集群中的任何新节点都可用于监控。\n结论 这是我们为 Kubernetes 工作负载构建完整的 CI/CD 工具链所遵循的方法之一。 这个模型帮助我们自动化所有的三个环境的准备。 通过 Rancher ,我们能够提供一个开发环境,每个开发人员都可以使用这个项目概念。 每个开发人员都有一个节点和一个项目,它由 RBAC 控制,这样他们就可以部署和测试他们自己的更改。 没有人可以看到项目/节点的详细信息,也不会妨碍其他开发人员部署的 Kubernetes 工作负载。 由于节点自动注册到 Rancher Server,系统重新启动不会影响节点的可用性。 即使在最坏的情况下,如果节点丢失,也很容易在几分钟内打开一个新节点。 应用程序可以使用 Helm charts 进行部署,也可以使用 Rancher 提供的内置的 Helm charts 进行部署。\n这些是我们部署的来管理整个环境的一些高级组件。 我们考虑的其他方面是高可用性集群环境,用于 Rancher servers、Kubernetes 集群、Gluster 文件服务器集群或任何其他后端集群。 在提出此方法时,需要考虑生产级环境所需的更改和更新。 还考虑了其他方面,例如对集群实例的安全访问、升级、备份和恢复,以及根据行业标准提出的分层体系结构建议。\n希望本文为您提供一些参考,当您计划为多个云提供商提供生产级环境准备时,可以考虑这些参考。\n",
        "auhtor": "Ravi Sarma Kasibhatla",
        "translator": "donhui",
        "original": "https://dzone.com/articles/cloud-agnostic-automated-cicd-for-k8s",
        "poster": "../../../images/articles/2019/04/2019-05-16-cloud-agnostic-automated-cicd-for-k8s/blue.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/about/plugins/",
        "title": "插件列表",
        "type": "about",
        "date": "2019-05-15 20:30:05 +0800 +0800",
        "tags": [],
        "description": "Jenkins 中文社区维护的插件",
        "content": "下面的列表是由 Jenkins 中文社区的成员维护的插件:\n   插件 GitHub 仓库 版本 安装量 主要维护者     Simplified Chinese Plugin jenkinsci/localization-zh-cn-plugin    LinuxSuRen    Hugo Plugin jenkinsci/hugo-plugin    LinuxSuRen    Maven SNAPSHOT Check Plugin jenkinsci/maven-snapshot-check-plugin    donhui    Code Coverage API Plugin jenkinsci/code-coverage-api-plugin    cizezsy    WeiBo Plugin jenkinsci/weibo-plugin    LinuxSuRen    Job priorty sorter for Multi-branch Job jenkinsci/multi-branch-priority-sorter-plugin    LinuxSuRen     同时也期待有更多的贡献者增砖添瓦。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-15-gsoc-annoncement/",
        "title": "19年 GSoC 中 Jenkins 的七个项目",
        "type": "wechat",
        "date": "2019-05-15 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "Jenkins 社区在 Google Summer of Code 中的项目",
        "content": "Google Summer of Code (GSoC) 项目是一个年度性的全球化活动,该项目旨在鼓励高校学生在暑假期间参与到开源项目中来。\n通过审核的学生会收到由 Google 提供的带薪工作,参与到设计好的项目中以改进或提升 Jenkins 项目。作为回报,数名 Jenkins 社区成员会志愿作为学生“导师”来帮助他们融入开源社区并成功完成他们的夏令营项目。\nJenkins 社区从2009年开始以开源社区的身份参与到 GSoC 中,并分别在16年有5个项目、18年有3个项目被选中。 而今年的项目、导师的数量是最多的一年,相信在这个夏天里,Jenkins 社区可以给我们的用户带来很多不错的 成果,其中也许正有你或者你们团队所希望有的功能或者改进。\n2019年被选中的七个项目包括:\n 支持制品升级的流水线插件 基于云的外部工作空间管理器插件 多分支流水线对 Gitlab 的支持 插件安装管理器的 CLI 工具以及库 基于 Apache Kafka 以及 Kubernetes 的远程协议 基于角色策略的插件的改进 时间窗口插件——UI 改进  上面的每个项目都有一位学生主导进行,至少两位具有相关经验的导师加以指导,每周会有两次的同步会议来 保证方向与进度。当然,在开源社区里任何人都可以通过 PR 的形式对代码或者文档进行 Review。\n今年负责 GSoC 的管理员为:\n Martin d’Anjou Jeff Pearce Lloyd Chang Oleg Nenashev  我本人是“多分支流水线对 Gitlab 的支持”项目的领队导师,请大家与我一起期待这七位高校学生的精彩表现,后续社区也会及时发布上面项目的介绍以及进展。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“../../../images/gsoc/gsoc-big-logo.jpeg”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-14-devops-jenkins-credential-manage/",
        "title": "基于 Jenkins 的 DevOps 平台应该如何设计凭证管理",
        "type": "wechat",
        "date": "2019-05-14 00:00:00 +0000 UTC",
        "tags": ["jenkins", "devops"],
        "description": "一种基于 Jenkins 的 DevOps 平台建设思路",
        "content": " 背景 了解到行业内有些团队是基于 Jenkins 开发 DevOps 平台。而基于 Jenkins 实现的 DevOps 平台,就不得不考虑凭证的管理问题。\n本文就此问题进行讨论,尝试找出相对合理的管理凭证的方案。\n一开始我们想到的方案可能是这样的:用户在 DevOps 平台增加凭证后,DevOps 再将凭证同步到 Jenkins 上。Jenkins 任务在使用凭证时,使用的是存储在 Jenkins 上的凭证,而不是 DevOps 平台上的。\n但是,仔细想想,这样做会存在以下问题: * Jenkins 与 DevOps 平台之间的凭证数据会存在不一致问题。 * 存在一定的安全隐患。通过 Jenkins 脚本命令行很容易就把所有密码的明文拿到。哪天 Jenkins 被注入了,所有的凭证一下子就被扒走。 * 无法实现 Jenkins 高可用,因为凭证存在 Jenkins master 机器上。\n那么,有没有更好的办法呢?\n期望实现的目标 先定我们觉得更合理的目标,然后讨论如何实现。以下是笔者觉得合理的目标: \u0026gt; 用户还是在 DevOps 管理自己的凭证。但是 DevOps 不需要将自己凭证同步到 Jenkins 上。Jenkins 任务在使用凭证时,从 DevOps 上取。\n实现方式 Jenkins 有一个 Credentials Binding Plugin 插件,在 Jenkins pipeline 中的用法如下:\nwithCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) { sh ''' curl -u \u0026quot;$USERPASS\u0026quot; https://private.server/ \u0026gt; output ''' }  withCredentials 方法做的事情就是从 Jenkins 的凭证列表中取出 id 为 mylogin 的凭证,并将值赋到变量名为 USERPASS 的变量中。接下来,你就可以在闭包中使用该变量了。\n说到这里,不知道读者朋友是否已经有思路了?\n思路就是实现一个和 Credentials Binding Plugin 插件类似功能的方法,比如叫 zWithCredentials(后文还会提到)。与 withCredentials 不同的是,zWithCredentials 根据凭证 id 获取凭证时,不是从 Jenkins 上获取,而是从 DevOps 平台获取。\n会遇到的坑 需要适配只认 Jenkins 凭证的插件 withCredentials 方法是将凭证的内容存到变量中,这可以满足一大部分场景。但是有一种场景是无法满足的。就是某些 Jenkins 插件的步骤接收参数时,参数值必须是 Jenkins 凭证管理系统中的 id。比如 git 步骤中 credentialsId 参数:\ngit branch: 'master', credentialsId: '12345-1234-4696-af25-123455', url: 'ssh://git@bitbucket.org:company/repo.git'  这种情况,我们不可能修改现有的插件。因为那样做的成本太高了。\n那怎么办呢?\n笔者想到的办法是在 zWithCredentials 中做一些 hack 操作。也就是 zWithCredentials 除了从 DevOps 平台获取凭证,还在 Jenkins 中创建一个 Jenkins 凭证。在 Jenkins 任务执行完成后,再将这个临时凭证删除。这样就可以适配那些只认 Jenkins 凭证 id 的插件了。\n对凭证本身的加密 DevOps 平台在存储凭证、传输凭证给 Jenkins 时,都需要对凭证进行加密。至于使用何种加密方式,交给读者思考了。\n小结 以上解决方案对 Jenkins 本身的改造几乎没有,我们只通过一个插件就解耦了 Jenkins 的凭证管理和 DevOps 平台的凭证管理。\n思路已经有了。具体怎么实现,由于一些原因不能开源,虽然实现起来不算难。还请读者见谅。\n最后,希望能和遇到同样问题的同学进行交流。看看是否还可以有更好的设计思路。\n",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "./2019-05-14-devops-jenkins-credential-manage/devops-platform-lock-jenkins.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-13-jenkins-book-gift/",
        "title": "Jenkins 公众号送书福利",
        "type": "wechat",
        "date": "2019-05-13 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "赠送 5 本《Jenkins 2.x实践指南》",
        "content": " Jenkins 中文社区是一个开放、包容、活跃的社区,包含大量的 Jenkins 干货。\n当然,它也会为公众号的粉丝们发放福利。\n本次福利是《Jenkins 2.x实践指南》x 5,以下是介绍:\n本次活动书籍均由博文视点(Broadview)提供,特此感谢。\n参与方式:  关注本公众号,并在后台回复【抽奖】,根据二维码进入小程序抽奖。 开奖时间为:5月19日晚上7点自动开奖(记得填自己的手机号,地址以便中奖后邮寄发出)。  中奖的同学,不要忘记发朋友圈分享支持噢~\n等不急的同学,还可以扫二维码直接购买:\n",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "./2019-05-13-jenkins-book-gift/poster.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-13-cdf-call-for-papers/",
        "title": "持续交付峰会 Call For Papers",
        "type": "wechat",
        "date": "2019-05-13 00:00:00 +0000 UTC",
        "tags": ["cdf", "cfp"],
        "description": "持续交付基金会在上海 KubeCon 的同场活动",
        "content": " 持续交付峰会是一个为期一天的活动,将开源 CI/CD 社区汇集在一起。这一天将包括主题演讲,项目展示和终端用户的故事,以及 BoF 会议。与同行会面并推动未来持续交付的方向。\n重要日期  CFP 开始:4月29日,星期一 CFP 关闭:太平洋标准时间 5月17日,23:59,星期五 CFP 通知:5月29日,星期三 日程通知:5月30日,星期一 幻灯片截止:6月17日,星期四 活动时间:6月24日  建议的话题  CDF 的项目  Jenkins Jenkins X Tekton 和 Spinnaker 讲述你正在使用的这些项目的功能或者集成的功能,分享你为什么要使用以及如何利用这些项目解决了哪些问题  你们团队的持续交付  我们希望能听到真实项目中的使用,以及你们团队所推荐的持续交付实践  安全与合规性最佳实践  分享在持续交付中改善你们的软件供应链中的安全性的案例和技巧  帮助我们的同时也帮助自己 描绘你希望看到的 CI/CD 景象   点击这里提交你的演讲题目\n点击这里查看其他更多的同场活动。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“../../../images/logos/cdf-logo.png”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-09-jenkins-release/",
        "title": "Jenkins 版本发布",
        "type": "wechat",
        "date": "2019-05-09 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "Jenkins 每周更新版发布",
        "content": " 2.175 (2019-04-28)  当构建完成后,更新状态图标 (issue 16750) 插件管理页面提供了更方便的插件更新选项,包括:“全选”、“兼容的“或”全不选“。 “兼容”的选择(之前为“全选”)已经不再包括含有任何兼容性警告的插件。 (issue 56477) 从连接 Jenkins 节点的界面上移除会误导到 Java Web Start 和 JNLP 的链接等引用。 (pull 3998) 再次启用 Stapler 请求分发 telemetry。 (pull 3999) 确保远程对象仅通过远程通道被序列化。 确定永远不会设计以 XML 形式持久化到磁盘中的类包括: FilePath, [Stream]TaskListener, and ProcessTree. (issue 47896) 修复在 Linux 代理安装器中看到的一些错误。 (issue 57071) 使得 Debian/Ubuntu 启动器脚本对 Java 11 兼容。 (issue 57096) 开发者:使得 mvn -f war hudson-dev:run支持${port}。 (pull 3984)  2.174 (2019-04-21)  重命名一个代理节点,保持旧的配置,导致重启后旧的代理节点再次出现。 (issue 56403) 嵌套的视图现在也可以根据名称搜索了。 (issue 43322)  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“../../../images/cow.jpg”"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-08-jenkins-plugin-develop-within-two-days-part02/",
        "title": "Jenkins 插件开发之旅:两天内从 idea 到发布(下篇)",
        "type": "wechat",
        "date": "2019-05-08 00:00:00 +0000 UTC",
        "tags": ["jenkins", "maven", "jira"],
        "description": "两天内,从产生 idea 到编写插件,最后发布到 Jenkins 插件更新中心",
        "content": " 本文分上下两篇,上篇介绍了从产生 idea 到插件开发完成的过程; 下篇将介绍将插件托管到 Jenkins 插件更新中心的一系列过程。\n托管插件 托管插件包括一系列流程步骤。 笔者完成了它所有步骤(包括非必须的步骤),其中主要有两个具有标志性的任务: - 插件代码被托管在 jenkinsci GitHub 组织的一个仓库,然后作者拥有它的管理权限。\n笔者插件的代码仓库为:jenkinsci/maven-snapshot-check-plugin 。 - 你可以将插件发布到 Jenkins 项目的 Maven 仓库,它是 Jenkins 项目所使用的更新站点的数据来源。\n准备工作 在请求插件托管之前,需要完成以下几个步骤。\n查找类似的插件 Jenkins 社区欢迎任何人的贡献,但为了让 Jenkins 用户受益, 它要求查找解决相同或类似问题的插件,看看是否可以与现有的维护人员联手。 可以在 https://plugins.jenkins.io 查看所有的插件, 以确认是否已有类似的插件实现了你计划实现的功能。 笔者在之前已进行过查找,并没有找到可以实现笔者计划实现的功能的类似插件。\n命名规约 Jenkins 制定了一些与插件相关的命名规约。 插件开发者要确保遵循这些命名规约。\nartifactId 插件的 artifactId 被用于文件基本名称,是 Jenkins 插件和更新站点的唯一标识。\n它需要遵循一些发布规约: - 使用小写 ID ,并根据需要使用连字符分隔术语。 - 除非名称有任何意义,否则不要在 ID 中包含 jenkins 或 plugin 。\n插件名称 插件的名称在 Jenkins UI 和其它地方(如:插件站点)展示给用户。\n如果可以,建议使用简短的描述性名称,如 Subversion 。\n笔者所写的插件的名称为:Maven SNAPSHOT Check 。\ngroupId 推荐使用 io.jenkins.plugins 或 org.jenkins-ci.plugins 作为 groupId 。 但是不禁止其他组织 ID ,除非它们是恶意的(例如引用与你没有关系的组织)。 笔者所写的插件使用的 groupId 为: org.jenkins-ci.plugins 。\nJava 源代码 Jenkins 项目一般遵循 Oracle Java 代码规约, 但是并没有很好的强制甚至在核心组件中。 个别的插件维护者有时会选择使用不同的风格指南作为插件。 笔者日常使用 IDEA 进行开发,之前安装了「阿里 Java 规约插件」, 因而使用它作为编码规约。\n提交消息 Git 提交消息应该从引用与之相关的 JIRA 问题开始(如果适用), 然后在第一行进行简短的总结,并在随后的行中提供更多详细信息。例如:\n[JENKINS-00000] Frobnicate the widget  如果给定的提交修复了指定的问题, 那么使用以下前缀中的任何一个将会自动化解决相关的 JIRA 问题。\n[FIX JENKINS-00000] Frobnicate the widget [FIXED JENKINS-00000] Frobnicate the widget [FIXES JENKINS-00000] Frobnicate the widget  由于还没过将插件托管,笔者并没有遵循该规约, 等插件发布后,笔者将考虑遵循该规约。\nLicense Jenkins 项目分发的所有插件都需要是免费的开源软件。 这适用于插件源代码及其所有依赖项。 要确保在 pom.xml 文件和仓库中的 LICENSE 文件指定协议。 官方建议使用 MIT license ,它用于 Jenkins 核心和大多数插件和库, 但是任何 OSI 批准的开源 license 都可以。 笔者这里使用了 MIT license 。\n要求注册的账号 通过 Jenkins 项目更新站点分发的插件需要托管在 jenkinsci GitHub 组织中, 因此需要在 GitHub 上有一个账号,并且需要有一个公共仓库来存放插件源代码。\n为了完整地发布你的插件,需要注册一个 Jenkins 社区帐号, 它可以让你访问 JIRA,wiki 和 Maven 仓库 。\n发起托管请求  注意:Jenkins 官方自动化流程使用更容易实现的 fork + 删除的方式(见下文),而不是转移仓库所有者。\n 登录到 JIRA 然后在 HOSTING 项目创建一个问题。 请确保按照描述填写所有字段。 Jenkins 项目成员将在几天内审查你的请求。 如果审查人员要求你更改,那么请按照要求进行更改。\n笔者提交的申请为:HOSTING-750, 比较幸运的是当天凌晨(北京时间)笔者的请求就被审查, 正巧那时笔者未眠,于是随后按要求进行了更改并在不久后该申请被审批通过。\n一旦满足了所有的需求,你的仓库将被 fork 到 jenkinsci 组织中, 并且你将被邀请加入该组织,并且将为你在 JENKINS 项目中创建 JIRA 组件。\n此时,将要求你删除 Jenkins 从中 fork 的仓库。 之后你可以通过再次从 jenkinsci 那里 fork 来重新创建它。 这将确保 jenkinsci 仓库是 Github 上网络图的根。 这意味着: - 不会混淆哪个仓库是权威仓库。 - 即使在 GitHub 上没有大量的关注者,源代码搜索也会成功。 - 其他人更可能在 jenkinsci 仓库中提交 pull request(这是协作的理想选择)。\n创建 wiki 页面 尽管这对发布插件来说这不是严格要求的,但最好为插件创建一个 wiki 页面来存储文档。关于如何执行此操作的详细信息,请参阅插件 wiki 页面指南。\n笔者所写的插件的 wiki 页面为:Maven SNAPSHOT Check Plugin 。 其间除了官方文档,笔者还参考了其它插件 wiki 页面的排版。\n开启 CI 构建 Jenkins 项目托管了一个 Jenkins 实例来执行插件的持续集成构建。 官方推荐通过在插件的 Github 仓库根目录创建一个 Jenkinsfile, 为在 Jenkinsci Github 组织中的插件设置 CI 构建。 典型的插件构建( Maven 或 Gradle )只需在 Jenkinsfile 中包含以下语句即可运行:\nbuildPlugin()  申请上传权限 在源代码被 fork 到 jenkinsci 组织后,需要提交一个上传权限请求。 按照 jenkins-infra/repository-permissions-updater/ 仓库的 README 文件中所说的来做就可以。\nJenkins 项目在 Artifactory 上托管 Maven 制品,例如核心和插件发布。 它的权限系统与 Github 是独立的, 限制了那些用户(由 Jenkins LDAP 帐户标识,与 wiki 和 JIRA 一样)可以上传。 这个仓库包含 YAML 格式的 Artifactory 上传权限定义, 以及将它们同步到 Artifactory 的工具。 \u0026gt; 先决条件:在申请权限之前,需要先用 Jenkins 社区帐号登录一次 Artifactory 。\n要请求对制品(通常是插件)的上传权限,需要提交一个 PR , 该 PR 需要创建与申请上传权限相关的 YAML 文件。 笔者所提交的 PR 为:Plugin: Permission for maven-snapshot-check-plugin 。\n通过查看它可以看出该 PR 增加了一个文件:permissions/plugin-maven-snapshot-check.yml ,其内容如下:\nname: \u0026quot;maven-snapshot-check\u0026quot; github: \u0026quot;jenkinsci/maven-snapshot-check-plugin\u0026quot; paths: - \u0026quot;org/jenkins-ci/plugins/maven-snapshot-check\u0026quot; developers: - \u0026quot;donhui\u0026quot;  在创建 PR 后,会有帮助说明以及 checklist 让提交人对该 PR 进行检查确认。\n等这个 PR 被审批后,插件开发者就会拥有该插件的发布权限。\n发布插件 前提 要先确认拥有发布该插件的权限。\nMaven 要使用的 Artifactory 凭据 需要告诉 Maven 访问 Artifactory 的凭据。 登录 Artifactory ,从用户 profile 中获取加密的密码。 在 ~/.m2/settings.xml 文件配置 server 认证信息,如下所示:\n\u0026lt;settings xmlns=\u0026quot;https://maven.apache.org/SETTINGS/1.0.0\u0026quot; xmlns:xsi=\u0026quot;http://www.w3.org/2001/XMLSchema-instance\u0026quot; xsi:schemaLocation=\u0026quot;https://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd\u0026quot;\u0026gt; \u0026lt;servers\u0026gt; \u0026lt;server\u0026gt; \u0026lt;id\u0026gt;maven.jenkins-ci.org\u0026lt;/id\u0026gt; \u0026lt;username\u0026gt;your_user_name_here\u0026lt;/username\u0026gt; \u0026lt;password\u0026gt;your_encrypted_password_here\u0026lt;/password\u0026gt; \u0026lt;/server\u0026gt; \u0026lt;/servers\u0026gt; \u0026lt;/settings\u0026gt;  配置 GitHub 以接受你的 SSH key 当执行 release 时,Maven Release Plugin 会自动往仓库推送代码, 所以需要配置 GitHub 以接受你的 SSH key 。\n更多信息可以参考:GitHub help on SSH 。\n执行发布 当 GitHub 和 Maven 凭据配置好后, 执行一次发布应该很简单,只需要运行下面的命令:\nmvn release:prepare release:perform  可能在执行发布时会遇到 \u0026ldquo;401 Unauthorized\u0026rdquo; 或 \u0026ldquo;403 Forbidden\u0026rdquo; 之类问题, 这一般是 settings.xml 配置问题或是没有上传权限。 一些公共的问题处理方案可以查看:HostingPlugins-Workingaroundcommonissues。\n插件发布后,8 小时内,将可以在插件更新中心看到它。\n笔者所写的 maven-snapshot-check 插件, 在插件列表页的地址为:https://plugins.jenkins.io/maven-snapshot-check 。\nJenkins 实例的插件管理页面的「可选插件」选项截图如下: 为插件分类 在 Jenkins 插件列表页面,可以对插件进行分类显示。\n要为插件添加一个分类,需要向 jenkins-infra/update-center2 仓库提交一个 PR 。 笔者所提交的 PR 为:add maven-snapshot-check category 。\n通过查看它可以看出该 PR 在 src/main/resources/label-definitions.properties 文件增加了一行,如下所示:\nmaven-snapshot-check=builder  总结 两天的 Jenkins 插件开发之旅(尤其是 04.24 晚上花了很多时间), 让笔者了解了插件开发的基本知识,并在托管插件的过程中学到一些知识。 然后在周末花了几个小时总结回顾,并将它写成文档。 同时也希望此文能给 Jenkins 插件开发者入门带来一点帮助!\n参考  Guide to Plugin Hosting Performing a Plugin Release  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "./2019-05-08-jenkins-plugin-develop-within-two-days-part02/sunset.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-07-jenkins-install-plugins-shell/",
        "title": "Jenkins 自动化安装插件",
        "type": "wechat",
        "date": "2019-05-07 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "Jenkins 批量安装指定版本插件",
        "content": " 手工安装 Jenkins 插件的方法 通常,我们有两种方法安装 Jenkins 插件。第一种方法是到 Jenkins 插件管理页面搜索插件,然后安装。第二种方法是上传 Jenkins 插件的 hpi 文件安装。这两种方法能满足大多数人的需求。\n第一种方法,如下图所示: 第二种方法,如下图所示: 但是对于需要保证 Jenkins 稳定或在 Jenkins 上进行二次开发的同学来说,以上方法是无法满足需求的。\n第一种方法是无法指定插件的版本。第二种方式必须自己找到该插件的依赖树,然后根据依赖关系一个个地安装。是的,手工上传插件的这种方法,Jenkins 是不会自动下载依赖的。\n还有,就是这两种方式都无法实现批量安装。\n自动安装插件的方法 那么,有什么方法能指定插件的版本,又能自动下载它的依赖,还能批量下载呢?\n幸运的是,Jenkins 的 Docker 镜像的代码仓库里的 install-plugins.sh 脚本已经实现。只不过需要我们拿过来小小修改才能使用。笔者修改后创建了相应的代码仓库:jenkins-install-plugins-shell 。链接在文章末尾。\n以下是 jenkins-install-plugins-shell 的使用方法: 1. 将代码 clone 到 JENKINS_HOME 目录中。\ncd $JENKINS_HOME git clone https://github.com/zacker330/jenkins-install-plugins-shell.git cd jenkins-install-plugins-shell   在 plugins.txt 中加入希望安装的插件 在 jenkins-install-plugins-shell 目录中,有一个 plugins.txt 文件,在文件中写入希望安装的插件及版本号。例如:  ansible:1.0 powershell:1.3  执行安装\n# Jenkins War 的路径,用于分析 export JENKINS_WAR_PATH=\u0026lt;Jenkins war文件的路径\u0026gt; chmod +x install-plugins.sh jenkins-support ./install-plugins.sh \u0026lt; plugins.txt  重启 Jenkins install-plugins 本质上做的事情就只是将插件从云端下载到 JENKINS_HOME 下的 plugins 目录中。要使安装的插件生效,还需要重启 Jenkins。\n  关于 Jenkins 插件的名称 Jenkins 插件有两个名称。一个叫 display name,一个叫 short name。比如 Ansible 插件的 disply name 为 Ansible plugin,short name 为 ansible。\n如何知道一个插件的 short name 呢?可以在 Jenkins 插件官网上找到,比如 Ansible 的:\n在 plugins.txt 中使用的是 short name。\n总结 笔者为什么一定要确定 Jenkins 插件的版本?是因为插件的版本会影响 Jenkins 流水线的可靠性。所以,笔者才会这么在意 Jenkins 插件的版本。\n附录  Jenkins 官方 Docker 镜像中的自动化插件安装脚本:https://github.com/jenkinsci/docker/blob/master/install-plugins.sh 笔者修改后的自动化插件安装脚本: https://github.com/zacker330/jenkins-install-plugins-shell  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "./2019-05-07-jenkins-install-plugins-shell/poster.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-06-jenkins-plugin-develop-within-two-days-part01/",
        "title": "Jenkins 插件开发之旅:两天内从 idea 到发布(上篇)",
        "type": "wechat",
        "date": "2019-05-06 00:00:00 +0000 UTC",
        "tags": ["jenkins", "maven", "jira"],
        "description": "两天内,从产生 idea 到编写插件,最后发布到 Jenkins 插件更新中心",
        "content": " 本文介绍了笔者首个 Jenkins 插件开发的旅程, 包括从产生 idea 开始,然后经过插件定制开发, 接着申请将代码托管到 jenkinsci GitHub 组织, 最后将插件发布到 Jenkins 插件更新中心的过程。\n鉴于文章篇幅过长,将分为上下两篇进行介绍。\n从一个 idea 说起 前几天和朋友聊天时,聊到了 Maven 版本管理领域的 SNAPSHOT 版本依赖问题, 这给他带来了一些困扰,消灭掉历史遗留应用的 SNAPSHOT 版本依赖并非易事。\n类似问题也曾经给笔者带来过困扰,在最初没能去规避问题, 等到再想去解决问题时却发现困难重重,牵一发而动全身, 导致这个问题一直被搁置,而这也给笔者留下深刻的印象。\n等到再次制定 Maven 规范时,从一开始就考虑 强制禁止 SNAPSHOT 版本依赖发到生产环境。\n这里是通过在 Jenkins 构建时做校验实现的。 因为没有找到提供类似功能的 Jenkins 插件, 目前这个校验通过 shell 脚本来实现的, 具体的做法是在 Jenkins 任务中 Maven 构建之前增加一个 Execute shell 的步骤, 来判断 pom.xml 中是否包含 SNAPSHOT 关键字,如果包含,该次构建状态将被标记为失败。 脚本内容如下:\n#!/bin/bash if [[ ` grep -R --include=\u0026quot;pom.xml\u0026quot; SNAPSHOT .` =~ \u0026quot;SNAPSHOT\u0026quot; ]]; then echo \u0026quot;SNAPSHOT check failed\u0026quot; \u0026amp;\u0026amp; grep -R --include=\u0026quot;pom.xml\u0026quot; SNAPSHOT . \u0026amp;\u0026amp; exit 1; else echo \u0026quot;SNAPSHOT check success\u0026quot;; fi  恰好前不久在看 Jenkins 插件开发文档, 那何不通过 Jenkins 插件的方式实现它呢?\n于是笔者开始了首个 Jenkins 插件开发之旅。\n插件开发过程 Jenkins 是由 Java 语言开发的最流行的 CI/CD 引擎。\n说起 Jenkins 强大的开源生态,自然就会说到 Jenkins 插件。 Jenkins 插件主要用来对 Jenkins 的功能进行扩展。 目前 Jenkins 社区有上千个插件, 用户可以根据自己的需求选择合适的插件来定制 Jenkins 。\n插件开发准备 插件开发需要首先安装 JDK 和 Maven,这里不做进一步说明。\n创建一个插件 Jenkins 为插件开发提供了 Maven 原型。 打开一个命令行终端,切换到你想存放 Jenins 插件源代码的目录,运行如下命令:\nmvn -U archetype:generate -Dfilter=io.jenkins.archetypes:  这个命令允许你使用其中一个与 Jenkins 相关的原型生成项目。\n$ mvn -U archetype:generate -Dfilter=io.jenkins.archetypes: ...... Choose archetype: 1: remote -\u0026gt; io.jenkins.archetypes:empty-plugin (Skeleton of a Jenkins plugin with a POM and an empty source tree.) 2: remote -\u0026gt; io.jenkins.archetypes:global-configuration-plugin (Skeleton of a Jenkins plugin with a POM and an example piece of global configuration.) 3: remote -\u0026gt; io.jenkins.archetypes:hello-world-plugin (Skeleton of a Jenkins plugin with a POM and an example build step.) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 3 Choose io.jenkins.archetypes:hello-world-plugin version: 1: 1.1 2: 1.2 3: 1.3 4: 1.4 Choose a number: 4: 4 ...... [INFO] Using property: groupId = unused Define value for property 'artifactId': maven-snapshot-check Define value for property 'version' 1.0-SNAPSHOT: : [INFO] Using property: package = io.jenkins.plugins.sample Confirm properties configuration: groupId: unused artifactId: maven-snapshot-check version: 1.0-SNAPSHOT package: io.jenkins.plugins.sample Y: : Y  笔者选择了 hello-world-plugin 这个原型, 并在填写了一些参数,如artifactId、version 后生成了项目。\n可以使用 mvn verify 命令验证是否可以构建成功。\n构建及运行插件 Maven HPI Plugin 用于构建和打包 Jenkins 插件。 它提供了一种便利的方式来运行一个已经包含了当前插件的 Jenkins 实例:\nmvn hpi:run  这将安装一个 Jenkins 实例,可以通过 http://localhost:8080/jenkins/ 来访问。 等待控制台输出如下内容,然后打开 Web 浏览器并查看插件的功能。\nINFO: Jenkins is fully up and running  在 Jenkins 中创建一个自由风格的任务,然后给它取个名字。 然后添加 \u0026ldquo;Say hello world\u0026rdquo; 构建步骤,如下图所示:\n输入一个名字,如:Jenkins ,然后保存该任务, 点击构建,查看构建日志,输出如下所示:\nStarted by user anonymous Building in workspace /Users/mrjenkins/demo/work/workspace/testjob Hello, Jenkins! Finished: SUCCESS  定制开发插件 Jenkins 插件开发归功于有一系列扩展点。 开发人员可以对其进行扩展自定义实现一些功能。\n这里有几个重要的概念需要做下说明:\n扩展点( ExtensitonPoint ) 扩展点是 Jenkins 系统某个方面的接口或抽象类。 这些接口定义了需要实现的方法,而 Jenkins 插件需要实现这些方法。\n笔者所写的插件需要实现 Builder 这个扩展点。 代码片段如下:\npublic class MavenCheck extends Builder {}  Descriptor 静态内部类 Descriptor 静态内部类是一个类的描述者,用于指明这是一个扩展点的实现, Jenkins 通过这个描述者才能知道我们写的插件。 每一个描述者静态类都需要被 @Extension 注解, Jenkins 内部会扫描 @Extenstion 注解来获取注册了哪些插件。\n代码片段如下:\n@Extension public static final class DescriptorImpl extends BuildStepDescriptor\u0026lt;Builder\u0026gt; { public DescriptorImpl() { load(); } @Override public boolean isApplicable(Class\u0026lt;? extends AbstractProject\u0026gt; aClass) { return true; } @Override public String getDisplayName() { return \u0026quot;Maven SNAPSHOT Check\u0026quot;; } }  在 DesciptorImpl 实现类中有两个方法需要我们必须要进行重写: isApplicable() 和 getDisplayName() 。 isApplicable() 这个方法的返回值代表这个 Builder 在 Jenkins Project 中是否可用, 我们可以将我们的逻辑写在其中,例如做一些参数校验, 最后返回 true 或 false 来决定这个 Builder 是否可用。\ngetDisplayName() 这个方法返回的是一个 String 类型的值, 这个名称被用来在 web 界面上显示。\n数据绑定 前端页面的数据要和后台服务端进行交互,需要进行数据绑定。 前端 config.jelly 页面代码片段如下:\n\u0026lt;?jelly escape-by-default='true'?\u0026gt; \u0026lt;j:jelly xmlns:j=\u0026quot;jelly:core\u0026quot; xmlns:st=\u0026quot;jelly:stapler\u0026quot; xmlns:d=\u0026quot;jelly:define\u0026quot; xmlns:l=\u0026quot;/lib/layout\u0026quot; xmlns:t=\u0026quot;/lib/hudson\u0026quot; xmlns:f=\u0026quot;/lib/form\u0026quot;\u0026gt; \u0026lt;f:entry title=\u0026quot;check\u0026quot; field=\u0026quot;check\u0026quot;\u0026gt; \u0026lt;f:checkbox /\u0026gt; \u0026lt;/f:entry\u0026gt; \u0026lt;/j:jelly\u0026gt;  如上所示,需要在 config.jelly 中包含需要传入的参数配置信息的选择框,field 为 check ,这样可以在 Jenkins 进行配置,然后通过 DataBoundConstructor 数据绑定的方式,将参数传递到 Java 代码中。 服务端 Java 代码片段如下:\n@DataBoundConstructor public MavenCheck(boolean check) { this.check = check; }  核心逻辑 笔者所写的插件的核心逻辑是检查 Maven pom.xml 文件是否包含 SNAPSHOT 版本依赖。\nJenkins 是 Master/Agent 架构, 这就需要读取 Agent 节点的 workspace 的文件, 这是笔者在写插件时遇到的一个难点。\nJenkins 强大之处在于它的生态,目前有上千个插件, 笔者参考了 Text-finder Plugin 的源码, 并在参考处添加了相关注释,最终实现了插件要实现的功能。\n详细代码可以查看 jenkinsci/maven-snapshot-check-plugin 代码仓库。\n分发插件 使用 mvn package 命令可以打包出后缀为 hpi 的二进制包, 这样就可以分发插件,将其安装到 Jenkins 实例。\n插件使用说明 以下是对插件的使用简要描述。\n如果勾选了下面截图中的选择框, Jenkins 任务在构建时将会检查 pom.xml 中是否包含 SNAPSHOT 。 如果检查到的话,则会将该次构建状态标记为失败。 总结 文章上篇主要介绍了从产生 idea 到插件开发完成的过程。\n那么插件在开发完成后是如何将它托管到 Jenkins 插件更新中心让所有用户都可以看到的呢?\n两天后的文章下篇将对这个过程进行介绍,敬请期待!\n参考  Plugin tutorial Preparing for Plugin Development Create a Plugin Build and Run the Plugin  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "./2019-05-06-jenkins-plugin-develop-within-two-days-part01/huashan.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-30-what-cicd-tool-should-i-use/",
        "title": "应该使用什么 CI/CD 工具?",
        "type": "wechat",
        "date": "2019-04-30 00:00:00 +0000 UTC",
        "tags": ["ci", "cd", "pipeline"],
        "description": "了解典型自动化 CI/CD 部署流水线的组件以及您需要的组件。",
        "content": " 在我们正在进行的 Kubernetes FAQ 系列中,我们回答了社区中一些常见的问题,本周我们将讨论在选择 CI/CD 工具时需要考虑什么。\n目前已经有大量的 CI/CD 工具可供选择-开源解决方案和商业解决方案。在这里,我们重点介绍在设置持续交付流水线时要考虑的一些最重要的注意事项。\n在这篇文章中你将学到: - 为什么需要自动化流水线 - 部署典型流水线的组件 - CD 流水线功能需要考虑 - 如何合并 GitOps\n为什么要创建自动化 CI/CD 流水线? 自动化 CI/CD 流水线有许多好处: - 将您的上线时间从数周或数月减少到数天或数小时。通过自动化流水线,开发团队可以提高发布的速度以及代码的质量。以小增量连续添加的新功能和修复可以使产品具有更少的缺陷。 - 一个强大的开发团队。由于交付流水线的所有阶段都可供团队中的任何人检查、改进和验证,因此可以创建对构建的所有权,从而鼓励整个组织的强大团队合作和协作能力。 - 降低软件开发的风险和成本。自动化鼓励开发人员在继续前进之前分阶段验证代码更改,从而减少了缺陷最终出现在生产中的机会。 - 减少进展中的工作量。CD 流水线提供从开发到客户的快速反馈循环。这个迭代周期不仅可以帮助您构建正确的产品,而且还允许开发人员更快地进行产品改进,从而减少正在进行的工作。 典型的部署流水线 CD 流水线由几个不同的阶段组成; 一个工具不能满足所有这些步骤。\n以下是构成大多数自动化流水线的步骤: 1. 在笔记本电脑上编写代码,将其推入源代码仓库(如 Git)。 2. 代码通过单元、集成和其他自动化测试。如果测试通过,将构建成新的 Docker 镜像。 3. 将镜像推送到镜像仓库。 4. 将新镜像推送到集群中。 思考 CD 流水线的特性 创建流水线的困难之一是成功地将您想要使用的工具粘合在一起。这些是为流水线选择工具时要考虑的主要功能: - 端到端的安全性 - 能够使用完全可重现的审计跟踪进行回滚 - 内置可观察性和警报功能 - 平均快速部署时间以及平均快速恢复时间 - 简单的开发人员经验和工作流程\n流水线端到端的安全性 在市场上的 CI/CD 工具中,有些工具将 CI 和 CD 部分合并为一个工具。或者更糟糕的是,那些负责创建 CI/CD 流水线的人将组装一系列手工锻造的脚本,这些脚本可以在一个方向上通过流水线推送代码,或执行被称为CIOP 流水线。\n出于多种原因,您不希望这样做。这是一种反模式,因为集群安全和其他凭据不在集群之外,这可能是不安全的。建议的方法是使用实​​现 Kubernetes Operator 的工具。\n部署到集群的 Kubernetes Operator 可以监视仓库中的新镜像。更进一步,如果您的整个集群状态(通过声明性清单)都保存在 Git 中,那么“diff alert”可以成为从仓库中“提取”新镜像并将其部署到集群的动力。这不仅是一种更安全的部署方法,而且还为开发人员提供了一种更简单的方法来应用和回滚生产环境的更改。\n具备完整审计跟踪回滚 跟踪差异历史记录,以及在团队中处理大型应用程序时管理新旧部署的回滚可能具有挑战性。您需要一个可以轻松处理此类方案的工具。如果您拥有一个完全可审计的路径,它可以帮助您了解何时何时执行了哪些操作,这也有助于 SOC 2合规性规定的增加。\n可观察性和警报 将可观察性纳入您的流水线意味着什么?\n为了提高你的速度,你的流水线需要结合可观察性来回答这些问题:\n如果自动发布更改,我怎么知道它是否有效? 在复杂的分布式系统中,我如何理解问题、诊断问题并管理事件 - 尤其是当您需要回滚时? 将持续交付与实时可观察性相结合,使您的开发团队能够在部署新功能之前做出更好的决策。\n新功能和补丁被推送到 Git 并触发部署流水线,当它们准备好发布时,理想情况下应该对正在运行的集群实时监控。这允许开发人员根据反馈做出决策。可以将它们返回到流水线的起点,或将更新后的镜像部署到生产集群中。 更快的平均部署和恢复时间 除了能够频繁可靠地部署之外,还需要考虑考虑一个重要场景,是在集群宕机时的恢复。这需要快速、平滑,并且可能由可能不是由 Kubernetes 专业的开发人员来执行。\n简单的开发人员经验和 Git 工作流程 为了在当今的云原生世界中快速发展,开发人员必须从端到端控制流水线。提交凭据等待人来回复的时期已经没有了。从开发人员一直使用的工具构建流水线是有意义的。像 Git 这样的工具。\n使用 GitOps,有三个基本原则:\n#1.所有可以描述的内容都必须存储在 Git 中 通过使用 Git 作为事实源,可以观察集群并将其与所需的状态进行比较。目标是描述所有内容:策略、代码、配置,甚至监控事件和版本控制。将所有内容保持在版本控制之下,可以增强收敛性,如果最初它们没有成功,则可以重新应用更改。\n#2.不要直接使用 kubectl 一般来说,使用命令行工具 kubectl 直接部署到集群不是一个好主意。许多人让他们的 CI 工具推动部署,但是这样做可能会对生产环境遭受更容易被攻击的风险。\n#3.使用遵循操作符模式的 Kubernetes Operator 使用遵循操作符模式的 Kubernetes Operator,您的集群始终通过其签入 Git 的配置文件与“事实源”保持同步。由于集群的所需状态保存在 Git 中,因此还可以观察到与正在运行的集群的差异。\n将 GitOps 工作流程应用于流水线 通过采用 GitOps,开发人员可以通过提取请求管理基础架构配置和软件部署以及回滚。当真实来源与集群中运行的不同时,集群会自动与 Git 中保存的内容同步。 Weave Cloud 的部署代理在集群内部运行。这意味着容器映像注册表和集群 API 的凭据永远不会离开集群的域。通过使用 Git 作为事实源,可以比较和警告所需的状态和当前状态。这不仅可以确保集群保持最新,而且还可以在集群崩溃时提供从灾难中快速恢复的方法。\n",
        "auhtor": "Anita Buehrle",
        "translator": "yJunS",
        "original": "https://dzone.com/articles/what-cicd-tool-should-i-use",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-29-progressive-delivery-with-jenkins-x-automatic-cana/",
        "title": "使用 Jenkins X 渐进式交付:自动化金丝雀部署",
        "type": "wechat",
        "date": "2019-04-29 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "为了避免渐进式交付可能带来的麻烦,学习使用 Jenkins X 为金丝雀发布自动部署。",
        "content": " 这是渐进式交付系列的第三篇文章,前两篇请参见: - Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署 - 使用 Jenkins X 渐进式交付\n渐进式交付被 Netflix, Facebook 以及其它公司使用用来减轻部署的风险。 但是现在你可以在使用Jenkins X时采用它。\n渐进式交付是持续交付的下一步,它将新版本部署到用户的一个子集,并在将其滚动到全部用户之前对其正确性和性能进行评估,如果不匹配某些关键指标,则进行回滚。\n尤其是,我们聚焦金丝雀发布,并让它在你的 Jenkins X 应用中变得易于采用。 金丝雀发布包括向应用程序的新版本发送一小部分流量,并在向其他用户发布之前验证这里没有错误。 Facebook 就是这样做的,首先向内部员工提供新版本,然后是一小部分用户,然后是其他所有用户,但是你要采用它并不需要成为 Facebook !\n你可以在 Martin Fowler 的网站阅读更多与金丝雀发布相关信息。\nJenkins X 如果在 Jenkins X 中你已经有一个应用,那么你知道的你可以 通过 jx promote myapp --version 1.0 --env production 命令 promote 它到\u0026rdquo;生产\u0026rdquo;环境。 但是,在检查新版本是否失败的同时,它也可以自动并逐步地向一定比例的用户推出。 如果发生失败,应用程序将自动回滚。 整个过程中完全没有人为干预。\n注意:这个新功能是非常新的,在将来这些步骤将不再需要,因为它们也将由 Jenkins X 自动化了。\n作为第一步,三个 Jenkins X 插件需要被安装: - Istio : 一种服务网格容许我们管理我们服务的流量。 - Prometheus :Kubernetes 中最流行的监控系统。 - Flagger :一个使用 Istio 的项目,该项目使用 Prometheus 的指标自动化进行金丝雀发布和回滚。\n插件可以使用如下命令安装(使用一个最近版本的 jx CLI ): 1. jx create addon istio 2. jx create addon prometheus 3. jx create addon flagger\n这将在 jx-production 命名空间启动 Istio 来进行指标收集。\n现在获取 Istio ingress 的 IP ,并将一个通配符域名(如: *.example.com )指向它,以便我们可以使用它根据主机名路由多个服务。 Istio ingress 提供了金丝雀发布需要的路由能力(流量转移),传统的 Kubernetes ingress 对象不支持该功能。\n集群被配置后,是时候配置我们的应用了。 在 charts/myapp/templates 目录下向你的 helm chart 添加一个 canary.yaml。\n然后往 charts/myapp/values.yaml 追加如下内容,将 myapp.example.com 修改为你的主机名或域名:\n不久,当你从 Jenkins X 快速开始创建你的应用,将不再需要修改 canary.yaml 和 values.yaml 这两个文件,因为它们默认启用金丝雀部署。\n就这样!现在当使用 jx promote myapp --version 1.0 --env production 将你的应用 promote 到生产环境,它将执行一次金丝雀部署。 请注意,第一次被 promote 时,它不会执行金丝雀部署,因为它需要与以前的版本数据进行比较,但从第二次 promotion 开始,它将起作用。\n根据上面 values.yaml 文件中的配置,它看起来像: - 第 1 分钟:将 10% 的流量发送到新版本 - 第 2 分钟:将 20% 的流量发送到新版本 - 第 3 分钟:将 30% 的流量发送到新版本 - 第 4 分钟:将 40% 的流量发送到新版本 - 第 5 分钟:将 100% 的流量发送到新版本\n如果我们配置的指标(请求持续时间超过 500 毫秒或超过 1% 的响应返回 500 错误)失败,Flagger 将注意到失败,并且如果重复 5 次,它将回滚这次发布,将 100% 的流量发送到旧版本。\n获得金丝雀事件输出,执行如下命令: 1. $ kubectl -n jx-production get events \u0026ndash;watch\n2. \u0026ndash;field-selector involvedObject.kind=Canary 3. 23m \u0026hellip; New revision detected! Scaling up jx-production-myapp.jx-production 4. 22m \u0026hellip; Starting canary analysis forjx-production-myapp.jx-production 5. 22m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 10 6. 21m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 20 7. 20m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 30 8. 19m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 40 9. 18m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 50 10. 18m \u0026hellip; Copying jx-production-myapp.jx-production template spec to jx-production-myapp-primary.jx-production 11. 17m \u0026hellip; Promotion completed! Scaling down jx-production-myapp.jx-production\n仪表盘 为了可视化的目的,Flagger 包含一个 Grafana 面板,尽管它在金丝雀发布中不需要。 可以在本地通过 Kubernetes 端口转发访问它。\n然后使用 admin/admin 访问 http://localhost:3000/,选择 canary-analysis 面板以及 - namespace 选择 jx-production - primary 选择 jx-production-myapp-primary - canary 选择 jx-production-myapp\n它将为我们提供当前版本和新版本的对比视图,视图中包含不同指标(CPU,内存,请求持续时间,响应错误……)。\n附加说明 请注意 Istio 默认地将阻止从你的 Pod 访问外部集群(一种预计将在 Istio 1.1 中发生变化的行为)。 学习如何控制 Istio ingress 流量。\n如果因为指标失败出现自动回滚,生产环境的 Jenkins X GitOps 仓库会过时,仍然使用新版本而不是旧版本。 这是计划在即将发布的版本中修复的内容。\n",
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://dzone.com/articles/progressive-delivery-with-jenkins-x-automatic-cana",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-28-devsecops/",
        "title": "我们为什么需要 DevSecOps 和制品仓库?",
        "type": "wechat",
        "date": "2019-04-28 00:00:00 +0000 UTC",
        "tags": ["security", "devops"],
        "description": "Helen Beal 在 Nexus 用户大会上发表的关于构建 DevSecOps 的建议",
        "content": "Helen Beal 曾经在一次讨论什么是 DevSecOps 工程师的会议上发言。令她惊讶的是,在与会人员中,许多人都没有将安全机制引入 DevOps。在与人们讨论之后,她将大家的问题总结为三类:安全机制会制造额外的隔阂;组织中的人很难理解 DevOps,因此安全机制可能会造成更多困惑;可能没有为安全机制预留空间。\n当然,Helen 不同意这些观点。她在技术领域从业近20年,专注于软件开发生命周期,对于 DevOps 和DevSecOps 有一些自己的理解。她自称为 Ranger4 的 「DevOpsologist」,因为她帮助那里的组织实现 DevOps。她在世界各地分享知识,并且她将参加我们在 2018 年的 Nexus User Conference ,讨论工具仓库及其在 DevSecOps 工具链中的角色。\n从高层次来看,Helen 为 DevSecOps 提出了一些重要建议:\n 确保安全是每一个人的职责 认识到安全人员的匹配限制。平均而言,人员比例为 100 名开发人员 : 10 名运维人员 : 1名安全人员 尽早移交产品进行测试和验证。缺乏足够的安全人员会造成一定的约束,移交并自动执行任务可以减少瓶颈并提前解决问题。 积极主动地降低风险 培养安全文化  Helen 花了一些时间阐述如何培养安全文化,组织在维护系统和人员行为安全时可以采用的一些关键原则和行动。\n行为安全使个人和团队能够以安全的方式行事。为了培养行为安全,她建议:\n 让人们意识到,失败是一个学习机会 确保团队之间有共同的责任和目标 不要吝啬花时间做实验 使用可协作的平台来分享学习经验和最佳实践 对实验的过程进行回顾,并确保有后续  她提到了几个真实的例子,例如 Esty,LEGO 还有 P\u0026amp;G 的「失败奖励」以及 Spotify 用来展示和追踪失败的「失败墙」。\n系统安全能够保障你的基础设施安全,她关于培养系统安全的建议包括:\n 用持续集成进行构建 使用部署自动化来驱动一致性和可审计性,并允许即时重新部署上一个已知的可用版本 用 ChatOps 来归类问题和事件 使用应用程序性能管理以提早发现问题并警告 降低出现问题波及范围,例如使用功能开关,金丝雀测试,蓝/绿环境和微服务 将产品需求与服务台相结合 养成使用混沌工程来找到失败原因的习惯  在讲述 DevSecOps 案例并说明如何灌输安全文化后,她将话题转向如何使用制品仓库。 毕竟,这是一个 Nexus 会议,制品仓库是 Nexus 的特色。\n她引用了 Manfred Moser 的话:「开发软件中没有制品仓库和制造业中没有仓库是一样的。」你不会奢望在没有仓库的情况下开办工厂,软件开发也一样。制品仓库保存了你每次构建的结果,并且确保你拥有可用的构建。\n制品仓库位于 DevOps 工具链的集成阶段,尽管其在构思阶段可被用来表示你想使用的工具是可用状态。\n如果没有开源策略,你就不应该使用制品仓库。制品仓库会自动执行你的开源策略,这样就不会像 35% 的组织一样有开源策略但忽略它。\nHelen 利用 Nexus Lifecycle 来告诉开发人员如何更好地使用制品,降低风险,并协助运维和安全部门确保使用了正确的软件。\n最重要的是,如果你还没有用上 DevSecOps ,那你应该尽早启用。这是未来的趋势,它已经渡过了发展期成为了一个成熟的概念,也有成熟的工具来帮助你。这会花一些时间,但一定是值得的。\n如果对 Helen 的整篇演讲感兴趣,可以在 此处 免费观看。\n",
        "auhtor": "Derek Weeks",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/why-you-need-devsecops-and-artifact-repositories",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-26-progressive-delivery-with-jenkins-x/",
        "title": "使用 Jenkins X 渐进式交付",
        "type": "wechat",
        "date": "2019-04-26 00:00:00 +0000 UTC",
        "tags": ["progressive delivery", "kubernetes", "k8s", "jenkins", "jenkins x", "shipper", "istio", "flagger"],
        "description": "使用 Jenkins X 渐进式交付",
        "content": " 这是渐进式交付系列的第二篇文章,第一篇请看:Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署。\n我使用的我的 Croc Hunter 示例项目评估了 Jenkins X 中金丝雀部署和蓝绿色部署的三种渐进式交付方案。 - Shipper 为 Jenkins X 构建的 Helm 图表启用了蓝绿部署和多集群部署,但是对图表的内容有限制。 你可以在 staging 和生产环境之间做蓝绿部署。 - Istio 允许通过创建一个虚拟服务将一定比例的流量发送到 staging 或预览环境。 - Flagger 构建在 Istio 之上,并添加了金丝雀部署,可以根据指标自动进行滚动部署和回滚。 Jenkins X 可以通过创建一个 Canary 对象自动启用金丝雀功能,从而实现优雅的滚动部署,以升级到生产环境。\n这里可以查看 Shipper、Isito 和 Flager 的示例代码。\nShipper 由于 Shipper 对创建的 Helm 图表有多个限制,因此我必须对应用做一些更改。 而且 Jenkins X 只从 master 分支构建 Helm 包,所以我们不能做 PRs 的滚动部署,只能对 master 分支做滚动部署。\n应用标签不能包含发布名称,例如: app: {{ template “fullname” . }} 不起作用, 需要一些类似这样的标签: app: {{ .Values.appLabel }}。\n由 Jenkins X 生成的图表导致应用滚动失败,归因于生成的 templates/release.yaml 可能和 jenkins.io/releases CRD 冲突。\nChart croc-hunter-jenkinsx-0.0.58 failed to render: could not decode manifest: no kind \u0026quot;Release\u0026quot; is registered for version \u0026quot;jenkins.io/v1\u0026quot;  我们只需要将 jx step changelog 更改为 jx step changelog -generate-yaml =false ,这样就不会生成文件。\n在多集群环境,需要在 shipper 应用 yaml 中为 chartmuseum 和 docker registry 使用公开的 url,以便其他集群可以发现管理集群服务来下载图表。\nIstio 我们可以创建这个虚拟服务, 将所有进入 Ingress 网关的主机为 croc-hunter.istio.example.org 的请求的 1% 的流量发送到 Jenkins X 预览环境( PR 号为 35 )。\napiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: croc-hunter-jenkinsx namespace: jx-production spec: gateways: - public-gateway.istio-system.svc.cluster.local - mesh hosts: - croc-hunter.istio.example.com http: - route: - destination: host: croc-hunter-jenkinsx.jx-production.svc.cluster.local port: number: 80 weight: 99 - destination: host: croc-hunter-jenkinsx.jx-carlossg-croc-hunter-jenkinsx-serverless-pr-35.svc.cluster.local port: number: 80  Flagger 我们可以为 Jenkins X 在 jx-production 命名空间中部署的图表创建一个 Canary 对象, 所有新的 Jenkins X 对 jx-production 的 promotions 每次将自动滚动 10% , 如果出现任何失败,将自动回滚。\napiVersion: flagger.app/v1alpha2 kind: Canary metadata: # canary name must match deployment name name: jx-production-croc-hunter-jenkinsx namespace: jx-production spec: # deployment reference targetRef: apiVersion: apps/v1 kind: Deployment name: jx-production-croc-hunter-jenkinsx # HPA reference (optional) # autoscalerRef: # apiVersion: autoscaling/v2beta1 # kind: HorizontalPodAutoscaler # name: jx-production-croc-hunter-jenkinsx # the maximum time in seconds for the canary deployment # to make progress before it is rollback (default 600s) progressDeadlineSeconds: 60 service: # container port port: 8080 # Istio gateways (optional) gateways: - public-gateway.istio-system.svc.cluster.local # Istio virtual service host names (optional) hosts: - croc-hunter.istio.example.com canaryAnalysis: # schedule interval (default 60s) interval: 15s # max number of failed metric checks before rollback threshold: 5 # max traffic percentage routed to canary # percentage (0-100) maxWeight: 50 # canary increment step # percentage (0-100) stepWeight: 10 metrics: - name: istio_requests_total # minimum req success rate (non 5xx responses) # percentage (0-100) threshold: 99 interval: 1m - name: istio_request_duration_seconds_bucket # maximum req duration P99 # milliseconds threshold: 500 interval: 30s  ",
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://blog.csanchez.org/2019/01/24/progressive-delivery-with-jenkins-x/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-25-jenkins-ansible-nginx/",
        "title": "使用 Jenkins + Ansible 实现自动化部署 Nginx",
        "type": "wechat",
        "date": "2019-04-25 00:00:00 +0000 UTC",
        "tags": ["jenkins", "ansible", "nginx"],
        "description": "使用 Jenkins + Ansible 实现自动化部署 Nginx",
        "content": " 本文介绍如何使用 Jenkins + Ansible 实现对 Nginx 的自动化部署。最终达到的效果有如下几点: 1. 只要你将 Nginx 的配置推送到 GitHub 中,Jenkins 就会自动执行部署,然后目标服务器的 Nginx 配置自动生效。这个过程是幂等(idempotent)的,只要代码不变,执行多少遍,最终效果不变。 2. 如果目标机器没有安装 Nginx,则会自动安装 Nginx。 3. 自动设置服务器防火墙规则。\n1. 实验环境介绍 本次实验使用 Docker Compose 搭建 Jenkins 及 Jenkins agent。使用 Vagrant 启动一台虚拟机,用于部署 Nginx。使用 Vagrant 是可选的,读者可以使用 VirtualBox 启动一个虚拟机。使用 Vagrant 完全是为了自动化搭建实验环境。\n以下是整个实验环境的架构图: 注意,图中的 5123 \u0026lt;-\u0026gt; 80 代表将宿主机的 5123 端口请求转发到虚拟机中的 80 端口。\n Vagrant:虚拟机管理工具,通过它,我们可以使用文本来定义、管理虚拟机。 Ansible:自动化运维工具 Docker Compose:它是一个用于定义和运行多容器 Docker 应用程序的工具。可以使用 YAML 文件来配置应用程序的服务。  2. 启动实验环境  克隆代码并进入文件夹 bash git clone https://github.com/zacker330/jenkins-ansible-nginx.git cd jenkins-ansible-nginx  构建 Jenkins agent 的镜像 需要自定义 Jenkins agent 镜像有两个原因:  本次实验,使用 Swarm 插件实现 Jenkins master 与 agent 之间的通信,所以 Jenkins agent 需要启动 swarm 客户端。 Jenkins agent 必须支持 Ansible。 bash docker build -f JenkinsSlaveAnsibleDockerfile -t jenkins-swarm-ansible .   启动 Jenkins master 及 Jenkins agent bash docker-compose up -d  通过 http://localhost:8080 访问 Jenkins master,如果出现“解锁密码”页面,如下图,则执行命令 docker-compose logs jenkins 查看 Jenkins master 启动日志。将日志中的解锁密码输入到表单中。然后就一步步按提示安装即可。  安装 Jenkins 插件 本次实验需要安装以下插件:  Pipeline 2.6:https://plugins.jenkins.io/workflow-aggregator Swarm 3.15:https://plugins.jenkins.io/swarm 用于 实现 Jenkins master 与 Jenkins agent 自动连接 Git 3.9.3:https://plugins.jenkins.io/git  配置 Jenkins master 不执行任务 进入页面:http://localhost:8080/computer/(master)/configure,如下图所示设置:  确认 Jenkins 安全配置有打开端口,以供 Jenkins agent 连接。 我们设置 Jenkins master 开放的端口,端口可以是固定的 50000 ,也可以设置为随机。设置链接:http://localhost:8080/configureSecurity/。  启动目标机器,用于部署 Nginx 在命令行中执行以下命令:\nvagrant up  注意,Vagrantfile 文件中的 config.vm.box 值必须改成你的 vagrant box 。\n  至此,实验环境已经搭建好了。接下来就可以新建 Jenkins 任务了。\n3. 在 Jenkins 上创建部署任务  新建流水线任务  配置流水线 配置 Jenkins 任务从远程仓库拉取 Jenkinsfile,如下图所示: 除此之外,不需要其它配置了,是不是很简单?\n4. 手工触发一次自动化构建 点击“立即构建”: 最终执行日志如下:   至此,部署已经完成。以后修改 Nginx 的配置,只需要修改代码,然后推送到远程仓库,就会自动化部署。不需要手工登录到目标机器手工修改了。\n最后,我们可以通过访问 http://localhost:5123,如果出现如下页面说明部署成功:\n5. 代码讲解 以上步骤并不能看出自动化部署真正做了什么。那是因为我们所有的逻辑都写在代码中。是的,可以说是 everything is code。\n接下来我们介绍代码仓库。\n% tree -L 2 ├── JenkinsSlaveAnsibleDockerfile # Jenkins agent 镜像 Dockerfile ├── Jenkinsfile # 流水线逻辑 ├── README.md ├── Vagrantfile # Vagrant 虚拟机定义文件 ├── docker-compose.yml # Jenkins 实现环境 ├── env-conf # 所有应用配置 │ └── dev # dev 环境的配置 ├── deploy # Ansible 部署脚本所在文件夹 │ ├── playbook.yaml │ └── roles └── swarm-client.sh # Jenkins swarm 插件的客户端  5.1流水线逻辑 Jenkinsfile 文件用于描述整条流水线的逻辑。代码如下:\npipeline{ // 任务执行在具有 ansible 标签的 agent 上 agent { label \u0026quot;ansible\u0026quot;} environment{ // 设置 Ansible 不检查 HOST_KEY ANSIBLE_HOST_KEY_CHECKING = false } triggers { pollSCM('H/1 * * * *') } stages{ stage(\u0026quot;deploy nginx\u0026quot;){ steps{ sh \u0026quot;ansible-playbook -i env-conf/dev deploy/playbook.yaml\u0026quot; } }}}   environment 部分:用于定义流水线执行过程中的环境变量。 triggers 部分:用于定义流水线的触发机制。pollSCM 定义了每分钟判断一次代码是否有变化,如果有变化则自动执行流水线。 agent 部分:用于定义整条流水线的执行环境。 stages 部分:流水线的所有阶段,都被定义在这部分。  以上只是定义流水线是如何执行的,目前整条流水线只有一个 deploy nginx 阶段,并且只执行了一条 ansible-playbook 命令。但是它并没有告诉我们部署逻辑是怎么样的。\n5.2 部署逻辑 所有的部署逻辑,包括 Nginx 的安装启动、配置的更新以及加载,都放在 Ansible 脚本中。对 Ansible 不熟的同学,可以在本文末尾找到介绍 Ansible 的文章。\n整个部署逻辑的入口在 deploy/playbook.yaml,代码如下:\n--- - hosts: \u0026quot;nginx\u0026quot; become: true roles: # Nginx 的部署 - ansible-role-nginx # 对防火墙的设置 - ansible-role-firewall   hosts:定义了 playbook 部署的目标主机分组名为 nginx。 roles:包含了两个执行具体部署动作的 role,至于 role 内部逻辑,不在本文讨论范围,有兴趣的同学阅读源码。  5.3 配置管理 谈到部署,就不得不谈配置管理。\n回顾前文中流水线中执行的 shell 命令:ansible-playbook -i env-conf/dev deploy/playbook.yaml 我们通过 -i 参数指定部署时所使用的环境配置。通过这种方式实现环境配置与执行脚本的分离。这样带来以下几个好处: 1. 新增环境时,只需要复制现有的环境,然后将里面的变量的值改成新环境的即可。比如,要对测试环境进行部署,只需要将 -i 参数值改成:env-conf/test。 2. 对配置版本化控制。\n本次实验中,各个环境的配置放在 env-conf 目录中,目前只有 dev 环境,以下是 env-conf/ 目录结构:\n% cd env-conf/ % tree └── dev ├── group_vars │ └── nginx.yaml ├── host_vars │ └── 192.168.52.10 └── hosts   hosts文件:Ansible 中通过“分组”来实现对主机的管理。hosts 文件内容如下:  [nginx] 192.168.52.10  host_vars 目录:用于存放主机级别的配置变量,本例中 192.168.52.10 是一个 YAML 格式文件。注意文件名是该主机的 IP。我们在文件中放主机相关的配置,比如 Ansible 连接主机时使用到的用户名和密码。 group_vars 目录:用于存放组级别的配置变量。比如 nginx.yaml 对应的就是 nginx 这个组的的配置变量。文件名与 hosts 中的组名对应。  总结 到此,我们完整的自动化部署已经讲解完成。但是还遗留下一些问题: 1. 本文只是安装了一个“空”的 Nginx,但是没有介绍 Nginx 真正配置。 2. 目前主机的连接信息(SSH 密码)是明文写在 host_vars/192.168.52.10 文件中的,存在安全风险。 3. 没有介绍如何当 Java 应用部署时,如何自动更新 Nginx 的配置。\n本文属于使用 Jenkins + Ansible 实现自动化部署的入门文章,笔者将根据读者的反馈决定是否写续集。\n如果觉得本文讲的 Jenkins 流水线逻辑部分不够过瘾,可以考虑入手一本最近才出版的《Jenkins 2.x实践指南》。长按下图进行扫码购买。\n附录  本次实验环境代码:https://github.com/zacker330/jenkins-ansible-nginx 简单易懂 Ansible 系列 —— 解决了什么:https://showme.codes/2017-06-12/ansible-introduce/ Puppet,Chef,Ansible 的共性:https://showme.codes/2016-01-02/the-nature-of-ansible-puppet-chef/  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-24-progressive-delivery-in-kubernetes-blue-green-and-canary-deployments/",
        "title": "Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署",
        "type": "wechat",
        "date": "2019-04-24 00:00:00 +0000 UTC",
        "tags": ["progressive delivery", "kubernetes", "k8s", "shipper", "istio", "flagger"],
        "description": "本文介绍 Kubernetes 中与渐进式交付相关的三个有趣的项目:Shipper、Istio 以及 Flagger ",
        "content": " 渐进式交付是持续交付的下一步, 它将新版本部署到用户的一个子集,并在将其滚动到全部用户之前对其正确性和性能进行评估, 如果不匹配某些关键指标,则进行回滚。\n这里有一些有趣的项目,使得渐进式交付在 Kubernetes 中变得更简单。 我将使用一个 Jenkins X 示例项目 对它们之中的三个进行讨论:Shipper、Istio 以及 Flagger。\nShipper shipper 是来自 booking.com 的一个项目, 它对 Kubernetes 进行了扩展,添加了复杂的部署策略和多集群编排(文档)。 它支持从一个集群到多个集群的部署,允许多区域部署。\nShipper 通过一个 shipperctl 命令行进行安装。 它增加不同集群的配置文件来进行管理。 请注意这个与 GKE 上下文相关的问题。\nShipper 使用 Helm 包来部署,但是它们没有随着 Helm 一起安装,它们不会在 helm list 的输出显示。 同样地,deployments 的版本必须是 apps/v1 , 否则 shipper 将不能编辑 deployment 来添加正确的标签和副本数量。\n使用 shipper 部署都是与从旧版本(现有版本)过渡到新版本(竞争版本)相关。 这是通过创建一个新的应用对象实现的, 它定义了部署需要通过的多个阶段。例如下面 3 个步骤过程: 1. Staging:部署新版本到一个 pod ,没有流量 2. 50 / 50:部署新版本到 50% 的 pods,50% 的流量 3. Full on:部署新版本到全部的 pods,全部的流量\nstrategy: steps: - name: staging capacity: contender: 1 incumbent: 100 traffic: contender: 0 incumbent: 100 - name: 50/50 capacity: contender: 50 incumbent: 50 traffic: contender: 50 incumbent: 50 - name: full on capacity: contender: 100 incumbent: 0 traffic: contender: 100 incumbent: 0  如果发布的某个步骤没有将流量发送到 pods , 则可以使用 kubectl port-forward 访问它们,如:kubectl port-forward mypod 8080:8080, 这对于在用户看到新版本之前进行测试非常有用。\nShipper 支持多集群的概念,但是以相同的方式对待所有集群,仅使用区域并通过 capabilities (配置在集群对象中)进行筛选, 所有对一个应用对象来说,这里没有一个 dev, staging, prod 集群的选项。 但是我们可以有两个应用对象: - myapp-staging 部署到 \u0026ldquo;staging\u0026rdquo; 区域 - myapp 部署到其它区域\n在 GKE 中,你可以轻松地配置多集群 ingress , 该入口将公开在多个集群中运行的服务,并从离你所在位置最近的集群提供服务。\n局限性 Shipper 中的主要的局限性有: - Chart 限制:Chart 必须有一个部署对象。 Deployment 的名称必须使用 {{.Release.Name}} 模板化。 Deployment 对象应该有 apiVersion:apps/v1 。 - 基于 Pod 的流量切换:这里没有细粒度的流量路由,例如:发送 1% 的流量到新版本,它基于正在运行的 Pod 数量。 - 如果 Shipper 不工作了,新的 Pod 将获取不到流量。\nIstio Istio 不是一个部署工具,而是一个服务网格。 然而,它很令人感兴趣,因为它已经变得非常流行,并且允许流量管理,例如,将一定比例的流量发送到不同的服务和其他高级网络。\n在 GKE 中,只需在集群配置中选中复选框即可启用 Istio 。 在其它集群中,可以通过 Helm 手动安装。\n有了 Istio ,我们可以创建一个网关,通过 Ingress 网关处理所有外部流量,并创建虚拟服务来管理到我们服务的路由。 为此,只需找到 ingress 网关的 ip 地址并为其配置通配符 DNS 。 然后创建一个网关,通过 Ingress 网关路由所有外部流量。\napiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: public-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - \u0026quot;*\u0026quot;  Isito 不管理应用的生命周期,只管理网络。 我们可以创建一个虚拟服务,为所有进入 ingress 网关的请求 向 pull request 或 master 分支中部署的服务发送 1% 的流量。\napiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: croc-hunter-jenkinsx namespace: jx-production spec: gateways: - public-gateway.istio-system.svc.cluster.local - mesh hosts: - croc-hunter.istio.example.org http: - route: - destination: host: croc-hunter-jenkinsx.jx-production.svc.cluster.local port: number: 80 weight: 99 - destination: host: croc-hunter-jenkinsx.jx-staging.svc.cluster.local port: number: 80 weight: 1  Flagger Flagger 是一个由 Weaveworks 赞助的使用了 Istio 的项目, 该项目使用 Prometheus 的指标进行自动化金丝雀发布和回滚。 它超越了 Isito 提供了基于指标的自动化渐进式发布和回滚。\nFlager 需要将 Istio与 Prometheus、Servicegraph 和某些系统的配置一起安装, 另外还要安装 Flager 控制器本身。 它也提供了一个 Grfana 面板来监控部署进度。\n部署 rollout 通过 Canary 对象定义, 它会生成主要的和金丝雀 Deployment 对象。 编辑 Deployment 时,例如要使用新的镜像版本, Flagger 控制器将负载从 0% 切换到 50% ,每分钟增加 10% ,然后它将切换到新的 deployment 或者如果响应错误和请求持续时间等指标失败则进行回滚。\n比较 此表总结了 Shipper 和 Flagger 在几个渐进式交付特性方面的优势和劣势。\n    Shipper Flagger     流量路由 k8s 原生的按 Pods 的百分比进行均衡 基于 Istio 的高级流量路由(请求的百分比)   部署进度 UI 无 Grafana 面板   支持的 Deployments 具有较强限制的 Helm charts 任何 Deployment   多集群部署 是 否   在不同命名空间(如 jx-staging 和 jx-production )的金丝雀部署或蓝绿部署 否 否,但是要做到它可以手动编辑虚拟服务   在不同集群的金丝雀部署或蓝绿部署 是,但是有点极客,使用一个新应用并将它链接到新区域 也许可以使用 Istio 多集群?   自动部署 否,操作者必须手动完成这些步骤 是,每分钟增加 10% 的流量,可配置的   自动回滚 否,操作者必须发现错误并手动完成这些步骤 是,基于 Prometheus 指标   必需品 无 Istio,Prometheus   告警  Slack    综上所述,我看到了 Shipper 在多集群管理和简单性方面的价值,它不需要 Kubernetes 以外的任何东西,但是它有一些严重的局限性。\nFlager 确实在自动部署和回滚以及对流量进行细粒度控制的过程中付出了额外的努力,它以更高的复杂性成本提供了所需的所有额外服务( Isito、Prometheus )。\n这里可以查看 Shipper、Isito 和 Flager 的示例代码。\n",
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://blog.csanchez.org/2019/01/22/progressive-delivery-in-kubernetes-blue-green-and-canary-deployments/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-23-jenkins-master-shared-home/",
        "title": "关于 Jenkins master 共享 JENKINS_HOME 目录的实验",
        "type": "wechat",
        "date": "2019-04-23 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "你觉得能通过共享 JENKINS_HOME 目录实现 Jenkins master 的高可用吗?",
        "content": "  审校:王冬辉,linuxsuren\n Jenkins master 的高可用是个老大难的问题。和很多人一样,笔者也想过两个 Jenkins master 共享同一个 JENKINS_HOME 的方案。了解 Jenkins 原理的人,都会觉得这个方案不可行。但是真的不可行吗?\n由于工作原因,笔者需要亲自验证以上猜想。\nJENKINS_HOME 介绍 Jenkins 所有状态数据都存放文件系统的目录中,这个目录被称为 JENKINS_HOME 目录。\n实验环境介绍 笔者通过 Docker compose 启动两个独立的 Jenkins master,分别为 jenkins-a 和 jenkins-b。它们共用同一个 JENKINS_HOME 目录。相应的代码仓库的链接放在文章底部。\n将代码克隆到本地后,进入仓库,执行 docker-compose up -d 即可启动实验环境。启动完成,在浏览器中输入 http://localhost:7088 可访问 jenkins-a,jenkins-b 的地址是 http://localhost:7089 。但是你会发现它们启动后的界面显示是不一样的。\njenkins-b 的界面如下图所示:\n而 jenkins-a 的界面如下图所示:\n这时,将 jenkins-a 日志中的解锁密码(Unlock password)输入到 jenkins-b 的页面中,会得到报错信息:\nERROR: The password entered is incorrect, please check the file for the correct password  这时,再次 jenkins-b 日志中的解锁密码(Unlock password)输入到表单中即可进入下一步。接下来就是按照提示一步步完成了。在 jenkins-b 安装步骤的最后一步,我们设置了管理员的用户名密码:admin/admin。然后就算完成任务了。\n然后我们再在 jenkins-a 使用 admin/admin 进行登录,登录是报错的:用户密码不正确。\n接下来,执行 docker-compose restart jenkins-a 命令重启 jenkins-a。再次使用 admin/admin 就可以登录成功了。\n当两个 Jenkins 启动完成后,接下来开始做实验。\n实验1:创建任务 在 jenkins-a 创建任务 x,刷新 jenkins-b 的页面,jenkins-b 上会不会显示出任务 x ?\n结果:jenkins-b 不会出现任务 x。重启 jenkins-b 后,任务 x 出现在任务列表中。\n实验2:任务结果可见性 jenkins-a 上任务执行,jenkins-b 上能否看到任务执行结果?\njenkins-a 执行任务 x,并且执行成功。刷新 jenkins-b 看不到任何执行记录。重启 jenkins-b 后,可看到执行记录。\n实验3:两 master 同时执行同一任务 分别在两个 Jenkins master 上(几乎)开始同一个任务 x。其中一个任务的 build number 会更新,但是另一个不会。\n其中 jenkins-a 任务 x 的 build number 会升到 2,而 jenkins-b 保持的是 1。这时,单独执行 jenkins-b 的任务 x,日志会出现错误:\njenkins-b_1 | WARNING: A new build could not be created in job x jenkins-b_1 | java.lang.IllegalStateException: JENKINS-23152: /var/jenkins_home/jobs/x/builds/2 already existed; will not overwrite with x #2  实验4:编辑任务 jenkins-a 上设置任务 x 定时执行,刷新 jenkins-b 页面,任务 x 中并没有定时执行的设置。重启 jenkins-b 后,任务 x 更新。\n实验5:定时任务的结果是什么? 如果 jenkins-a 和 jenkins-b 两个任务均为定时任务,而且都生效了。它们运行结果是什么的呢?\n看到的现象是,两个任务都会按时执行,但是只有一个任务能将运行结果写入到磁盘中。界面如下图:\n另,从日志中,可以确认 jenkins-a 和 jenkins-b 确实按时执行了。如下图日志中,看出 jenkins-a 定时执行 #6 次构建时报错,因为 jenkins-b 已经执行过 #6 次构建了:\n小结 可以确认的是,当两个 Jenkins 进程共用同一个 JENKINS_HOME 目录时,其中一个 Jenkins 进程更新了 JENKINS_HOME 的内容,另一个是不会实时更新的。所以,同时启动两个 Jenkins master 共用同一个 JENKINS_HOME 的方案是不可行的。我们不能在 jenkins-a 挂了后,直接将流量切到 jenkins-b。因为 jenkins-b 必须重启。\n最后结论:多个 Jenkins master 共享同一个 JENKINS_HOME 的方案是无法使用 Jenkins master 的高可用。\n附录  Jenkins standby 实验环境:https://github.com/zacker330/jenkins-standby-experiment  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-22-jenkins-weekly-2.173/",
        "title": "Jenkins 2.173 发布通知",
        "type": "wechat",
        "date": "2019-04-22 00:00:00 +0000 UTC",
        "tags": ["devops", "ai"],
        "description": "Jenkins 更新通知",
        "content": "本次更新移除了一些不太推荐的功能,请管理员及时关注,如果希望能恢复的旧的形态,可以按照下面的提示操作。\n另外,有一项重要的更新,使得我们可以把所有的中文本地化资源文件从 Jenkins 核心中移除。因此, 请关注 Jenkins 简体中文插件后续的动态,我们会及时完成所有的迁移。\n 移除对 CCtray 文件的内置支持。\n如果要继续使用该功能的话,请安装CCtray XML Plugin (issue 40750) 调整代码在远程计算节点上运行时的流刷新行为,使得具有更好的性能。\n这可能导致插件在节点集群上输出日志,但是没有刷新时,丢失消息。\n使用 -Dhudson.util.StreamTaskListener.AUTO_FLUSH=true 恢复自由风格构建之前的行为。注意,流水线的构建总是需要远程刷新。 (pull 3961) 增加用于将新创建的 API token 拷贝到粘贴板的按钮。 (issue 56733) 使得 Jenkins 经典界面上的表单提交按钮,对 Firefox 的 bug 修复是兼容的。 (issue 53462, Firefox bug 1370630) 如果一个工作空间已经被跨节点重连的流水线正在使用,那么,不会提供给新的构建。 (issue 50504) 从核心中移除 Mailer 相关的本地化字符串。确保你使用 Mailer Plugin 1.23。 (issue 55292) 从 Maven 控制台装饰器中适当地刷新输出。 (issue 56995) 开发者:更新 Stapler 1.256 到 1.257,增加对从任意插件中加载本地化 webapp 资源的支持。\n增加接口 jenkins.PluginLocaleDrivenResourceProvider 使得插件可以参与本地化资源的查找。 (JEP-216, 完整的变更日志) 开发者:SystemProperties 可以在计算节点中使用。 参考 SystemProperties#allowOnAgent。 (pull 3961) 开发者:增加 LineTransformationOutputStream#Delegating 使得更加方便。 (pull 3959) 开发者:hudson.util.ssh.SFTPClient 被移除。\n使用库 Trilead SSH 中的 com.trilead.ssh2.jenkins.SFTPClient 作为代替。 (issue 56166) 内部:更新 commons-beanutils 1.8.3 到 1.9.3。 (pull 3948)  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-19-the-business-value-of-cd/",
        "title": "持续交付的商业价值",
        "type": "wechat",
        "date": "2019-04-19 00:00:00 +0000 UTC",
        "tags": ["cd", "devops", "jenkins"],
        "description": "了解整体的持续交付如何帮助你的组织以更低的风险更快地交付和更新软件",
        "content": "持续交付使你能够以更低地风险、更快低交付新软件或是更新已有软件。\n降低风险很重要,但是,支持持续交付的流程将转化为对业务更重要的价值: - 加速价值时间。 一个小企业不需要一个 MBA 就可以认识到持续交付可以帮助他们完成工作。 一家大型企业已经规划了其价值流, 并且在整个大型组织中拥有复杂的投资和合约, 将发现持续交付有助于加速实现价值的时间。 - 数据驱动决策。 部署、度量和调整。 你仍然可以推动更大规模的发布,但你的流程将更适合于持续的数据收集。 这将缩短与客户的反馈循环。 它提高了你的反应能力,计划你的下一步行动,并保持领先的竞争力。 - 质量。 你持续发布的行为使你必须提高你的质量标准以及完全的自动化测试实践。 更好的质量意味着更快乐的客户、更低的成本、更少的消防演习和更少的计划外工作。 - 试验 = 创新。 开发人员和业务线可以自由地以较低的成本尝试新的想法, 从而释放出长期高投资发布周期背后的创新想法。 - 降低成本。 大的发布会有巨大的成本,如果出现错误会有严重的后果。 保持可交付成果处于可发布状态会降低交付成本。\n对企业来说,这些价值一起使持续交付成为真正的游戏变革者。 尽管可以在团队或项目级别开始采用和验证,但持续交付的本质是它以需要真正投资和自上而下承诺的方式跨越了组织边界。 选择与现有投资互补并共存的持续交付工具链是走向成功的关键一步, 特别是因为 CD 可以引导你的组织采用 DevOps 文化。\n持续交付为创建更好的软件开辟了全新的道路。 CD 是商业层面的热门话题,这有很多的原因: - 早期的采用者已经证明了它的价值。 主流采用者都观察到了它的优势,并感觉到竞争的刺痛,因为他们更灵活的竞争对手超过了他们。 - DevOps 作为一种运动获得了关注。 业务人员理解,在开发和运营之间有一个共同的理解,打破孤立的行为,并在整个组织内发展一种责任文化,是提高效率和上市时间的关键步骤。 在许多方面,持续交付等同于 DevOps 。 - 随着软件“吞噬世界”,商业领袖们越来越清楚 IT 必须被用作战略资产。 在正确处理安全性、可用性和合规性的同时,能够缩短交付时间、提高质量并快速适应变化是一项挑战。 持续交付,强调自动化和尽早的、直接的反馈,是实现这些目标的方法。 - 当你通过持续交付实现廉价的、低风险的试验时,你可以用更多的信息指导业务投资,并发现你可能完全错过的机会。\n持续交付正在改变企业使用其 IT 资产与客户和合作伙伴联系的方式。 CD 建立在多年来之不易的敏捷过程和持续集成经验的基础上, 将这些好处提升到业务级别,而不是简单地成为开发团队使用的技术, 并最终导致 DevOps 。 随着开发和运营人员学习如何协作和分担责任时,许多成功的关键都植根于组织和文化的变革。 无论是在组织范围内还是在本地,实现这种变革的技术工具链可能包括 Jenkins 。 CloudBees Jenkins 企业版,通过扩展开源 Jenkins 的使用范围, 提供了一个支持 Jenkins 混合模型(本地部署、云上部署或混合部署)的平台, 是组织在今天转向持续交付和在不久的将来实施 DevOps 的必要工具。\n更多内容请参见白皮书:持续交付的商业价值\n",
        "auhtor": "Brian Dawson",
        "translator": "donhui",
        "original": "https://dzone.com/articles/the-business-value-of-cd",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-17-aiops/",
        "title": "AIOps:DevOps 的未来",
        "type": "wechat",
        "date": "2019-04-17 00:00:00 +0000 UTC",
        "tags": ["devops", "ai"],
        "description": "DevOps 将结合人工智能变得更加强大",
        "content": " DevOps 和云技术正在逼近极限 范式转变往往会产生意想不到的后果,这些后果可能需要数年才能被完全消化。 云计算就是一个很好的例子。 云计算迎来了灵活的基础设施和低资本要求的时代,由于资源只是一个API调用,工程师们无需等待部署。 然而,这一切只是开始。\n敏捷的公司利用云来打破开发和运维之间的隔阂,并采用敏捷方法以缩短开发周期,从而创造战略优势。 他们将应用程序生命周期中的工程师团队分工从之前的开发和测试变为部署和运维, 并创建了需要一系列新技能的职位。这些公司使用 CI/CD 和 DevOps 进一步推动自动化流水线, 以实现更快的交付。\n这样有隐患吗?去问你的 DevOps 团队 DevOps 团队的任务是维护一个工具链,以便自动交付新代码,按需扩展,以及五个 9 的正常运行时间。 在空闲时间,他们致力于提高性能和控制成本。 对于大的应用程序,可以有数千个虚拟机或容器,每个虚拟机或容器都有一堆软件, 还有负载平衡器和自动扩容等云服务,所有这些都必须进行配置和维护。 这一切都在不断发展中。\n我之前了解过的一个大型独角兽公司拥有数百名开发人员,每天更新代码超过 100 次, 云上有超过 4000 台虚拟机,每月收集数 PB 的数据。 而他们的 DevOps 团队只有十几个人手,直到去年才有 VP。 对他们来说,这是一个艰巨且繁重的任务。\n应付这无数的挑战已经超出了人类的能力范围。\n幸好,AIOps 正在成为一种解决方案。\nAIOps 一词是由 Gartner 创造的, 他将其解释为:\nAIOps 结合了大数据,机器学习和可视化技术,通过更强的洞察力来优化 IT 运维。 IT 的领导者应该开始部署 AIOps,以优化当前的性能分析,\n并在未来两到五年内将使用范围扩展到 IT 服务管理和自动化。 虽然 Gartner 创造了这个术语,但以我拙见,这还没达到标准。 他的定义以循环中的人为中心,以他的描述 AIOps 基本上是一种高级的大数据分析。 要解决 DevOps 困境,我们要定一个更高的目标。\n那么,AIOps 应该是什么? 我们先从它不应该是什么开始:一个对现有的运维系统的修饰,软件供应商将\u0026rdquo;以 AI 驱动\u0026rdquo;作为卖点。 这种情况已经发生了,当新的技术威胁到现有利益时,往往会发生这种情况。 仅仅向已有工具添加一个 API 是不够的,如果决策需要人为干预,那就不能算是 AIOps。\n这是一些 AIOps 的关键要求: - AIOps 系统从你的数据中学习并适应应用程序的工作模式 + 这意味着它不会每次都做同样的事情 - AIOps 系统无需人工干预即可制定和实施决策 + 你可以让人参与循环,直到你完全信任这个系统 - AIOps 系统能持续运行 + 它能成为你的交付中的标准单元\n向 AIOps 的过渡正处于起步阶段,但它的热度正在上升,而且已经有了成功案例。 风险投资正在下注,大小软件供应商都正在为市场带来新的解决方案。 从几年前的日志分析系统开始,自动化根本原因分析再到故障预测的出现。 入侵检测系统现在可以从异常流量中学习,有些甚至可以跨公司。 最近,预测自动扩容系统首次亮相。 Optune 和 Opsani 的 AI 系统能够判断虚拟机类型、实例和应用程序参数, 并使用客户现有的 DevOps 工具链和监控系统将它们部署到测试或生产环境中。\nDevOps 正在取代传统的 IT 部门,它的名称被改变,角色职能也发生了变化, 但 IT 部门要解决的挑战并没有消失,它们的规模被乘以了微服务架构的固有规模。 因此,我们需要为这些挑战设计新的系统,AIOps 必须在未来几年内发展, 超越 Gartner 的愿景,使 DevOps 能够应对发展的规模和速度。\n",
        "auhtor": "Bert Armijo",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/aiops-the-future-of-devops-is-here",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-zabbix-monitor-jenkins/",
        "title": "使用 Zabbix 监控 Jenkins",
        "type": "wechat",
        "date": "2019-04-15 00:00:00 +0000 UTC",
        "tags": ["jenkins", "zabbix"],
        "description": "介绍了如何使用 Zabbix 监控 Jenkins",
        "content": "  本文假设读者已经了解 Jenkins 基本概念及插件安装,Zabbix 基础概念。基于 Zabbix 3.4,Jenkins 2.8 做实验\n 笔者最近的工作涉及到使用 Zabbix 监控 Jenkins。在谷歌上搜索到的文章非常少,能操作的就更少了。所以决定写一篇文章介绍如何使用 Zabbix 监控 Jenkins。\n下图为整体架构图:\n整体并不复杂,大体步骤如下:\n 在 Jenkins 上安装 Metrics 插件,使 Jenkins 暴露 metrics api。 配置 Zabbix server 及 agent 以实现监控及告警  为方便读者实验,笔者将自己做实验的代码上传到了 GitHub,链接在文章末尾。使用的是 Docker Compose 技术(方便一次性启动所有的系统)。\n接下来,我们详细介绍 Metrics插件及如何实现 Zabbix 监控 Jenkins。\n1. 使 Jenkins 暴露 metrics api 安装 Metrics 插件,在系统配置中,会多出“Metrics”的配置,如下图: 配置项不复杂。我们需要点击“Generate\u0026hellip;”生成一个 Access Key(生成后,记得要保存)。这个 Key 用于身份校验,后面我们会用到。\n保存后,我们在浏览器中输入URL:http://localhost:8080/metrics/\u0026lt;刚生成的 Access Key\u0026gt; 验证 Jenkins 是否已经暴露 metrics。如果看到如下图,就说明可以进行下一步了。\n1.1 Metrics 插件介绍 Metrics 插件是基于 dropwizard/metrics 实现。它通过4个接口暴露指标数据:/metrics,/ping,/threads,/healthcheck。\n1.2 Metrics 插件:/metrics 接口介绍 点击上图中的metric链接(http://localhost:8080/metrics/\u0026lt;Access Key\u0026gt;/metrics),它暴露了以下指标数据:\n{ version: \u0026quot;3.0.0\u0026quot;, gauges: {...}, counters: {...}, histograms: {...}, meters: {...}, timers: {...} }  从数据结构中可以看出它将指标分成 5 种数据类型: * Gauges:某项指标的瞬时值,例如:当前 Jenkins executor 的总个数(jenkins.executor.count.value) * Counters:某项指标的总数值,例如:http 请求活动连接数(http.activeRequests) * Meters:一段时间内,某事件的发生概率,例如:Jenkins成功执行的任务每分钟的执行次数(jenkins.runs.success.m1_rate) * Histogram:统计指标的分布情况。例如:Jenkins executor 数量的分布(jenkins.executor.count.history) * Timer:某项指标的持续时间。例如:Jenkins 任务等待时间(jenkins.job.waiting.duration)\n由于指标非常之多,我们就不分别介绍了。具体有哪些指标,读者朋友可以从代码仓库中的 metrics.json 文件了解。\n1.2 Metrics 插件其它接口介绍  /ping:接口返回 pong 代表 Jenkins 存活,如下图:  /threads:返回 Jenkins 的线程信息 /healthcheck:返回以下指标:  { disk-space: { healthy: true }, plugins: { healthy: true, message: \u0026quot;No failed plugins\u0026quot; }, temporary-space: { healthy: true }, thread-deadlock: { healthy: true } }  2. 配置 Zabbix server 与 agent 实现监控及告警 Zabbix server 通过与 Zabbix agent 进行通信实现数据的采集。而 Zabbix agent 又分为被动和主动两种模式。我们使用的是被动模式,也就是Zabbix server 向 agent 索要数据。\n所以,我们需要在 Zabbix agent 所在机器放一个获取 Jenkins 指标数据的脚本。再配置 Zabbix server 定时从该 agent 获取数据,最后配置触发器(trigger)实现告警。\n接下来的关于 Zabbix 的配置,基于我的 jenkins-zabbix 实验环境,读者朋友需要根据自己的实际情况变更。\n2.1 配置 Zabbix server 如何从 agent 获取指标数据 首先,我们需要告诉 Zabbix server 要与哪些 Zabbix agent 通信。所以,第一步是创建主机,如下图: 第二步,在主机列表中点击“Iterms”进行该主机的监控项设置: 第三步,进入创建监控项页面: 第四步,创建监控项: 这里需要解释其中几个选项为什么要那样填: * Type:是 Zabbix server 采集指标的类型,我们选择的是 Zabbix agent,如上文所说。 * Key:由于我们要监控的指标并不是 Zabbix 预定义的。所以,需要使用用户自定义参数来实现监控 Jenkins 指标。Key 填的值为:jenkins.metrics[gauges.jenkins.node.count.value.value]。jenkins.metrics是需要执行的真正的 Key 名称。而 [] 内是传给该 Key 对应的命令的参数。对于初学者,Zabbix 这部分概念非常不好理解。也许这样会更好理解:在使用用户自定义参数来实现监控的情况下,Zabbix server 会将这个 Key 发送给 agent,然后 agent 根据这个 Key 执行指定的 逻辑 以获取指标数据。这个 逻辑 通常是一段脚本(shell命令或Python脚本等)。而脚本也是可以传参的,[]中的值就是传给脚本的参数。具体更多细节,下文会继续介绍。 * Type of information:监控数据的数据类型,由于我们监控的是 Jenkins node 节点的个数,所以,使用数字整型。 * Update interval:指 Zabbix server 多长时间向 agent 获取一次数据,为方便实验,我们设置为 2s。\n到此,Zabbix server 端已经配置完成。\n2.2 配置 Zabbix agent 使其有能力从 Jenkins 获取指标数据 当 Zabbix agent 接收到 server 端的请求,如 jenkins.metrics[gauges.jenkins.node.count.value.value]。Zabbix agent 会读取自己的配置(agent 启动时会配置),配置内容如下:\n## Zabbix Agent Configuration File for Jenkins Master UserParameter=jenkins.metrics[*], python /usr/lib/zabbix/externalscripts/jenkins.metrics.py $1  根据 Key 名称(jenkins.metrics)找到相应的命令,即:python /usr/lib/zabbix/externalscripts/jenkins.metrics.py $1。并执行它,同时将参数 gauges.jenkins.node.count.value.value 传入到脚本 jenkins.metrics.py 中。jenkins.metrics.py 需要我们在 Jenkins agent 启动前放到 /usr/lib/zabbix/externalscripts/ 目录下。\njenkins.metrics.py 的源码在 jenkins-zabbix 实验环境中可以找到,篇幅有限,这里就简单介绍一下其中的逻辑。\njenkins.metrics.py 所做的事情,无非就是从 Jenkins master 的 metrics api 获取指标数据。但是由于 api 返回的是 JSON 结构,并不是 Zabbix server 所需要的格式。所以,jenkins.metrics.py 还做了一件事情,就是将 JSON 数据进行扁平化,比如原来的数据为:{\u0026quot;gauges\u0026quot;:{\u0026quot;jenkins.node.count.value\u0026quot;: { \u0026quot;value\u0026quot;: 1 }}} 扁平化后变成: gauges.jenkins.node.count.value.value=1。\n如果 jenkins.metrics.py 脚本没有接收参数的执行,它将一次性返回所有的指标如:\n...... histograms.vm.memory.pools.Metaspace.used.window.15m.stddev=0.0 histograms.vm.file.descriptor.ratio.x100.window.5m.p75=0.0 histograms.vm.memory.pools.PS-Old-Gen.used.window.5m.count=4165 gauges.vm.runnable.count.value=10 timers.jenkins.task.waiting.duration.mean=0.0 histograms.vm.memory.non-heap.committed.history.p99=123797504.0 gauges.vm.memory.pools.PS-Eden-Space.used.value=19010928 gauges.jenkins.node.count.value.value=1 histograms.vm.memory.pools.Code-Cache.used.window.15m.mean=44375961.6 ......  但是,如果接收到具体参数,如 gauges.jenkins.node.count.value.value ,脚本只返回该参数的值。本例中,它将只返回 1。\njenkins.metrics.py 脚本之所以对 JSON 数据进行扁平化,是因为 Zabbix server 一次只拿一个指标的值(这点需要向熟悉 Zabbix 的人求证,笔者从文档中没有找到明确的说明)。\n注意:在 2.1 节中,如果 Key 值设置为:jenkins.metrics,Zabbix server 不会拿 jenkins.metrics.py 返回的所有的指标值自动创建对应的监控项。所以,Key 值必须设置为类似于 jenkins.metrics[gauges.jenkins.node.count.value.value] 这样的值。\n3. 配置 Zabbix server 监控指标,并告警 在经过 2.2 节的配置后,如果 Zabbix server 采集到数据,可通过_Monitoring -\u0026gt; Latest data -\u0026gt; Graph_菜单(如下图),看到图形化的报表:\n图形化的报表: 有了指标数据就可以根据它进行告警了。告警在 Zabbix 中称为触发器(trigger)。如下图,我们创建了一个当 Jenkins node 小于 2 时,就触发告警的触发器:\n至于最终触发器的后续行为是发邮件,还是发短信,属于细节部分,读者朋友可根据自己的情况进行设置。\n小结 在理解了 Zabbix server 与 agent 之间的通信原理的前提下,使用 Zabbix 监控 Jenkins 是不难的。笔者认为难点在于自动化整个过程。上文中,我们创建主机和添加监控项的过程,是手工操作的。虽然 Zabbix 能通过自动发现主机,自动关联模板来自动化上述过程,但是创建”自动化发现主机“和”自动关联动作“依然是手工操作。这不符合”自动化一切“的”追求“。\n最后,如果读者朋友不是历史包袱原因而选择 Zabbix,笔者在这里推荐 Prometheus,一款《Google 运维解密》推荐的开源监控系统。\n附录  Metrics 插件:https://wiki.jenkins.io/display/JENKINS/Metrics+Plugin dropwizard/metrics:https://metrics.dropwizard.io/4.0.0/ Zabbix 监控项类型:https://www.zabbix.com/documentation/3.4/zh/manual/config/items/itemtypes metrics.json: https://github.com/zacker330/jenkins-zabbix/blob/master/metrics.json jenkins-zabbix 实验环境:https://github.com/zacker330/jenkins-zabbix Prometheus:https://prometheus.io/  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/about/social-media/",
        "title": "社交媒体",
        "type": "about",
        "date": "2019-04-12 14:26:05 +0800 +0800",
        "tags": [],
        "description": "Jenkins 中文社区的社交媒体",
1517
        "content": "社区所有的技术、活动类的文章都会同步发布到下面的社交媒体平台上。\n   媒体 方式 负责人     微信公众号 人工  LinuxSuRen    开源中国 人工  donhui    知乎 人工  LinuxSuRen    思否 SegmentFault 人工  LinuxSuRen    CSDN 人工  P01son6415    简书 人工  yJunS    掘金 人工  zacker330    腾讯 云+社区 自动同步  LinuxSuRen    企鹅号 自动同步  LinuxSuRen    百家号 自动同步  LinuxSuRen     ",
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-12-brief-analysis-the-encryption-algorithm-of-the-built-in-jenkins-user-database/",
        "title": "简析 Jenkins 专有用户数据库加密算法",
        "type": "wechat",
        "date": "2019-04-12 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "本文对 Jenkins 专有用户数据库加密算法进行简要分析",
        "content": " 认识Jenkins专有用户数据库 Jenkins 访问控制分为:安全域(即认证)与授权策略。\n其中,安全域可以采用三种形式,分别为:Jenkins 专有用户数据库、LDAP、Servlet 容器代理。 在哪里看到加密后的用户密码信息? Jenkins 专有用户的数据信息存放位置:$JENKINS_HOME/users/\n每个用户的相关信息存放在各自的 config.xml 文件中: $JENKINS_HOME/users/$user/config.xml\n在 config.xml 文件中的 passwordHash 节点可以看到用户密码加密后的密文哈希值: 用户密码是用什么算法加密的呢? 那么问题来了,用户密码是用何种加密方式加密的呢?可否通过解密密文得到明文呢?\n在 GitHub 上查看其源码,通过关键字 #jbcrypt 搜索定位到 HudsonPrivateSecurityRealm.java 这个文件。 HudsonPrivateSecurityRealm.java 具体路径是:jenkins/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java\n源码片段如下:\n/** * {@link PasswordEncoder} that uses jBCrypt. */ private static final PasswordEncoder JBCRYPT_ENCODER = new PasswordEncoder() { public String encodePassword(String rawPass, Object _) throws DataAccessException { return BCrypt.hashpw(rawPass,BCrypt.gensalt()); } public boolean isPasswordValid(String encPass, String rawPass, Object _) throws DataAccessException { return BCrypt.checkpw(rawPass,encPass); } }; /** * Combines {@link #JBCRYPT_ENCODER} and {@link #CLASSIC} into one so that we can continue * to accept {@link #CLASSIC} format but new encoding will always done via {@link #JBCRYPT_ENCODER}. */ public static final PasswordEncoder PASSWORD_ENCODER = new PasswordEncoder() { /* CLASSIC encoder outputs \u0026quot;salt:hash\u0026quot; where salt is [a-z]+, so we use unique prefix '#jbcyrpt\u0026quot; to designate JBCRYPT-format hash. '#' is neither in base64 nor hex, which makes it a good choice. */ public String encodePassword(String rawPass, Object salt) throws DataAccessException { return JBCRYPT_HEADER+JBCRYPT_ENCODER.encodePassword(rawPass,salt); } public boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException { if (encPass.startsWith(JBCRYPT_HEADER)) return JBCRYPT_ENCODER.isPasswordValid(encPass.substring(JBCRYPT_HEADER.length()),rawPass,salt); else return CLASSIC.isPasswordValid(encPass,rawPass,salt); } private static final String JBCRYPT_HEADER = \u0026quot;#jbcrypt:\u0026quot;; };  通过分析该源码得知: 1. 明文通过 jbcrypt 算法得到密文 encPass 2. 密文的格式为:salt: encPass,其中以 #jbcrypt 表示 salt 作为数据头\njbcrypt 是什么? jbcrypt 是 bcrypt 加密工具的 java 实现。 它的 API 非常简单,DEMO 如下,在 HudsonPrivateSecurityRealm.java 中可以看到加密和校验时使用了如下 API:\n// Hash a password for the first time String hashed = BCrypt.hashpw(password, BCrypt.gensalt()); // gensalt's log_rounds parameter determines the complexity the work factor is 2**log_rounds, and the default is 10 String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12)); // Check that an unencrypted password matches one that has previously been hashed if (BCrypt.checkpw(candidate, hashed)) System.out.println(\u0026quot;It matches\u0026quot;); else System.out.println(\u0026quot;It does not match\u0026quot;);  经验证,用 jbcrypt 对同一个明文加密后因为 salt 一般不同,加密后的密文一般不同。\nbcrypt 精要概况  bcrypt 是不可逆的加密算法,无法通过解密密文得到明文。 bcrypt 和其他对称或非对称加密方式不同的是,不是直接解密得到明文,也不是二次加密比较密文,而是把明文和存储的密文一块运算得到另一个密文,如果这两个密文相同则验证成功。  总结 综上, Jenkins 专有用户数据库使用了 jbcrypt 加密, jbcrypt 加密是不可逆的,而且对于同一个明文的加密结果一般不同。\n",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-10-getting-started-with-docker-for-java-applications/",
        "title": "Java 应用使用 Docker 的入门指南:建立一个 CI/CD 流水线",
        "type": "wechat",
        "date": "2019-04-10 00:00:00 +0000 UTC",
        "tags": ["cd", "ci", "docker", "jenkins", "pipeline"],
        "description": "本文是容器化现有 Java 应用以及使用 Jenkins 建立一个端到端部署流水线的指南",
        "content": " Docker 已经非常出名并且更多的组织正在转向基于 Docker 的应用开发和部署。这里有一个关于如何容器化现有 Java Web 应用以及使用 Jenkins 为它建立一个端到端部署流水线的快速指南。\n为此我使用了非常著名的基于 Spring 的宠物商店应用,它代表了一个很好的示例,因为大多数应用都遵循类似的体系结构。\n步骤  构建宠物商店应用。 运行一次 Sonar 质量检查。 使用该 Web 应用准备 Docker 镜像。 运行容器以及执行集成测试。 如果所有测试成功,推送该镜像到一个 dockerhub 账户。  所有的代码都在这里。\n这里是可用于以上步骤的 Jenkins 流水线代码:\nnode { stage 'checkout' git 'https://gitlab.com/RavisankarCts/hello-world.git' stage 'build' sh 'mvn clean install' stage('Results - 1') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'bake image' docker.withRegistry('https://registry.hub.docker.com','docker-hub-credentials') { def image = docker.build(\u0026quot;ravisankar/ravisankardevops:${env.BUILD_TAG}\u0026quot;,'.') stage 'test image' image.withRun('-p 8888:8888') {springboot -\u0026gt; sh 'while ! httping -qc1 http://localhost:8888/info; do sleep 1; done' git 'https://github.com/RavisankarCts/petclinicacceptance.git' sh 'mvn clean verify' } stage('Results') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'push image' image.push() } }  最初的步骤只是检出代码并运行构建。有趣的部分从这个步骤开始,它使用 dockerhub 凭证在 Docker 上下文中运行。\nstep 3 'bake image' docker.withRegistry('https://registry.hub.docker.com','docker-hub-credentials')  这个步骤构建 Docker 镜像。Docker build 命令将 dockerhub 仓库名称和 tag 名称作为一个参数,而构建位置作为另一个参数。\ndef image = docker.build(\u0026quot;dockerhub registry name\u0026quot;:\u0026quot;tag name\u0026quot;,'location of docker file') def image = docker.build(\u0026quot;ravisankar/ravisankardevops:${env.BUILD_TAG}\u0026quot;,'.')  这里使用 Dockerfile 来构建 Docker 镜像。 Dockerfile 的内容如下:\nFROM tomcat:8 ADD target/*.war /usr/local/tomcat/webapps  下一步是运行镜像并执行测试:\nstage 'test image' image.withRun('-p 8888:8888') { springboot -\u0026gt; sh 'while ! httping -qc1 http://localhost:8888/info; do sleep 1; done' git 'https://github.com/RavisankarCts/petclinicacceptance.git' sh 'mvn clean verify' }  withRun 步骤用来帮你运行你刚才构建的 Docker 镜像并暴露应用可以暴露的端口。我有另一个测试代码库,它被构建和执行,将对正在运行的镜像运行测试。\n最后一步是推送该镜像到一个 dockerhub registry 或者你的组织建立的任何内部 registry 。\nstage('Results') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'push image' image.push()  ",
        "auhtor": "Ravi Sankar",
        "translator": "donhui",
        "original": "https://dzone.com/articles/getting-started-with-docker-for-java-applications",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-08-becoming-contributor-intro/",
        "title": "介绍:成为一名 Jenkins 贡献者的旅程",
        "type": "wechat",
        "date": "2019-04-08 00:00:00 +0000 UTC",
        "tags": ["jenkins", "community", "developer", "contributing", "newcomer"],
        "description": "如何从零开始成为开源社区贡献者",
        "content": " 作为一名软件工程师,这些年来在我工作过的不同公司里用到过许多开源软件(包括框架、库、工具等)。 然而,在此之前我从没有以一名贡献者的身份参与过开源项目。\n自从我向 Jenkins 提交第一个简单又滑稽的 commit 已经过去六个月(2018 年 9 月)了, 我也尝试过作出更多贡献。然而总的来说,向开源项目贡献代码是具有挑战的, 特别是像 Jenkins 这样有着很长生命周期的项目,项目中不乏遗留代码和系统知识。 它通常难以入手,也很难想到一个计划来持续贡献使你的付出从长远看来是有意义的。\n对于 Jenkins 社区来说,我在尝试加入社区时所遇到的困难是其它人也有可能会面临的, 因此我决定分享我成为 Jenkins 活跃贡献者的心路历程。\n我计划大概每月发布一篇博文来描述我的这段旅程,我将从简单容易入手的项目开始, 随着时间推移再介绍更加复杂的项目。\n从哪开始 jenkins.io 要成为 Jenkins 的贡献者,首先会看到的就是 jenkins.io, 在顶部导航中\u0026rdquo;社区\u0026rdquo;下拉列表里第一个\u0026rdquo;参与\u0026rdquo;的链接就能将我们带到\u0026rdquo;参与和贡献\u0026rdquo;这个页面。\n在这个页面中列举了我们能够参与 Jenkins 项目和社区的许多方式。尽管它展示了所有可能的选项供读者选择,但一下子看上去令人有些无所适从。\n这个页面被分成了左右两个部分,左边提供了参与社区的方法,右边是向社区贡献的方法。\n参与社区的建议 在“参与和贡献”页面的左侧是有关参与社区的建议,其中包括结交他人、审阅修改或者提供反馈信息。\n这里面最让我困惑的是沟通渠道,里面列出的沟通渠道有 几个邮件列表 还有 IRC 和 Gitter 频道。\n当我第一次尝试参与时,我订阅了许多邮件列表和几个 IRC 和 Gitter 频道,但我很快发现里面有重要的讨论正在进行, 并且活跃的讨论中多数是关于特定的用户或开发者的问题。因此,我不建议你一开始在这上面花太多时间, 除非你是要为其他用户提供帮助(当你是经验丰富的 Jenkins 用户时可能会有这种情况)或者你已经有一个明确的问题需要提问。\n看一看社区成员如何互相帮助是好事,但是对新人来说它的信息量过于庞大。如果你的兴趣在于向 Jenkins 项目作贡献(不管是翻译、文档还是代码), 这些对话不会对你有太大的帮助。\n向社区贡献的建议 在“参与和贡献”页面的右侧有一些关于如何贡献的建议,主要分为:编写代码,翻译,文档和测试。\n在之后的博客中,我将介绍所有的这些贡献类型,以及如何参与的建议包括如何审阅 Pull Requests(PRs)或提供反馈 (反馈问题或者复现其它用户反映过的问题,提供额外信息来帮助维护者复现和修复它们。)\n开源之旅的第一次贡献 当看到「参与和贡献」页面时,我发现我可以帮助改进这个页面的一些内容。本来我打算选择其中一个作为这篇文章的第一个例子,但当我阅读贡献指南时, 我发现了一个更简单的贡献。我认为它可以更好的说明开始贡献社区是多么的简单,于是我决定就用它来当例子。\n网站代码仓库 在「文档」菜单中有一个链接 jenkins.io 的贡献指南, 这个 CONTRIBUTING 文件是大多数开源项目代码仓库的根目录中都会有的常见文件。\n点击链接跳转到 jenkins.io 代码仓库,这个仓库包含了网站的源代码其中也包括这篇文章。 事实上,我首先查看的是贡献指南,以便了解如何为网站做出贡献的相关信息。\n找到一个失效链接 通过阅读贡献指南,我了解了 Awestruct 静态站点生成器,它是用于将代码仓库中的 AsciiDoc 源文件转换为网页的工具。 然而,当我点击链接想查看更多信息时,我发现这个链接失效了——域名已经过期。\n为何不修复它? 这是一个好机会,我用它来向新人展示开始贡献是多么容易。\n创建代码仓库分支 第一步,通常是 fork 代码仓库,并克隆到本地。\n进行修改 下一步就是对相应文件进行修改。我创建了一个新的分支 “alternative-awestruct-link” 并对它作了如下修改:\n确保构建正确并且通过测试 尽管在这次的情况下,我的贡献并不针对网站的实际页面,而是对贡献指南(因此不太可能造成什么破坏),但是最好习惯每个贡献都遵循规范流程, 这样才能确保之后有所改变时构建也能够正常进行。\n如贡献指南所述,要构建此项目,我们只需在代码仓库的根目录中以默认的 “make” 作为 target 来运行构建命令。\n一旦命令执行完成,如果没有出现报错,我们就可以进行下一步:创建 Pull Request\n创建 PR 把我的改动 commit 并 push 到远程库以后,我就需要创建一个 PR 了。 有一个简单的方法,只需单击推送完成后在 git 日志中显示的链接,如果愿意的话也可以通过 GitHub UI 创建 PR; 或者甚至可以使用 GitHub CLI 的 “hub” 来完成它。\n这次我直接点击了链接,它将我跳转到 Github 的创建 PR 页面,我在这个页面上添加描述并创建了 PR。\n当创建这个代码仓库的 PR 后,可以发现有一些检查开始运行。Jenkins 代码仓库配置了 “Jenkins on Jenkins”, 它会为每个代码仓库运行 Jenkinsfile 中描述的相应 CI 流水线。\n检查结束后,可以在 PR 中看到结果:\n如果想看到执行的细节,可以点击 “Show all checks” 链接:\nPR review 现在我们已经创建好了 PR 并通过了自动测试,只需要等待代码 review 了。\n一旦 PR 被审核通过然后被 merge,你的贡献就会被整合到代码仓库的主分支并成为下次版本更新的一部分。\n我已经作出了贡献! 我做的这个贡献是微不足道的,它的复杂性很小,如果你的目标在于为 Jenkins 项目本身贡献代码,它可能看起来不是很有趣。\n然而对于我作为一名贡献者,这是一个熟悉代码库、贡献指南、jenkins.io 网站背后的技术的很好的方式; 并且最重要的是,我开始“放下恐惧”,为 Jenkins 这样的开源项目做出了贡献。\n因此,如果你同我一样,请不要犹豫。来吧,找到你自己的第一个贡献。每一个细节都很重要!\n",
        "auhtor": "romenrg",
        "translator": "P01son6415",
        "original": "https://jenkins.io/blog/2019/03/29/becoming-contributor-intro/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-03-the-benefits-and-challenges-of-continuous-integration/",
        "title": "持续集成的收益与挑战",
        "type": "wechat",
        "date": "2019-04-03 00:00:00 +0000 UTC",
        "tags": ["continuous integration", "ci"],
        "description": "本文介绍了持续集成的定义,并解释了实施CI的各种收益与挑战",
        "content": " 毫无疑问,持续集成( CI )已成为一个软件开发的主流原则。CI 的收益在业界众所周知的,并且很难找到反对实施它的人。\n在这里,我想把那些收益收集起来放到一个中心化的地方。但是我认为扮演反面角色并试图找出持续集成的弊端或挑战也是很有趣的。\n什么是持续集成? 从根本上说, 持续集成( CI )是一种开发实践,开发人员每天都要将代码集成到共享的仓库中。在该仓库中,代码被自动构建进行验证用来在这个流程中检验尽早的发现任何问题。这允许团队花更少的时间回溯,而花更多的时间构建新特性。\n持续集成的收益 1、缓解风险 据 Martin Fowler 说,持续集成的最大收益是减轻风险。由于延迟了代码集成,团队将不断增加合并冲突的数量和严重性。当团队频繁集成(使用自动构建),他们减轻了潜在风险的数量,因为他们总是知道系统的当前状态。\n2、质量保证 实施持续集成的团队对他们的操作更有信心。他们知道自动构建会立即捕获缺陷,这使他们能够保证质量。 他们也不会猜测系统中 bug 的数量,这允许他们能够向队友提供准确的数量,并为客户提供更好的服务。\n3、提高可见性和加强团队合作 自动构建为团队提供了对其系统的完全可见性。他们知道问题的数量,并能快速的解决问题。提高可见性可以让团队有机会在小问题变成大之前通过协作解决。\n持续集成的挑战 1、组织文化变革 一些企业更喜欢传统的方法,并且可能很难实施持续集成。 他们必须对员工进行再培训,这就意味着要对现有的业务进行大修。管理者可能会抵制因为持续集成并不能帮助他们实现公司的直接目标(例如:金钱在质量之上)。\n2、难以维护 构建一个自动化的代码仓库不是一个简单的任务。 团队必须构建适当的测试套件,并花时间编写测试用例,而不是开发代码。 起初,这可能会让他们放慢速度,让他们对按时完成自己的项目失去信心。如果测试套件不稳定,它可能在某些天内完美地工作,但其他天可能不起作用。 然后团队将不得不花费更多的时间来弄清楚发生了什么。\n3、大量的错误信息 对于较大的开发团队,他们可能每天都会看到 CI 错误消息,并开始忽略它们,因为它们还有其他任务和关注点。 他们可能会开始将一个破坏的构建视为一个正常的事情,并且缺陷可能开始堆积在一起。\n",
        "auhtor": "Jeffrey Lee",
        "translator": "donhui",
        "original": "https://dzone.com/articles/the-benefits-and-the-drawbacks-of-continuous-integ",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-18-weekly-version/",
        "title": "Jenkins 更新通知",
        "type": "wechat",
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": ["weekly"],
        "description": "Jenkins LTS、Weekly 以及简体中文插件更新",
        "content": " Jenkins LTS 2.164.1 更新内容如下:  Java 11 现已全面支持。 自 2.150.x 开始在 Java 11 上运行 Jenkins 的多项改进,包括:支持插件在它们的元数据中申明最小 Java 版本,并拒绝加载不兼容的插件,以及当运行在 Java11 上时安装新的 JAXB 插件后允许使用 JAXB 的 API. (博客发布的申明, 运行在 Java 11, 升级到 Java 11, issue 52012, issue 52282, issue 55076, issue 55048, issue 55980, issue 55681, issue 52285) 当列出一个指定目录时 list-jobs 不再进行递归。 (issue 48220) 增加一个新的 CLI 命令 disable-plugin 来禁用一个或多个已安装的插件,并可以选择同时重启 Jenkins. (issue 27177) 更新 Trilead SSH 库以支持 OpenSSH 使用 AES256-CTR 加密。 (issue 47603, issue 47458, issue 55133, issue 53653) 在 Jenkins CLI 中增加对 ed25519 关键算法的支持。 (issue 45318) 减少以 ZIP 格式下载归档或者工作空间文件时 SECURITY-904 对性能的影响。 (issue 55050) 在插件向导中增加语言分类,并会根据浏览器的语言设置自动安装本地化插件。 (pull 3626) Windows Service Wrapper 从 2.1.2 更新到 2.2.0,Windows Agent Installer 从 1.9.3 更新到 1.10.0,支持禁用、重命名以及归档服务日志。 (pull 3854, Windows Service Wrapper 变更日志, Windows Agent Installer Module 变更日志) SSHD 模块从 2.5 更新到 2.6,当自定义值设置为 org.jenkinsci.main.modules.sshd.SSHD.idle-timeout system property 时,设定一个合适的 Apache Mina 空闲超时时间。 (issue 55978, 全部变更日志) 开发者: 登陆和注册页面在 2.129 中重新设计了,现在可以从多个插件中接收风格贡献 (SimplePageDecorator 的视图页面 footer) (issue 54325)  Jenkins 每周版 2.168 更新内容如下:  优化移动端的登陆、加载和重启界面。 通知管理员关于潜在的不安全的权限设置,导致以虚拟系统用户运行构建。 在 Microsoft Docker 中的 Windows Server 2016 上工作空间和归档文件的浏览不可用。(在 2.154 中引入) 开发者: StringParameterValue.getValue() 现在返回 String 以避免不必要的类型转换。  简体中文插件 0.0.14 新增了多条中文词条,更多细节从查看变更日志。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-20-cdf-launch/",
        "title": "Jenkins 正在加入持续交付基金会",
        "type": "wechat",
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": ["cdf", "general", "community"],
        "description": "Jenkins 社区牵头成立 CDF",
        "content": "今天Linux 基金会与 CloudBees、Google 和一些其他公司启动了一个新的开源软件基金会,也就是持续交付基金会(CDF). CDF 相信持续交付的力量,它旨在培养与支持开源生态,以及厂商中立的项目。\nJenkins 的贡献者们已经决定,我们的项目应该加入这个新的基金会。 实际上,这样的讨论持续了多年,大致的动机简洁摘要在这里。\n此时,作为一名用户,又意味着什么呢?\n 首先,不会有大的中断。还是同样的人,URL 地址不会变,也会有正常的发布。决策方式也会延续,pull request 也不会发生变化。改变会逐步的进行。\n 这是 Jenkins 项目在这个领域的成熟和重要性的又一证明。在全球有25万个 Jenkins 在运行着,这着实从 IoT 到游戏、从云原生应用到机器学习项目撼动着整个软件研发的世界。对于任何寻求开放异构 DevOps 策略的人来说, Jenkins 是一个显然、安全的选择。\n CDF 创建了一个公平竞争的环境,这被组织中的贡献者所熟知,同时也会带来更多的贡献者,让 Jenkins 发展的更好、更快。在过去的几年里, Jenkins 项目正在稳步地增长,更多的结构使之变得清晰起来,CDF 是这一轨迹中的最新一步。\n 任何认真的研发团队都会把多种工具和服务结合起来,以覆盖整个软件研发领域。这些团队为了把这些工具集成起来投入了大量的工作。 Jenkins 将会在 CDF 旗下与其他项目紧密合作,使得这些软件之间减少重复。\n 我们的用户作为从业者尝试在他们的组织中改善软件研发流程。他们认为 CI/CD 和自动化可以释放组织所需要的生产力,但对他们的组织而言,并不总是那么显著。因此,我们的用户往往无法得到必要的支持。CDF 将会倡导持续交付的实践,因为这并不是来自某个厂商或项目,它将会联系可以提供帮助的人。\n  因此,我希望你能明白为什么我们会对此感到如此兴奋!\n实际上,对我们来说,已经为这个想法努力了将近两年。毫不夸张地说,整个 CDF 的想法 源自 Jenkins 项目。\n为此,已经有很多人在幕后做了大量的工作。但有些人扮演了举足轻重的角色,我须亲自感谢他们。为 Chris Aniszczyk 的耐心、坚持,R. Tyler Croy 酝酿并推动着这个想法,Tracy Miranda 将这些想法变成事实。\n",
        "auhtor": "kohsuke",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-electron-pipeline-demo/",
        "title": "Electron 应用的流水线设计",
        "type": "wechat",
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "Pipeline", "Electron"],
        "description": "跨平台构建的流水线 demo",
        "content": "  审校:LinuxSuRen(https://github.com/LinuxSuRen)\n 面向读者:需要了解 Jenkins 流水线的基本语法。\nElectron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。\n本文将介绍 Electron 桌面应用的流水线的设计。\n但是如何介绍呢?倒是个大问题。笔者尝试直接贴代码,在代码注释中讲解。这是一次尝试,希望得到你的反馈。\n完整代码 pipeline { // 我们决定每一个阶段指定 agent,所以, // 流水线的 agent 设置为 none,这样不会占用 agent agent none // 指定整条流水线的环境变量 environment { APP_VERSION = \u0026quot;\u0026quot; APP_NAME = \u0026quot;electron-webpack-quick-start\u0026quot; } stages { stage(\u0026quot;生成版本号\u0026quot;){ agent {label \u0026quot;linux\u0026quot; } steps{ script{ APP_VERSION = generateVersion(\u0026quot;1.0.0\u0026quot;) echo \u0026quot;version is ${APP_VERSION}\u0026quot; }} } stage('并行构建') { // 快速失败,只要其中一个平台构建失败, // 整次构建算失败 failFast true // parallel 闭包内的阶段将并行执行 parallel { stage('Windows平台下构建') { agent {label \u0026quot;windows \u0026amp;\u0026amp; nodejs\u0026quot; } steps { echo \u0026quot;${APP_VERSION}\u0026quot; } } stage('Linux平台下构建') { agent {label \u0026quot;linux \u0026amp;\u0026amp; nodejs\u0026quot; } // 不同平台可能存在不同的环境变量 // environment 支持阶段级的环境变量 environment{ SUFFIX = \u0026quot;tar.xz\u0026quot; APP_PLATFORM = \u0026quot;linux\u0026quot; ARTIFACT_PATH = \u0026quot;dist/${APP_NAME}-${APP_PLATFORM}-${APP_VERSION}.${SUFFIX}\u0026quot; } steps { script{ // Jenkins nodejs 插件提供的 nodejs 包装器 // 包装器内可以执行 npm 命令。 // nodejs10.15.2 是在 Jenkins 的全局工具配置中添加的 NodeJS 安装器 nodejs(nodeJSInstallationName: 'nodejs10.15.2') { // 执行具体的构建命令 sh \u0026quot;npm install yarn\u0026quot; sh \u0026quot;yarn version --new-version ${APP_VERSION}\u0026quot; sh \u0026quot;yarn install\u0026quot; sh \u0026quot;yarn dist --linux deb ${SUFFIX}\u0026quot; // 上传制品 uploadArtifact(\u0026quot;${APP_NAME}\u0026quot;, \u0026quot;${APP_VERSION}\u0026quot;, \u0026quot;${ARTIFACT_PATH}\u0026quot;) }}} // 将括号合并是为了让代码看起来紧凑,提升阅读体验。下同。 } stage('Mac平台下构建') { agent {label \u0026quot;mac \u0026amp;\u0026amp; nodejs\u0026quot; } stages { stage('mac 下阶段1') { steps { echo \u0026quot;staging 1\u0026quot; } } stage('mac 下阶段2') { steps { echo \u0026quot;staging 2\u0026quot; } } } } } } stage(\u0026quot;其它阶段,读者可根据情况自行添加\u0026quot;){ agent {label \u0026quot;linux\u0026quot;} steps{ echo \u0026quot;发布\u0026quot; } } } post { always { cleanWs() } } // 清理工作空间 } def generateVersion(def ver){ def gitCommitId = env.GIT_COMMIT.take(7) return \u0026quot;${ver}-${gitCommitId}.${env.BUILD_NUMBER}\u0026quot; } def uploadArtifact(def appName, def appVersion, def artifactPath){ echo \u0026quot;根据参数将制品上传到制品库中,待测试\u0026quot; }  代码补充说明 因为 Electron 是跨平台的,我们需要将构建过程分别放到 Windows、Linux、Mac 各平台下执行。所以,不同平台的构建任务需要执行在不同的 agent 上。我们通过在 stage 内定义 agent 实现。如在“Mac平台下构建”的阶段中,agent {label \u0026quot;mac \u0026amp;\u0026amp; nodejs\u0026quot; } 指定了只有 label 同时包括了 mac 和 nodejs 的 agent 才能执行构建。\n多平台的构建应该是并行的,以提升流水线的效率。我们通过 parallel 指令实现。\n另外,默认 Electron 应用使用的三段式版本号设计,即 Major.Minor.Patch。但是笔者认为三段式的版本号信息还不够追踪应用与构建之间的关系。笔者希望版本号能反应出构建号和源代码的 commit id。函数 generateVersion 用于生成此类版本号。生成的版本号,看起来类似这样:1.0.0-f7b06d0.28。\n完整源码地址:https://github.com/zacker330/electronjs-pipeline-demo\n小结 上例中,Electron 应用的流水线设计思路,不只是针对 Electron 应用,所有的跨平台应用的流水线都可以参考此思路进行设计。设计思路大概如下:\n 多平台构建并行化。本文只有操作系统的类型这个维度进行了说明。现实中,还需要考虑其它维度,如系统位数(32位、64位)、各操作系统下的各版本。 各平台下的构建只做一次编译打包。并将制品上传到制品库,以方便后续步骤或阶段使用。 全局变量与平台相关变量进行分离。  最后,希望能给读者带来一些启发。\n参考:  持续交付的八大原则:https://blog.csdn.net/tony1130/article/details/6673741 Jenkins nodejs 插件:https://plugins.jenkins.io/nodejs Electron 版本管理:https://electronjs.org/docs/tutorial/electron-versioning#semver  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "https://showme.codes/2019-03-10/electronjs-pipeline-demo/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-gsoc2019-announcement/",
        "title": "Jenkins 已经被 Google Summer Of Code 2019 接受!",
        "type": "wechat",
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["gsoc", "gsoc2019", "events", "community"],
        "description": "19年的 Google Summer Of Code 正式起航",
        "content": " 作为 Jenkins GSoC 管理员团队的代表,我很高兴地宣布 Jenkins 在2019年的 Google Summer of Code上 已经被接受。 今年,我们邀请了学生和导师加入 Jenkins 社区,并一起努力增强 Jenkins 生态圈。\n这里提供一些数字,这是有史以来最大的一次 GSoC,今年共有206个组织参与。并且,希望对 Jenkins 而言也是最大的一年。 我们有25个项目想法,而且有超过30个准导师(不断增多!)。 这已经超过了2016年以及2018年的总和。 有很多的插件,特别兴趣小组以及子项目已经加入了今年的 GSoC.而且,我们已经收到了十几个学生的消息以及第一次贡献,耶!\n下一步? GSoC 已经正式启动,请期待更多的学生在我们的Gitter 频道和邮件列表中联系项目。 在特别兴趣小组和子项目频道中已经有了很多沟通。 我们会努力帮助学生找到他们感兴趣的项目,在这个领域探索,并帮助他们在4月9日的截止日前准备好他们的项目提议。 然后,我们将会继续这个申请,选择项目并分配导师团队。\n所有关于 Jenkins GSoC 的信息都可以在子项目页面上找到。\n我是一个学生。如何申请? 在/projects/gsoc/students[学生的信息]页面中有完整的申请指导。\n我们鼓励感兴趣的学生尽早联系 Jenkins 社区并开始探索项目。所有的项目在对应的页面上都有聊天室与邮件列表。 我们也会为学生组织工作日的会议,在这些会议上你可以见到管理员和导师,并向他们提问。 另外,加入我们的Gitter 频道和邮件列表,以便收到项目中即将到来的事情。\n3月25日开放申请,但你现在就可以准备了!利用这段申请前的时间来讨论并改进你的项目提议。 我们也建议你着手熟悉 Jenkins 并开始探索你的提议的领域。项目的想法包括快速开始的指导,以及有助于初期研究时对新手友好的问题。 如果没有看到任何感兴趣的,你可以提出你自己的项目想法或者 查看由其他参与 GSoC 的组织提出的想法。\n我想要成为一名导师。会不会太晚了? 不晚!我们正在寻找更多的项目想法,以及 Jenkins 的贡献者或用户中对 Jenkins 富有热情并想要指导学生的人。 无须底层经验,导师可以和学生一起研究项目并给出技术指导。 我们尤其对 Java 技术栈方向感兴趣,以及一些新的技术和领域(例如:Kubernetes, IoT, Python, Go 或者其他的)。\n你可以提议一个新项目或者加入已有的。查看博客寻找导师以及导师的信息中的细节。 如果你想要提议一个新项目,那么请在3月11日之前完成,以便学生有时间探索并准备他们的提议。\n今年,导师并不必须要有 Jenkins 开发上的很强的专业知识。目标是指导学生参与到 Jenkins 社区。 如果需要特殊的专业知识,GSoC 组织管理员会帮助寻找顾问。\n重要的日期  3月11日 - 停止新的 GSoC 项目提议 4月9日 - 停止接受学生的申请 5月6日 - 宣布接受了的项目,团队开始社区合作以及编码 8月26日 - 结束编码 9月3日 - 宣布结果  查看 GSoC 时间线了解更多信息。 在 GSoC 期间和之后,我们也会组织 Jenkins 相关的特别活动(例如:在 Jenkins World 上)。\n",
        "auhtor": "oleg_nenashev",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-ready-for-cdf/",
        "title": "为 Continuous Delivery Foundation 的成立感到兴奋",
        "type": "wechat",
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["cdf", "cicd", "jenkins", "opensource"],
        "description": "CDF 就要来啦",
        "content": "大概十一年前,我就开始为现在被称为 Jenkins 的项目做贡献,自己当时其实也并不知道在做什么。但是接下来发生的事情令人感觉难以置信,数以百计的贡献者加入,成千上万的新用户开始使用 Jenkins,每天都会运行数以百万条的流水线。这样的增长是充满挑战性的,用户的增长意味着问题的增长,问题的增长就意味着需要新的解决方式。 在大约两年半之前,我在2017年的 Jenkins World Contributor Summit 大会上面对一大群 Jenkins 的贡献者们,为我的所谓的 \u0026lsquo;Jenkins软件基金会\u0026rsquo; 做了宣传,那就是,不要羞于从 Python 社区汲取思想,在我的朋友 Chris Aniszczyk 和 Linux 基金会的帮助下,这个基金会变成了一个更加全面的 *持续交付基金会*(CDF),我的同事 Tracy Miranda 一直在领导这项工作,帮助推动 CDF 的成立。\nKohsuke 为 jenkinsci-dev@ mailing list 撰写了一篇很好的概述文章,其中列举了如果 Jenkins 项目一旦建立后就应该加入 Continuous Delivery Foundation 的原因。如果你对 Jenkins 项目感兴趣,但是还没有阅读过这边文章的话,那我认为你应该花些时间来阅读 Kohsuke 的这份邮件。但是在 这篇文章 中,我 想分享我愿意帮助建立持续交付基金会(CDF)的原因。\n持续交付(CD)已经成为我职业生涯中不可或缺的一部分,甚至在 Jez Humble 将此概念清晰地表述之前,我就开始学习 CD 并且对它一直充满热情。我认为它对软件的开发实践至关重要,当有人说他们没有练习使用 CI 或 CD 时,我感觉这就像回到了原始社会。想象一下,如果有人说 \u0026ldquo;呃,我们在这里有一个采用 Source Control 的项目,但领导们觉得这个东西不太靠谱\u0026rdquo;,我想你肯定会惊掉下巴。\u0026rdquo;在这个时代竟然还有开发团队都不使用源代码管理?\u0026rdquo;。总体来说,我认为CD已经是现代软件开发的基础了。\n持续交付也 不是 说只依赖于 Jenkins 这样的单一工具,它也是依赖于其他的用于协同工作的许多工具。虽然我可能觉得 Jenkins 是所有工具中占最中心位置的工具,但也不是说 Jenkins 是这些工具中唯一优秀的一款工具。但是不幸的是,像 Jenkins 这样的许多开源社区往往对他们的世界有着一定的狭隘观点。他们只专注于他们的事情,虽然这是有道理的,但这及可能导致错失交叉合作产生新价值的机会。\n我们所依赖 CD 的许多工具现在都是完全支持的,或者一小部分由不同的供应商支持。Jenkins 从 CloudBees、微软和 Red Hat 获得了大量投资。在过去的五年中,我逐渐认识到像 CDF 这样的基金会需要在这些不同公司中保持中立的位置。我们为企业贡献者提供一套指导方针,规则和期望,这样开源项目就会更有可能从他们那里获得支持。无论是宣传,代码或是现金,帮助企业贡献者在与我们其他人在一个相同的中立立场上,都会有助于确保开源工作的长久性。而且基金会制定规则的附加好处是,公司的参与者不会有意或无意地想要去超越对方或某个贡献者。\n在免费和开源项目的早期阶段,我们自欺欺人地认为每个人都会阅读我们的许可证,订阅我们的“开源精神”,提出问题并修复问题,或者为我们贡献代码。但 现实情况是,运营大型开源社区其实需要更多的资源。它不仅需要人,需要基础设施,而且还需要钱。像 CDF 这样的基金会为依赖项目或以其他方式投资项目的组织提供了一种有意义的参与方式。 Jenkins 项目的资金预算很紧张,我们每年的花费大约在10,000-15,000美元之间。如果我们要将我们捐赠的资产,提供的免费服务或我过去十一年来所做的事情都收取报酬的话,那么这个数字每年在60,000-80,000美元之间。 Kohsuke 可以证明我有能力为 Jenkins 项目提供免费的东西,但免费的东西并不是每年都保证会有的。为了更好的发展,Jenkins 需要一个稳定的预算,类似于像 FreeBSD Foundation 这样的大型基金会,这样我们便可以投资于服务和人员。\n如果您发现自己在担心开源的可持续性,那么请查看不同的社区,众筹或其他意识形态工具(如许可变更),并且请允许我帮助您。一致的预算是让大型开源项目可持续发展的重要因素。因为开源项目靠的是 *人*。确保有才能的作家,开发人员,营销人员,测试人员和设计师继续提供支持,就代表着他们雇主必须代表他们投入时间的成本,或者他们需要通过其他方式获得报酬。我坚信开源基金会能够为更大的免费和开源项目发展提供解决 预算 问题的途径。\nCDF虽然尚未启动,但我已经对它的潜力感到兴奋。因为这个基金会不仅适用于Jenkins项目,还适用于整个持续交付领域。\n",
        "auhtor": "rtyler",
        "translator": "yuzp1996",
        "original": "https://brokenco.de/2019/01/31/lets-go-cdf.html",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-01-08-mpl-modular-pipeline-library/",
        "title": "MPL - 模块化的流水线库",
        "type": "wechat",
        "date": "2019-03-06 00:00:00 +0000 UTC",
        "tags": ["jenkins", "pipeline", "shared-library"],
        "description": "Jenkins 流水线共享库技术实践",
        "content": " MPL - 模块化的流水线库 尽管通过自动化部署加快了开发速度,但由于在 DevOps 方面缺少协作,我们一个客户正因此而放慢产品的上市时间。虽然他们也投入了资源来做 DevOps ,但每条生产流水线都是独立设置的,迫使团队为每个项目重新造轮子。更糟糕的是,由于没有跨团队协作,平台中的任何错误又会出现在每条新的流水线中。许多客户都有类似的问题存在,因此我们决定开发一个既能帮助现有客户,又能适应未来使用需求的通用工具。使用通用框架且标准化的 CI/CD 平台是最显而易见的选择,但这将导致缺少灵活性的单体结构(monolithic structure),最终会变得举步维艰。每个团队都需要在自己的流水线上工作,基于此,我们开发了一个方便 DevOps 流水线的每个可重用部分可供以后使用的解决方案 — Jenkins 驱动的模块化流水线库。\n解决方案:模块化流水线库 模块化流水线库(译注:modular pipeline library,简称 MPL)是一个高度灵活的 Jenkins 流水线共享库,它可以轻松将最佳实践共享到整个公司。它具有清晰的模块化结构,先进的测试框架,多级嵌套的能力,流水线配置系统,被改进了的错误处理机制以及许多其他有用的组件。\n我们将通过以下几部分内容深入了解并解释 MPL 是如何工作的:\n 探索用于构建 MPL 的技术和工具 回顾MPL,并说明它为何有效 一步一步在流水线样例中使用 MPL 深入研究 MPL 的一些重要的组件,例如测试框架和嵌套库  首先,让我们介绍构建 MPL 时使用到的关键技术。\n使用共享库和 Jenkins 流水线构建 MPL 我们的 Jenkins 自动化平台最近收到了一些 Jenkins 流水线的更新。这些更新允许我们创建一个 Jenkinsfile 文件来描述整条流水线,并用于执行一系列不言自明的脚本。这提高了最终用户对 CI/CD 自动化流程的可视化程度,并提高了 DevOps 团队对流水线的可支持性。\n然而,流水线存在一个很大的问题:很难用唯一的流水线支持多个 Jenkinsfile 文件(因此存在多少个项目就存在多少个 Jenkinsfile 文件)。我们需要一个地方存放公共逻辑,这正是 Jenkins 共享库能够实现的。共享库用于存放流水线公共的部分,它定义在 Jenkinsfile 文件中,并允许在其中使用接口简化自动化脚本。\n虽然共享库允许你存储公共逻辑并操作 Jenkins,但它们并没有提供一种好的方式去使用这些公共逻辑。所以,MPL 通过允许用户创建易于理解的流程描述来优化流水线和共享库,然后方便其他团队使用。\nMPL 致力于创建跨团队协作 DevOps 流程 通过 MPL,我们现在能够跨团队协作和共享 DevOps 实践,轻松地为特定的项目指定特定的流水线,并能在将它们集成到 MPL 库中之前进行调试和测试。每个团队都可以创建一个嵌套库,在其中增加流水线和模块,并在流水线中使用,这样还可以提高流水线的可视化程度。MPL 能够适用于任何包含 Jenkinsfile 文件的项目,还可以根据项目团队的需要灵活地管理它。\nMPL 的核心是提供一种简单的方法:\n 通过引入模块分离流水线和步骤 使用简单的接口描述模块中的步骤 测试所描述的模块并与其他流水线和项目共享结果  MPL 中还有许多其他功能,但本质上它是一个解决 DevOps 一般性协作问题的平台。为了简化开发和手动测试,MPL 提供了模块覆盖和继承模型,允许用户在不影响其他任何情况下测试项目中的特定修复。在 Jenkins 中,一个模块就是一个文件,其中包含脚本步骤和逻辑,以实现简单的目标(构建工件,运行测试,创建图像等)。这些模块在流水线的阶段中可以被组合使用,而且任何了解 Jenkins 流水线语法的人都可以轻松读懂。\nMPL 允许用户使用库的核心特性(结构,模块,管道)并创建嵌套库以满足特定 DevOps 团队的需求。DevOps 团队可以在他们的项目中使用任何自定义的逻辑来组装一条完整的流水线。他们还可以通过多种方式覆盖和继承核心 MPL 模块,或者轻松地与其他团队分享自定义模块。接下来的信息,展示了这些模块的适用范围:\n你还可以在模块中指定某些流水线所需的后续步骤。例如,动态部署模块的执行会创建测试环境,当流水线结束时,它又会销毁该测试环境。想要仔细查看 MPL 调用过程,请查看下图:\n此图显示了 MPL 的执行。首先,你必须创建一个 Jenkins 任务,它将调用 Jenkinsfile(例如,当源代码被更改时),之后 Jenkinsfile 将调用流水线。流水线逻辑可以被定义在这些位置:MPL 端、Jenkins 任务的流水线脚本中 、嵌套库或项目 Jenkinsfile 中。最后,流水线的各个阶段将调用模块,而这些模块所使用的特性,可能来自 groovy 逻辑,流水线步骤或者共享库中的步骤。\n现在我们已经完成对解决方案的概述,接下来,让我们通过一个简单的流水线来了解 MPL 是如何工作的。\n流水线在 MPL 中执行的示例 假设你有一个常规的 Java Maven 项目。你在项目中创建 Jenkinsfile,并希望使用 DevOps 团队准备的默认流水线。MPL 本身就提供一个简单的流水线:核心 MPLPipeline 。这是一个非常简单的流水线,但对于想要尝试 MPL 的人来说,这是一个很好的开端。我们来看一下这个简单的 Jenkinsfile 文件:\n@Library('mpl') _ MPLPipeline {}  这个 Jenkinsfile 文件只包含两行代码,一行加载 MPL 逻辑,另一行运行流水线。大多数的共享库实现了像这样的接口,调用步骤并提供参数。MPLPipeline 只是一个自定义的流水线步骤,因为它位于 vars 目录中。MPLPipeline 结构非常简单,执行步骤如下:\n 初始化 MPL MPL 使用 MPLManager 单例对象来控制流水线 使用默认值合并配置并将其存储 指定阶段所需的默认配置并预定义一些有用的配置 定义一个包含4个阶段和后续步骤的声明式流水线:  检出(Checkout)- 获取项目源代码 构建(Build)- 编译,静态分析,单元测试 部署(Deploy)- 将制品上传到动态环境(dynamic environment)并运行应用程序 测试(Test)- 检查与其他组件的集成 后续步骤(Poststeps)- 清理动态环境,发送通知等  运行已定义的流水线 这是 MPL 开始发挥其魔法并实际运行的地方  MPL 的主要阶段只有一步,即 MPLModule。此步骤包含 MPL 的核心特性:执行包含流水线逻辑的模块。你可以在 MPL 代码仓库中找到默认模块,这些模块位于 resources/com/griddynamics/devops/mpl/modules 目录中,包括:Checkout,Build,Deploy 和 Test 模块。在每个模块的目录中,我们都可以找到真正执行相应阶段逻辑的 Groovy 文件。下图是简化了的 MPL 代码仓库结构图:\n检出阶段启动时,MPLModule 按名称加载模块(默认为阶段名称),并运行 Checkout/Checkout.groovy 文件中的逻辑:\nif( CFG.'git.url' ) MPLModule('Git Checkout', CFG) else MPLModule('Default Checkout', CFG)  如果配置中包含该 git.url 选项,它将加载一个 Git Checkout 模块。否则,它将运行该 Default Checkout 模块。所有被调用的模块使用与父模块相同的配置,这就是 CFG 被传递给 MPLModule 调用的原因。在以上代码中,我们没有指定 git.url 配置,因此它将运行 Checkout/DefaultCheckout.groovy 中的逻辑。模块名称中的空格是将模块映射到特定文件夹的分隔符。\n在 Default Checkout 模块中,只有一行代码 checkout scm,它负责克隆 Jenkins 任务中指定的源代码仓库。这就是检出阶段所做的一切,MPL 对于这么小的阶段似乎有些多余,我们只需要在这里讨论它,以展示 MPL 在模块中的工作方式。\n当流水线运行 Maven Build 模块时,也是同样的运行逻辑:\nwithEnv([\u0026quot;PATH+MAVEN=${tool(CFG.'maven.tool_version' ?: 'Maven 3')}/bin\u0026quot;]) { def settings = CFG.'maven.settings_path' ? \u0026quot;-s '${CFG.'maven.settings_path'}'\u0026quot; : '' sh \u0026quot;\u0026quot;\u0026quot;mvn -B ${settings} -DargLine='-Xmx1024m -XX:MaxPermSize=1024m' clean install\u0026quot;\u0026quot;\u0026quot; }  这个阶段稍微复杂一些,但是操作很简单:我们使用默认名称为 Maven 3 的工具来运行 mvn clean install 命令。这些模块是脚本化的流水线(scripted pipeline),所以你可以执行所有 Jenkins 流水线支持的步骤。这些文件不需要任何特定的和复杂的语法,只需要一个普通的文件,其中包含步骤和 CFG, CFG 是包含了阶段配置的预定义变量。MPL 模块从父模块继承了沙盒(sandbox),因此你的脚本执行将是安全的,并且和一个普通的 Jenkins 流水线一样在 Jenkins 重启后还能生效。\n在 Deploy 文件夹中,Openshift Deploy 模块具有相同的结构。它的主要目的中是为了展示如何在模块中定义后续步骤(poststep):\nMPLPostStep('always') { echo \u0026quot;OpenShift Deploy Decommission poststep\u0026quot; } echo 'Executing Openshift Deploy process'  首先,我们定义了 always 后续步骤。它最终会被存放到 MPLManager 对象中(译注:https://github.com/griddynamics/mpl/blob/master/src/com/griddynamics/devops/mpl/MPLManager.groovy#L40),在真正执行后续步骤时被调用。我们可以多次定义 always MPLPostStep:所有后续步骤都将按先进后出(FILO)顺序存放和执行。因此,我们可以在同一模块中定义需要完成和撤消操作的后续步骤逻辑,例如动态环境的销毁。这样就可以确保在流水线完成时执行操作。\n在部署阶段之后,流水线会执行测试阶段,但是在测试阶段并没有太多有趣的事情发生。然而,测试中有一个非常重要的事情,那就是 MPL 本身的测试。\nMPL 本身的测试 MPL 的测试框架基于 LesFurets 的 JenkinsPipelineUnit,其中一个很小的区别是它能够测试 MPL 模块。测试整个流水线被认为是不现实的,因为流水线可能非常复杂,为这些怪物编写测试就像一项西西弗斯任务(sisyphean task,译注:永无尽头而又徒劳无功的任务)。而使用用少量的步骤测试一个黑盒要容易得多,可以确保任务能正常工作。\n在 MPL 源代码中,你可以找到构建模块的测试用例:所有测试都存放在 test/groovy/com/griddynamics/devops/mpl/modules 目录中,Build/BuildTest.groovy 文件内有多个测试用例。MPL 库的构建阶段会执行这些测试,测试的步骤如下:\nLoading shared library mpl with version snapshot MPLModule.call(Build, {maven={tool_version=Maven 2}}) Build.run() Build.MPLModule(Maven Build, {maven.tool_version=Maven 2}) MavenBuild.run() MavenBuild.tool(Maven 2) MavenBuild.withEnv([PATH+MAVEN=Maven 2_HOME/bin], groovy.lang.Closure) MavenBuild.sh(mvn -B -DargLine='-Xmx1024m -XX:MaxPermSize=1024m' clean install) Build.fileExists(openshift)  测试运行 MPLModule 自定义配置和模拟步骤,以检查在执行期间,工具是否已根据提供的配置更改为 Maven 2。我们使用此类测试覆盖所有测试用例,确保模块按预期工作,并且流水线将正常工作。如果需要,你可以测试整条流水线,但模块测试是简化测试过程的一种方法。\n现在我们已经了解了如何测试 MPL 模块,现在是时候看看 MPL 的一个关键特性,即嵌套库。\n嵌套库的好处 在大型公司中,支持一个大型库是没有意义的。每个部门都需要多个(不同于标准的)配置选项,并针对标准流水线进行调整,这会带来不必要的工作量。MPL 通过引入嵌套库来解决这些问题。下图展示了使用嵌套库与仅仅使用主库的区别:\n嵌套库与共享库相同,都通过导入 MPL 使用其特性,模块和流水线。此外,它允许将一些与团队相关的逻辑与公司的通用逻辑分离。以下是具有嵌套库的 MPL 的结构:\n你可以在重写的流水线中导入 MPL,指定一些附加模块的路径,覆盖模块逻辑,并由 Jenkins 负责协调(译注:此处原文是You can import the MPL in the overridden pipeline, specify the path of some additional modules, override module logic, and use Jenkins power moves: there are no limitations. 本人能力有限,无法真正理解作者的意思)。当另一个团队需要你的模块时,你只需向公司 MPL 基础仓库提交变更请求,如果变更请求通过,就可以与他们共享你的功能模块。\n因为嵌套库可以覆盖 MPL 或 Jenkins 流水线的基本功能,所以嵌套库可以调试和修改 MPL 提供的步骤(例如 MPLModule)和流水线。你可以覆盖任何功能,因为这些覆盖仅影响你自己的流水线。经常验证的嵌套库,可以与其他团队讨论,看看它是否也适用于其他嵌套库。\n嵌套库的嵌套层级数是没有限制的,但我们建议仅使用两层级( MPL 和嵌套库),因为在低层级上配置和测试嵌套库非常复杂。\n强大的模块覆盖 进一步了解嵌套库和项目端模块后,我们知道,模块名称是可以与上层库中模块名同名的。这是覆盖上层模块逻辑的好方法——使用自己的模块替换 Build/Build.groovy——真正执行时就会执行你的模块中的逻辑,而不是上层模块的。下图说明了模块覆盖是如何工作的:\n更棒的是,MPL 的优点之一是你仍然可以使用上层模块!MPL 具有防止循环调用的机制,因此同一运行分支中不会再次运行同一模块。但是,你可以轻松地通过在一个模块中调用原始模块来使用上层逻辑。\n上面的 Petclinic-Selenium 示例中,使用了默认值 MPLPipeline(您可以在 MPL Wiki 页面上找到它),并在 .jenkins 目录中包含项目级别模块。这些模块将在库模块之前调用。例如,Checkout 模块没有放在项目级别,因此它将从 MPL 调用,但 Build 模块存在于 .jenkins 项目端的目录中,它将被调用:\nMPLPostStep('always') { junit 'target/surefire-reports/*.xml' } MPLModule('Build', CFG) if( fileExists('Dockerfile') ) { MPLModule('Docker Build', CFG) }  如代码所示,项目中的 Build 模块注册了后续步骤,接着调用原始的 Build 模块,最后调用 Docker Build 模块。流水线的后续阶段更复杂,但所有模块覆盖基本原理都相同。现实中,有些项目可能很棘手,需要对现有模块进行一些小调整。但是,你可以在项目级别的模块中轻松调整,并考虑如何将功能移动到嵌套库或 MPL 中。\n结论:MPL 为 DevOps 带来了什么 许多 DevOps 团队和公司都使用臃肿,限制多的的和错误的 CI/CD 自动化平台。这增加了用户的学习曲线,导致团队工作更慢,并提高了生产成本。DevOps 团队发现,相同的问题经常在不同的项目中出现,而缺乏协作意味着团队每次都必须单独修复它们。\n但是,通过 MPL,DevOps 团队拥有一个共享、简单、灵活的 CI/CD 平台。可以改善生产过程中的用户支持,协作和整体项目源代码。通过利用 MPL,你的公司可以找到自动化共识,实现跨公司协作的目标,并重用来自大型社区的最佳实践。而且这些都是开源工具。如果你对构建 MPL 感兴趣,请联系我们以了解更多信息!\n其他资源  Jenkins Pipeline Engine Jenkins Shared Libraries MPL GitHub repository  概述和演示视频:  介绍 概述 MPL Build的演示 嵌套库的演示 流水线的演示  ",
        "auhtor": "sparshev",
        "translator": "zacker330",
        "original": "https://jenkins.io/blog/2019/01/08/mpl-modular-pipeline-library/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/about/star-plan/",
        "title": "社区贡献激励方案",
        "type": "about",
        "date": "2019-03-03 00:00:00 +0000 UTC",
        "tags": [],
        "description": "激励可以让社区活动更有趣",
        "content": " 为了激励社区成员积极地为社区作出贡献,我们会不定期给予积极活跃、付出重大贡献的小伙伴一定形式的奖励。\n定期激励:每个季度被选中的贡献者,可以在人民邮电出版社微店中自行挑选图书一本。\n大会门票赠送:不定期会有合作社区的大会门票赠送给有需要的贡献者。\n其他激励: 此外,还会有其他形式的激励。\n下面是历次的奖励记录:\n大会门票赠送 不定期会有合作社区的大会门票赠送给有需要的贡献者。\n需要大会门票的成员需要在 GitHub 的 jenkins-zh/jenkins-zh 仓库提交一个 issue 用来申请门票,在该 issue 中需要提供最近贡献的 PR(Pull Request)链接。\n下面的表格中包括所有大会的历次赠票记录:\n   大会 举办时间 成员 奖励 申请链接     Jenkins User Conference China 2019年11月2日  donhui  门票一张 #138   Jenkins User Conference China 2019年11月2日  tomatofrommars  门票一张 #139    社区聚会    日期 城市 成员 备注     2020-1-5 北京  linuxsuren  50元   2020-1-5 北京  donhui  50元   2020-1-5 北京  linan607  50元   2020-1-5 北京  yJunS  50元 论坛帖子    定期激励 每个季度被选中的贡献者,可以在人民邮电出版社微店中自行挑选图书一本。\nNO.2 时间范围:2019年6月~8月\n赞助方:人民邮电出版社\n   成员 奖励      donhui  《人生护城河 如何建立自己真正的优势》    yJunS  《精通 jQuery(第二版)》    linan607  《持续交付 2.0 业务引领的 DevOps 精要》    P01son6415  《算法 第四版》    hummerstudio  《极简主义——风靡欧美的工作与生活理念》    NO.1 时间范围:2019年3月~5月\n赞助方:人民邮电出版社\n   成员 奖励      donhui  《黑客与画家》    zacker330  《基础设施即服务》    yJunS  《黑客与画家》    ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-jenkins-script-console-in-practice/",
        "title": "批量修改 Jenkins 任务的技巧",
        "type": "wechat",
        "date": "2019-02-27 00:00:00 +0000 UTC",
        "tags": ["Jenkins"],
        "description": "Jenkins 脚本命令行的一种实践",
        "content": " 通过脚本命令行批量修改 Jenkins 任务 最近,笔者所在团队的 Jenkins 所在的服务器经常报硬盘空间不足。经查发现很多任务没有设置“丢弃旧的构建”。通知所有的团队检查自己的 Jenkins 任务有没有设置丢弃旧的构建,有些不现实。\n一开始想到的是使用 Jenkins 的 API 来实现批量修改所有的 Jenkins 任务。笔者对这个解决方案不满意,经 Google 发现有同学和我遇到了同样的问题。他使用的更“技巧”的方式:在 Jenkins 脚本命令行中,通过执行 Groovy 代码操作 Jenkins 任务。\n总的来说,就两步:\n 进入菜单:系统管理 \u0026ndash;\u0026gt; 脚本命令行 在输入框中,粘贴如下代码:\nimport jenkins.model.Jenkins import hudson.model.Job import jenkins.model.BuildDiscarderProperty import hudson.tasks.LogRotator // 遍历所有的任务 Jenkins.instance.allItems(Job).each { job -\u0026gt; if ( job.isBuildable() \u0026amp;\u0026amp; job.supportsLogRotator() \u0026amp;\u0026amp; job.getProperty(BuildDiscarderProperty) == null) { println \u0026quot; \\\u0026quot;${job.fullDisplayName}\\\u0026quot; 处理中\u0026quot; job.addProperty(new BuildDiscarderProperty(new LogRotator (2, 10, 2, 10))) println \u0026quot;$job.name 已更新\u0026quot; } } return; /** LogRotator构造参数分别为: daysToKeep: If not -1, history is only kept up to this days. numToKeep: If not -1, only this number of build logs are kept. artifactDaysToKeep: If not -1 nor null, artifacts are only kept up to this days. artifactNumToKeep: If not -1 nor null, only this number of builds have their artifacts kept. **/   脚本命令行介绍 脚本命令行(Jenkins Script Console),它是 Jenkins 的一个特性,允许你在 Jenkins master 和 Jenkins agent 的运行时环境执行任意的 Groovy 脚本。这意味着,我们可以在脚本命令行中做任何的事情,包括关闭 Jenkins,执行操作系统命令 rm -rf /(所以不能使用 root 用户运行 Jenkins agent)等危险操作。\n除了上文中的,使用界面来执行 Groovy 脚本,还可以通过 Jenkins HTTP API:/script执行。具体操作,请参考 官方文档。\n问题:代码执行完成后,对任务的修改有没有被持久化? 当我们代码job.addProperty(new BuildDiscarderProperty(new LogRotator (2, 10, 2, 10)))执行后,这个修改到底有没有持久化到文件系统中呢(Jenkins 的所有配置默认都持久化在文件系统中)?我们看下 hudson.model.Job 的源码,在addProperty方法背后是有进行持久化的:\npublic void addProperty(JobProperty\u0026lt;? super JobT\u0026gt; jobProp) throws IOException { ((JobProperty)jobProp).setOwner(this); properties.add(jobProp); save(); }  小结 本文章只介绍了批量修改“丢弃旧的构建”的配置,如果还希望修改其它配置,可以参考 hudson.model.Job 源码。\n不得不提醒读者朋友,Jenkins 脚本命令行是一把双刃剑,大家操作前,请考虑清楚影响范围。如果有必要,请提前做好备份。\n",
        "auhtor": "zacker330",
        "translator": "",
        "original": "https://showme.codes/2019-02-23/jenkins-script-console-in-practice/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-contribution-inspire/",
        "title": "社区贡献激励活动",
        "type": "wechat",
        "date": "2019-02-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "Jenkins 中文社区送福利",
        "content": "自 Jenkins 官方微信公众号开通以来,收到了很多热心、愿意参与开源社区的同学的贡献。这里,包括有 Jenkins 官方博客中的博文翻译,也有 Jenkins 中文站点维护的 Pull Request。我能够看到的是,有些同学从英文技术文章的翻译过程中,对 Jenkins 相关技术的理解更加深入了;而有的则从对 GitHub 不甚了解到逐渐熟悉社区贡献的大致流程;对于深度参与社区贡献的同学,更是能够在“中文本地化”以及 Jenkins 其他的特别兴趣小组(SIG)会议讨论上获得最新的动态。\n本着给社区贡献者谋福利的想法,Jenkins 中文社区携手“人民邮电出版社”给大家提供三本技术相关的书籍。从19年3月开始,截止到5月,我们会给予三名贡献者每人一本书。我们会在下次公众号文章中介绍评选规则,欢迎任何一位认可开源、希望参与开源的朋友提出你的建议,不要吝惜你的 PR。获选的同学,按照贡献量可以从下面的列表中依次任选一本:\n最后,再次让我们对“人民邮电出版社”给予开源社区的大力支持表示感谢。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-20-java11-preview-availability/",
        "title": "Java 11 预览支持已在 Jenkins 2.155+ 中可用",
        "type": "wechat",
        "date": "2019-02-20 00:00:00 +0000 UTC",
        "tags": ["core", "developer", "java11", "community", "platform-sig"],
        "description": "Java 11 预览支持已在 Jenkins 2.155+ 中可用",
        "content": "  NOTE: 这是由 Java 11 支持团队 联合撰写的博客。 在 12 月 18 号(UTC时间下午4点)我们也会在 Jenkins 在线 Meetup 展示对 Java 11 的预览支持。(链接)\n Jenkins 作为领先的开源自动化服务器之一,目前仍然只支持到 Java 8。在 9 月 25 日 OpenJDK 11 发布了。这是一个长期支持版本,并将持续多年,我们想要在 Jenkins 项目中对这个版本进行全面的支持。在过去的一年中,许多贡献者一直致力于在项目中支持 Java 11(Jenkins JEP-211)。这是一条艰辛的道路,但是现在,代表 Jenkins Platform SIG,我们很高兴的宣布在 Jenkins 每周发布提供 Java 11 预览!\n为什么我们需要 Java 11 的预览?\n这是因为它可以提供给 Jenkins 贡献者和早期使用者一个在明年年初(译者注:此文发布于 2018 年)GA 发布之前尝试这些变化的途径。它也可以帮助我们进行更多的探索性测试,并且有希望在 Jenkins 正式地提供 Java 11 支持之前,解决大部分的问题。\n在这篇文章中,我们将会介绍如何在 Java 11 环境下运行 Jenkins,还有如何调查兼容性问题并报告它们。\n背景 你可能还记得,在 2018 年 6 月我们举办了一个针对 Java 10+ 支持的在线黑客马拉松。作为黑客马拉松的一部分,我们提供了 Java 11 的实验性支持。这次活动对我们来说非常成功。我们可以在 Java 10 和 Java 11-ea 环境下运行 Jenkins 以及一些主要的功能 —— 包括流水线、JobDSL、Docker/Kubernetes plugin、Configuration as Code、BlueOcean 等。它让我们相信我们可以在 Jenkins 中提供Java 11支持而不会发生破坏性变化。在这场马拉松之后 Oleg Nenashev 创建了 \u0026ldquo;Java 10+ support in Jenkins\u0026rdquo;(之后修改为只针对支持 Java 11)。Jenkins Platform SIG 也已成立,以协调 Java 11 的支持工作和其他平台的支持工作(打包,操作系统支持等)。\n一组贡献者一直持续致力于 Java 11 支持,他们主要在关注上游的功能性补丁、在开发工具中提供 Java 11 支持、测试和解决已知的兼容性问题。详细的状态的更新,请参阅 Platform SIG 的会议记录。从 Jenkins 2.148 开始,Jenkins 在多个不同的 Linux 和 Windows 平台下成功的在最新的 OpenJDK 11 版本下运行。我们进行了大量的自动化和探索性测试,除了一些例外(见下文),大部分 Jenkins 插件运行良好。GA 版本发布需要的自动化测试工作还在进行,但是我们已经成功的运行了 Jenkins core 的测试,通过了全部的 Acceptance Test Harness,以及在推荐插件上运行通过了 Plugin Compat Tester。我们也部署了一个临时的为 Java 11 搭建的 Experimental Update Center,可以为 Java 11 的早期采用者提供快速的问题修复。使用Java 11 运行时,Jenkins 2.155+ 将会默认使用此更新中心,这就是我们宣布此版本的预览可用性的原因。\n在 2018 年 11 月 19 日,我们在 Platform SIG 会议的幻灯片上展示了当前的 Java 11 支持的状态,我们同意发布 Java 11 的可用性预览,以便我们可以提供内容让 Jenkins 用户得以进行评估。 在 12 月 4 日的下一次会议上,所有障碍都已得到解决,Platform SIG 会议签署发布了Java 11 预览版。\n在 Docker 中运行 Jenkins 和 Java 11 从 Jenkins 2.155 开始,我们开始为 Jenkins master 和 agent 提供 Docker 镜像。 所有这些镜像都基于官方的由 Docker 社区维护的 openjdk:11-jdk 镜像。这里有一些关于迁移到其他基本镜像的讨论,但是我们决定在预览可用性的范围中将其排除。基于同样的原因,我们目前不提供 Alpine 镜像。\nJenkins master 镜像 官方的 jenkins/jenkins 镜像现在已经提供了 Java 11 的支持。你可以向下面这样简单在 Java 11 的环境中运行 Jenkins。\ndocker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:jdk11  可以使用下面这些标签:\n jdk11 - 最新的包含 Java 11 支持的每周发布 2.155-jdk11 - 包含 Java 11 支持的每周发布=  这些镜像完全和 jenkins/jenkins documentation 兼容。例如:你可以使用 plugins.txt 来安装插件、挂载卷或者通过环境变量传递额外选项。\nAgent 镜像 如果你通过 Docker 或 Kubernetes 插件使用容器化的 agent,我们也发布了 Jenkins agent 的官方 Docker 镜像:\n jenkins/slave jenkins/jnlp-slave jenkins/ssh-slave  所有的镜像都可以使用 latest-jdk11 标签来获取 JDK 11 的捆绑。同时为这些过时的名字抱歉!\n实验性 Jenkins master 镜像 为了简化测试,我们也在 DockerHub 提供了一些实验性的镜像。 对于这些镜像,我们为其搭建好了持续交付流水线,所以不需要等待 Jenkins 的每周发布,就可以获得补丁。\n jenkins4eval/blueocean-platform-support - 等同于 jenkinsci/blueocean  标签: latest-jdk11 这个镜像捆绑了在 Java 11 上运行时需要的所有的 Jenkins 流水线和 Blue Ocean 的补丁 如果你想要使用流水线,使用这个镜像  jenkins/jenkins-experimental - 等同于 jenkins/jenkins  标签: latest-jdk11 这个镜像是从 Jenkins core 的 java11-support 分支中发布的 这个分支可能轻微的领先或落后于 master 分支,我们可能会用这个分支去快速发布补丁给 Java 11 用户   我们最终会把这个实验性流水线移到新的在 jep:217 中创建的 jenkins4eval 组织中去。\n在 Java 11 中运行 jenkins.war 在 Docker 外运行 Jenkins 并没有那么简单。这是因为 Jenkins 依赖一些在 Java 11 中已经被移除的模块。我们计划在 GA 发布中以某种方式解决掉这个问题 (参见 JENKINS-52186),但是现在,我们还需要一些手动操作才能在 Java 11 中运行 Jenkins WAR。\n 下载 2.155 版本的 Jenkins WAR 下载下面这些库到 jenkins.war 所在的目录中去  jaxb-api-2.3.0.jar (保存为 jaxb-api.jar) jaxb-core-2.3.0.1.jar (保存为 jaxb-core.jar) jaxb-impl-2.3.0.1.jar (保存为 jaxb-impl.jar) javax.activation v.1.2.0 (保存为 javax.activation.jar)  运行下列命令  Run Jenkins with ${JAVA11_HOME}/bin/java \\ -p jaxb-api.jar:javax.activation.jar --add-modules java.xml.bind,java.activation \\ -cp jaxb-core.jar:jaxb-impl.jar \\ -jar jenkins.war --enable-future-java --httpPort=8080 --prefix=/jenkins  已知的兼容性问题 为了帮助用户追踪兼容性问题,我们新创建了 Known Java 11 Compatibility Issues wiki 页面。\n几个重要的问题和障碍:\n Pipeline: Support Plugin 有一个已知的在 Java 11 中运行会产生的上下文持久性问题 (JENKINS-51998)  我们已经在 Experimental Update Center for Java 11 中部署了一个临时的修复版本。修复版本号: 3.0-java11-alpha-1。 如果你使用 Jenkins 流水线,请确认你使用了这个版本,否则你的 Job 会几乎立即失败 当你更新实例到 Java 11 时,请确认没有正在运行的流水线。  JENKINS-54305 - JDK Tool Plugin 不提供 JDK 11 的安装器 JENKINS-52282 - Java Web Start 在 Java 11 中已经不再可用, 所以我们不再可能在网页图形界面中启动 agent。我们也没有计划提供一个替代品。  我们也在其它插件中发现了一些次要的不兼容问题,但是我们不认为它们对于预览可用性来说是一个阻碍。\n报告兼容性问题 如果你碰到了任何有关 Java 11 兼容性的问题,请在我们的 bug 跟踪工具中报告问题。并为这类问题添加 java11-compatibility 标签,这样它们会自动出现在 wiki 页面中,并被分级。\n对于安全性问题,请使用标准的 漏洞报告流程。尽管我们在预览发布时,会公开修复 Java 11 相关的问题,但是遵守这个安全流程也会帮助我们调查它对 Java 8 用户的影响。\nJava 11 支持团队 一旦 Java 11 支持发布,我们希望会有插件和 Jenkins core 的回归 (regression)报告。我们关心的部分之一就是不同平台的本地库,还有其它的 Java 的版本的问题。同样,这里也存在第三方库和 Java 11 不兼容的风险。为了减轻这些风险,我们创建了 Java 11 支持团队。这个团队将会专注于对到来的问题进行分级、帮助 review PR、在一些情况下也会修复问题。这个团队的工作流程可在 JEP-211 文档中看到。\n我们不希望 Java 11 支持团队 去修复所有的发现的问题,我们将会和 Jenkins core 和插件的维护者一起解决它们。假如你有兴趣加入这个团队,可以在 Platform SIG Gitter Channel 中联系我们。\n贡献 我们感谢任何一种对 Java 11 支持的贡献, 包括在 Java 11 下运行 Jenkins,报告和解决兼容性问题。\n 假如你想要进行一些探索性测试,我们推荐你在你的其中一个测试实例中尝试 Java 11 支持。我们对这样的测试感激不尽。我们在上面提供了问题报告的准则。 假如你是一个插件的开发者/维护者,我们非常感谢你能在 Java 11 中测试你的插件。为了帮助你,我们创建了 Java 11 Developer guidelines。这个页面阐述了如何在 Java 11 下测试你的插件,同时它也列出了在开发工具中的已知的问题。  无论你做什么,请通过向 Platform SIG mailing list发送邮件告诉我们你的体验。这些信息将帮助我们跟踪变化和贡献。有关迁移复杂性的任何其他反馈将不胜感激!\n下一步是什么? 在 12 月 18 号(UTC时间下午4点)我们也会在 Jenkins 在线 Meetup 展示对 Java 11 预览支持(链接)。在这个 meetup 上我们将会总结目前的 Java 11 预览支持的状态。如果你是插件开发者,我们还将会组织单独的会议讨论有关在 Java 11 下测试插件以及有关修复兼容性问题的常见最佳实践。如果你有兴趣,请关注 Platform SIG 的公告。\n在下一周,我们将会专注于处理来自早期使用者的反馈并且修复一些发现的兼容性问题。我们还将继续为明年的 GA 发布开发 Java 11 支持补丁 (JENKINS-51805)。除此之外,我们将会开始在子项目中提供 Java 11 支持,包括 Jenkins X 和 Jenkins Evergreen。\n",
        "auhtor": "oleg_nenashev",
        "translator": "cizezsy",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-13-outreachy-audit-log-plugin/",
        "title": "Jenkins 对审计日志的支持",
        "type": "wechat",
        "date": "2019-02-13 00:00:00 +0000 UTC",
        "tags": ["community", "outreachy", "outreachy2018"],
        "description": "Outreachy 实习生提供了 Jenkins 对审计日志的支持",
        "content": "今年是 Jenkins 项目首次参与 Outreachy. Outreachy 是一个类似于 Google Summer of Code (GSoC) 的项目, 实习生有偿地为开源项目工作。 关键的不同之处在于,Outreachy 面向那些在他们国家的技术行业中受到歧视或偏见的小众群体。 当我了解到这个项目后,由于它的包容性与社区建设与我的理念相符就立即自愿作为导师来参与。 我很高兴地说,Jenkins 项目和我的雇主 CloudBees 对此非常支持。\n基于我们之前在 GSoC 上指导学生的付出,今年我们已经加入 Outreachy 并指导了两个实习生。 在 Outreachy 的这次活动中,我们的实习生 David Olorundare 和 LathaGunasekar 将与我一起研发 Jenkins 对审计日志的支持。 我很高兴欢迎 David 和 Latha, 并期待他们能在软件工程专业和对开源社区的贡献上都有所收获。 请继续关注后续博客对他们的介绍。\n该审计日志支持项目在 Jenkins 和 Apache Log4j 之间形成了一个新的链接,这给予我们的实习生学习 更多有关开源治理和认识新朋友的机会。 作为奖金,该项目旨在为支持高级的业务检测提供便利,例如:在认证事件中检测潜在的入侵尝试。 我们也会编写一个 JEP 来描述由插件提供的审计日志 API,以及其他插件如何定义并记录除 Jenkins 核心以外插件的审计事件。\n我期待我们将会一起完成了不起的作品,而且我希望在将来能够帮助更多的 Outreachy 实习生!\n",
        "auhtor": "jvz",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/about/how-to-involve/",
        "title": "如何参与",
        "type": "about",
        "date": "2019-01-05 22:56:04 +0800 +0800",
        "tags": [],
        "description": "参与 Jenkins 中文社区的具体步骤",
        "content": " 为什么要参与开源社区  翟志军:想亲身参与一个开源社区,了解其运行机制。而为什么选择 Jenkins 中文社区?是想更多人了解持续交付。 zhangc819:日常工作里经常需要开源社区的力量来解决问题、学习经验,参与开源社区建设也是为了给社区提供更多的力量,相互左右才能壮大下去。  如何参与 Jenkins 中文社区 参与 Jenkins 中文社区的方式不只有 Coding 一条路可选,还有很多方式,比如:\n 发表或翻译 Jenkins 相关的文章,并发表到社区网站及微信公众号。 Jenkins 本地化。 成为 Jenkins 线下或线上活动的志愿者。 Review 别人提交到 Pull Request。 发现 Jenkins 社区哪里可以改善,然后提个 Issue 或 Pull Request。  等等。所有你能想到的,促进 Jenkins 中文社区发展的事情都算是参与 Jenkins 中文社区。\n但是,具体怎么做呢?\n首先,我们都是基于 Git 工具进行协作的,所以,你需要会一些 Git 及 GitHub 的基础操作。\n分支策略主要是提供执行并行任务时的参考指引,方便社区贡献者借鉴使用。\n接下来,咱们分别介绍每一种参与方式。\nJenkins 中文社区代码仓库列表 那么,我们可以向哪些源代码仓库进行贡献呢?以下是各仓库的链接及简单介绍:\n wechat:存放 jenkins-zh.cn 网站的文章。也就是发文章可在此仓库提 PR。 jenkins-zh:Jenkins 中文社区网站源码,由 Hugo 实现。 wechat-backend:Jenkins 微信公众号机器人。 hugo-jenkins-theme:Jenkins 中文社区网站主题。 artwork:Jenkins 中文社区的艺术作品,比如 Jenkins 中文社区 Logo。  贡献 Jenkins 中文社区的具体工作 具体有哪些工作,可以让我们参与?\n翻译 Jenkins 相关文章 所有的翻译任务都会列在 GitHub的看板上。可以在看板上找到自己感兴趣的文章,然后将其拖到“In progress”列。这样可以避免重复的翻译。\n当然,为保证翻译质量,希望大家能做到:\n 认真、负责第一位。 翻译任务通常不建议超过两周。 遵守翻译规范。  Jenkins 中文本地化 本地化的工作包括:\n 对 Jenkins 官方网站及 博客 的翻译。Pull Request 提交到: cn.jenkins.io 代码仓库 。 维护 简体中文语言插件 Pull Request 提交到 localization-zh-cn-plugin 。  发表 Jenkins 原创文章 原创内容包括:Jenkins 相关、持续集成、持续交付、DevOps\n在 Jenkins 中文社区提交的 PR 通过后,会发布在多个不同的媒体平台上,目前包括:\n Jenkins 中文社区网站 Jenkins 微信公众号 开源中国博客 简书专栏 掘金  发表原创文章的步骤  Fork wechat 仓库,如果你还没有 fork。 在本地,参考 范文 写文章。动手前请仔细阅读请阅读规范。如果实在不明白的话,你也可以参考其它仓库中 articles 目录下的其它文章来写就好。 将本地的提交,推到自己的仓库。 在 GitHub 上提一个 PR。  关于排期 为了尽可能满足你期望的发布日期,可以自行选择,但同时需要满足如下的条件:\n 为保障大家有足够的时间进行 Review,建议排到一周以后 工作日 避免同一天有相同类型的文章  提 PR 时的要求  PR 的标题格式:[类型-文章排期] 标题 在 PR 类型列表前的 [] 中加入一个 x,例如:[x]  更多内容请参考 PULL_REQUEST_TEMPLATE.md\n分享 你可以在本站或者 Meetup 上分享你在使用 Jenkins 或者相关技术时总结的经验、教训、成果等。\n维护本站点 你可以从了解本站的架构开始。小到错别字修正,大到站点风格、架构完善都需要你的参与。\nReview 别人提交到 Pull Request Review 代码也算贡献社区的一种方式。\nLinus 说过:“Given enough eyeballs, all bugs are shallow(足够多的眼睛,就可让所有问题浮现)”。所以,当有贡献者提 Pull Request 到 Jenkins 中文社区的任何一个代码仓库,原则上,我们都需要两人及以上的人对该 Pull Request 进行 review。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/about/channels/",
        "title": "交流",
        "type": "about",
        "date": "2019-01-04 21:13:30 +0800 +0800",
        "tags": [],
        "description": "Jenkins 中文社区交流指南",
        "content": " 为了方便各位 Jenkins 的爱好者、用户以及贡献者之间互相交流,我这里列出来一些途径:\n 邮件组 即时聊天 在本站留言  邮件组 Jenkins 社区有很多 邮件组 ,感兴趣的童鞋请自行翻阅。本文仅介绍中文相关的邮件组:\n            Jenkins 中文用户邮件组  查看历史  订阅 取消订阅 求助   Jenkins 中文本地化兴趣邮件组  查看历史  订阅 取消订阅 求助     注意:点击上面的订阅或者取消都应该会弹出一个发送邮件的窗口,请不要做任何修改,邮件正文保持空白(不要添加邮件签名等内容)直接发送即可。邮件发送成功后,会收到确认的回复。鉴于邮件组是由 Google 提供的服务,无法科学上网的童鞋是无法查看历史邮件的。\n  即时聊天 即时聊天是一种很方便的线上交流方式,你有可能及时地收到大家的帮助,但是不要认为其他人有回答问题的义务。你没有能及时地得到帮助,可能是因为大家在忙、消息太多而被忽略、问题描述的不够详细等等。因此,建议大家在提问之前尽可能保证自己已经对问题理解的很清楚,并在提问时尽可能地给出上下文、复现步骤;当没有及时得到回答的话,可以把问题发送到邮件组(发送之前,请在邮件组中搜索其他人是否已经解决过类似问题),相信遇到过类似问题的人也会尽可能帮助你。\n Jenkins Gitter 中文聊天室 欢迎你!\n留言 本站的留言系统建立在 Github 提供的 Issues 上。欢迎大家在遵守社区行为规范的基础上积极地留言互动。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/about/course/",
        "title": "Jenkins 培训",
        "type": "slide",
        "date": "2019-01-03 22:50:02 +0800 +0800",
        "tags": [],
        "description": "Jenkins 培训大纲",
        "content": " class: center, middle\nJenkins 培训 大纲  Jenkins 项目介绍 安装、部署  传统环境 容器环境  插件管理 构建任务  流水线 多分支流水线 API  计算节点管理  静态 动态   大纲  日志、任务外部存储 权限、认证体系 安全防护 备份、恢复 集成 社区介绍  Gitter \u0026amp;\u0026amp; 邮件组 Meetup 特别兴趣小组(SIG) 基础设施   安装、部署 Jenkins 的版本分为长期支持版(LTS)和每周更新版。\n 安装手册 Docker  插件管理  介绍 仓库 托管  计算节点管理  节点类型  固定 动态(虚拟机、Docker、Kubernetes)  通道  SSH JNLP  标签(label)  表达式   流水线(Pipeline) Jenkins 流水线采用 Groovy 来编写,通常会保存在代码库根目录下名为 Jenkinsfile 的文件中。根据写法不同,分为:脚本式、申明式流水线。\n快速入手,参考:\n 语法生成器 步骤列表 例子 复用 IDE 插件  .left[.footnote[https://linuxsuren.github.io/blog/devops/jenkins/pipeline/]]\n多分支流水线(Multi-branch Pipeline) 对于使用 Git 作为代码仓库的团队来说,Jenkins 的多分支流水线能够充分地利用 Git 的分支功能,简化重复的工作。简单来说,它可以根据既定的策略动态地创建、删除流水线。而对于部分 Git 服务,还能很好地支持 Pull Request 的流水线构建。\nAPI Jenkins 的大部分操作支持通过 HTTP API 进行调用,可以返回 JSON、XML 的数据格式。\nclass: center, middle\n社区介绍 Jenkins Community\n沟通交流 推荐的交流途径包括:Gitter、Google 邮件组。不同的主题,会有不同频道、组。\n 普通用户(中文、英文) 开发者 特别兴趣小组  .left[.footnote[https://remarkjs.com]]\nMeetup 线上、线下交流活动。每年,在国内很多城市都组织一些线下交流活动。\n 北京 西安 上海 深圳  分享的主题通常包括:特性介绍、案例分享、工作坊等。\n.left[.footnote[https://www.meetup.com/Beijing-Jenkins-Area-Meetup/]]\nclass: center, middle\n特别兴趣小组 Jenkins Special Interest Groups\n.left[.footnote[SIGs]]\n??? here is the note\n中文本地化 致力于改善 Jenkins 的中文用户的使用体验。涉及的范围包括: Jenkins 核心和插件以及官方网站。欢迎加入!\n 官网(Jenkins、JX) Jenkins 及其插件 Jenkins 官方微信公众号 定期会议  .footnote[Chinese Localization]\n宣传与推广 平台 实训项目-1 热身练习 1. 构建 Maven 项目 2. 制品归档 3. 构建 Docker 镜像 4. 参数化构建,指定 Docker 镜像 Tag\n进阶练习 1. 构建 Maven 项目并发布到 Nexus 2. 使用私有 Nexus 中的依赖进行构建 3. 构建 Docker 镜像并推送到 Harbor 4. 构建 Heml Charts 并推送到 Chartmuseum\n.footnote[实训 demo 项目]\n实训项目-2 基于 Kubernetes 的持续交付 1. 基于 deployment 进行交付 2. 基于 helm charts 进行交付\n.footnote[实训 demo 项目]\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/event/readme/",
        "title": "",
        "type": "event",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 该目录下,保存 Jenkins 社区相关的活动内容。文件格式为 Markdown,包含的头信息(字段)包括如下:\n type 活动类型,目前只支持 meetup(必需) city 活动举办地(必需) hostDate 活动时间(必需) year 活动所属年份,用于按年度分开展示(必需) poster 活动海报(必需) topic 活动主题 speakers 分享人,数组格式 sponsors 赞助商(公司、社区等),数组格式 abstract 活动简介 agenda 活动日程  time 时间 item 事项  status 活动状态  发起活动 希望发起活动的人或者组织,请按照如上格式写入一个 Markdown 文件中,并打开一个 Pull Request 到该仓库,等待审核。\n分享人 对某个活动感兴趣的同学,请在目录 content/speaker 下以 JSON 格式增加自己的个人信息,文件名为 GitHub 账户 ID。然后在您感兴趣的活动中的 speakers 下添加您的 ID。\n赞助 如果您所在的企业、出版社、社区等对某个活动感兴趣,打算给 Jenkins 开源社区活动一定的赞助,请参考“分享人”的流程添加自己的信息。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/event/beijing-2019-04-20/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/cloud-native-community-day.jpeg"
    },
    {
        "uri": "https://jenkins-zh.cn/event/beijing-2019-06-22/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/ci-cd.jpeg"
    },
    {
        "uri": "https://jenkins-zh.cn/event/beijing-2019-07-27/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/ci-cd.jpeg"
    },
    {
        "uri": "https://jenkins-zh.cn/event/beijing-2019-08-24/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/kaiyuan.jpg"
    },
    {
        "uri": "https://jenkins-zh.cn/event/beijing-2019-10-25/",
        "title": "",
        "type": "hackthon",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 资源需求 志愿者 五名志愿者,负责场地秩序维护、活动事项问题解答等工作。具体包括如下: * 拍照/摄像 1~2名 * 签到、场地布置 1~2名 * 文案、宣传 1~2名\n志愿者福利: * 免费参加自本活动启动时一年内的所有活动 * 活动纪念品 * 赠送与本社区有合作关系的其他公司或者社区组织的活动门票\n技术教练 Kubernetes、Jenkins 领域的技术教练(导师)各两名,负责参赛选手过程中的问题解答,服务器资源 维护管理。\n技术教练福利: * 免费参加自本活动启动时一年内的所有活动 * 活动纪念品 * 赠送与本社区有合作关系的其他公司或者社区组织的活动门票\n服务器 Kubernetes 集群,1个 master 节点,5个计算节点。每个节点的配置为:4C+8G内存+40G硬盘。\n另外,需要提供的还有:PVC。\n其他物资 贴纸、鼠标垫、书、T恤、雨伞、笔、马克杯、背包等。\n睡袋、毯子。\n合作 合作的社区或者企业,需要共同宣传本次活动,形式不限。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/hackthon.png"
    },
    {
        "uri": "https://jenkins-zh.cn/event/shanghai-2019-09/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": "/images/meetup/shanghai.jpeg"
    },
    {
        "uri": "https://jenkins-zh.cn/meeting/",
        "title": "",
        "type": "meeting",
1852
        "date": "2020-03-04 00:00:00 +0000 UTC",
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
        "tags": [],
        "description": "",
        "content": " Jenkins 中文社区例会,每个双周周三(遇到法定节假日时延后)的 21:00 进行。准备参加的小伙伴,需要提前安装好 zoom 软件, 然后点击 https://zoom.us/j/691718976 即可进入会议。\n注意事项⚠️  要发言的小伙伴要提前找好一个相对比较安静的环境 不发言的时候,及时关闭麦克风🎤 例会是讨论社区的事情,而不是技术分享  如何接入? 可以下载桌面客户端,或者移动客户端来接入会议。\n如果不想下载软件,或者由于某种原因无法访问国外网站的,可以点击此处打开国内的 Web 客户端, 直接在浏览器中参加会议。\n会议 ID 为:691718976\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "字段说明: * 包含 logo 的才会显示出来\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/alauda/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/harmony-cloud/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/hogwarts/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/jingdongyun/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/junzi/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/kaiyuanshe/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/pinganyun/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/partner/press/",
        "title": "",
        "type": "partner",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/sponsor/alauda/",
        "title": "",
        "type": "sponsor",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tutorial/",
        "title": "",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
1996 1997
        "tags": [],
        "description": "",
1998
        "content": "本教程由 Jenkins 中文社区发起,并由每一位 Jenkins 的爱好者、用户或者开发者共同维护。\n文档以 Markdown 的格式来编写,并采用 Hugo 生成静态网站,每当该仓库的 master 分支发生变化后,就会由 hugo-plugin 构建并自动上线。\n每一位贡献者,都需要通过发起 Pull Request 的方式来帮忙完善、改进该 Jenkins 中文教程。\n在每个 Markdown 文件的头部,我们以 YAML 格式附加了一些信息,支持的字段如下:\n   字段名称 说明     type 固定值:tutorial   title 教程标题(必填项)   toc 是否显示目录结构,为 true 时显示   author 作者,首位编写本教程的人,值为 GitHub ID(必填项)   editors 协作者,作者以外的所有完善过本教程的人,值为 GitHub ID   references 本教程涉及的参考资料链接,包括的字段:name、link    ",
1999 2000 2001 2002 2003
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2004
    {
2005 2006 2007 2008
        "uri": "https://jenkins-zh.cn/wechat/articles/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
2009 2010
        "tags": [],
        "description": "",
2011
        "content": " 这里存放的是 Jenkins 官方微信公众号文章,文件采用 Markdown 格式,但包含一些必要的描述性字段。文章的校对、审核、排期等都通过 Pull Request 来完成。PR 合并后会发布到 Jenkins 中文社区网站。\n目录 文章以发布的排期来存放,层级为:年份/月份。如果月份为个位数的话,要以0开头,例如:01。\n以文章的文件名前缀作为图片的目录,例如:文章的文件名为 2019-01-01-sample.md,我们需要在同级目录下创建文件夹 2019-05-01-sample , 并在里面保存当前文章中的图片(封面、插图等)。\n排期 为了尽可能满足你期望的发布日期,可以自行选择,但同时需要满足如下的条件:\n 为保障大家有足够的时间进行 Review,建议排到一周以后 工作日 避免同一天有相同类型的文章  文件名 文件名前缀为“年月日”,中间部分需要以英文来描述,英文字母需要全部小写。例如:2019-01-01-sample.md。\n字段 文件中的字段,是为了描述文章相关的必要信息。具体的说明请参考:sample.md。\n",
2012
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2013 2014 2015 2016
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2017
    {
2018 2019 2020 2021
        "uri": "https://jenkins-zh.cn/weibo/weibo-operating-charter/",
        "title": "",
        "type": "weibo",
        "date": "0001-01-01 00:00:00 +0000 UTC",
2022
        "tags": [],
2023 2024 2025
        "description": "",
        "content": " Jenkins 官方微博运营章程 该文旨在说明 Jenkins 官方微博运营规范。\n需要讨论的问题  运营者选取形式\n志愿或其他形式 发布的内容\n同步微信公众号/同步 Twitter/类似其他机构官方账号与粉丝互动 发布内容的形式(分享/原创长微博)\n微博官方提供了分享微博和发布长微博的接口。 发布的时间/频率 微博的自动化\n 维护 Jenkins weibo plugin,需要进一步测试(较长时间无人维护,可能存在接口变动)\n 开发新的插件  对评论的回复  ",
        "auhtor": "",
2026 2027
        "translator": "",
        "original": "",
2028
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2029
    },
2030
    {
2031 2032 2033 2034
        "uri": "https://jenkins-zh.cn/tutorial/api/",
        "title": "API",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
2035 2036
        "tags": [],
        "description": "",
2037
        "content": "API\n",
2038
        "auhtor": "",
2039 2040
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2041 2042 2043
        "poster": ""
    },
    {
2044 2045
        "uri": "https://jenkins-zh.cn/tags/ai/",
        "title": "Ai",
2046
        "type": "tags",
2047
        "date": "2019-04-22 00:00:00 +0000 UTC",
2048 2049 2050 2051
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2052 2053
        "translator": "",
        "original": "",
2054 2055
        "poster": ""
    },
2056
    {
2057 2058 2059 2060 2061 2062 2063 2064
        "uri": "https://jenkins-zh.cn/tutorial/best-practice/android/",
        "title": "Android 应用构建",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "本教程将展示 Jenkins 如何使用 Jenkins 和 Gradle 构建一个简单的 Android 应用程序。并涵盖打包,测试,交付的过程。\n",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2065 2066
        "translator": "",
        "original": "",
2067
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2068 2069 2070
    },
    {
        "uri": "https://jenkins-zh.cn/tags/ansible/",
2071
        "title": "Ansible",
2072
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2073
        "date": "2019-05-20 00:00:00 +0000 UTC",
2074 2075 2076 2077 2078 2079 2080 2081
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2082
    {
2083 2084
        "uri": "https://jenkins-zh.cn/tags/asktheexperts/",
        "title": "Asktheexperts",
2085
        "type": "tags",
2086
        "date": "2019-09-15 00:00:00 +0000 UTC",
2087 2088 2089 2090 2091 2092
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2093
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2094
    },
2095
    {
2096 2097
        "uri": "https://jenkins-zh.cn/tags/aws/",
        "title": "Aws",
2098
        "type": "tags",
2099
        "date": "2019-08-23 00:00:00 +0000 UTC",
2100 2101 2102 2103 2104 2105 2106 2107
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2108
    {
2109 2110 2111 2112 2113 2114 2115 2116
        "uri": "https://jenkins-zh.cn/tags/benchmark/",
        "title": "Benchmark",
        "type": "tags",
        "date": "2019-07-04 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2117 2118
        "translator": "",
        "original": "",
2119
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2120 2121
    },
    {
2122 2123 2124 2125 2126 2127 2128 2129
        "uri": "https://jenkins-zh.cn/tags/blog/",
        "title": "Blog",
        "type": "tags",
        "date": "2020-01-10 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2130 2131
        "translator": "",
        "original": "",
2132
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2133 2134
    },
    {
2135 2136 2137 2138
        "uri": "https://jenkins-zh.cn/tags/blueocean/",
        "title": "Blueocean",
        "type": "tags",
        "date": "2019-08-15 00:00:00 +0000 UTC",
2139
        "tags": [],
2140 2141
        "description": "",
        "content": "",
2142 2143 2144
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2145 2146
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2147
    {
2148 2149 2150 2151 2152 2153 2154 2155
        "uri": "https://jenkins-zh.cn/tags/c-stat/",
        "title": "C Stat",
        "type": "tags",
        "date": "2019-11-18 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2156 2157
        "translator": "",
        "original": "",
2158
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2159 2160
    },
    {
2161 2162 2163 2164 2165 2166 2167 2168
        "uri": "https://jenkins-zh.cn/categories/",
        "title": "Categories",
        "type": "categories",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2169 2170
        "translator": "",
        "original": "",
2171
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2172
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2173
    {
2174 2175
        "uri": "https://jenkins-zh.cn/tags/cd/",
        "title": "Cd",
2176
        "type": "tags",
2177
        "date": "2020-02-17 00:00:00 +0000 UTC",
2178 2179 2180 2181
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2182 2183 2184
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2185
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2186
    {
2187 2188
        "uri": "https://jenkins-zh.cn/tags/cdf/",
        "title": "Cdf",
2189
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2190
        "date": "2019-05-13 00:00:00 +0000 UTC",
2191 2192 2193 2194
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2195 2196 2197 2198
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2199
    {
2200 2201 2202 2203 2204 2205 2206 2207
        "uri": "https://jenkins-zh.cn/tags/cdsummit/",
        "title": "Cdsummit",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2208 2209
        "translator": "",
        "original": "",
2210
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2211
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2212
    {
2213 2214 2215
        "uri": "https://jenkins-zh.cn/tags/cfp/",
        "title": "Cfp",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2216
        "date": "2019-05-13 00:00:00 +0000 UTC",
2217 2218 2219 2220
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2221 2222
        "translator": "",
        "original": "",
2223
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2224
    },
2225
    {
2226 2227 2228
        "uri": "https://jenkins-zh.cn/tags/ci/",
        "title": "Ci",
        "type": "tags",
2229
        "date": "2020-02-17 00:00:00 +0000 UTC",
2230 2231 2232 2233
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2234 2235
        "translator": "",
        "original": "",
2236
        "poster": ""
2237
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2238
    {
2239 2240 2241 2242 2243 2244 2245 2246
        "uri": "https://jenkins-zh.cn/tags/ci-cd/",
        "title": "Ci/Cd",
        "type": "tags",
        "date": "2020-01-10 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2247 2248
        "translator": "",
        "original": "",
2249
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2250
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2251
    {
2252 2253
        "uri": "https://jenkins-zh.cn/tags/cicd/",
        "title": "Cicd",
2254
        "type": "tags",
2255
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2256
        "tags": [],
2257 2258
        "description": "",
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2259 2260 2261 2262
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2263 2264
    },
    {
2265 2266
        "uri": "https://jenkins-zh.cn/tags/cli/",
        "title": "Cli",
2267
        "type": "tags",
2268
        "date": "2019-10-25 00:00:00 +0000 UTC",
2269 2270 2271 2272
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2273 2274 2275
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2276
    },
2277
    {
2278 2279 2280 2281 2282 2283 2284 2285
        "uri": "https://jenkins-zh.cn/tags/cloud-native/",
        "title": "Cloud Native",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2286 2287
        "translator": "",
        "original": "",
2288
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2289 2290
    },
    {
2291 2292 2293 2294 2295 2296 2297 2298
        "uri": "https://jenkins-zh.cn/tags/cloudbees/",
        "title": "Cloudbees",
        "type": "tags",
        "date": "2019-12-11 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2299 2300
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2301 2302 2303
        "poster": ""
    },
    {
2304 2305
        "uri": "https://jenkins-zh.cn/tags/community/",
        "title": "Community",
2306
        "type": "tags",
2307
        "date": "2020-02-18 00:00:00 +0000 UTC",
2308 2309 2310 2311 2312 2313
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2314
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2315 2316
    },
    {
2317 2318
        "uri": "https://jenkins-zh.cn/tags/continuous-integration/",
        "title": "Continuous Integration",
2319
        "type": "tags",
2320
        "date": "2019-04-03 00:00:00 +0000 UTC",
2321 2322 2323 2324 2325 2326
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2327
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2328 2329
    },
    {
2330 2331
        "uri": "https://jenkins-zh.cn/tags/contributing/",
        "title": "Contributing",
2332
        "type": "tags",
2333
        "date": "2019-04-08 00:00:00 +0000 UTC",
2334 2335 2336 2337 2338 2339
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2340
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2341
    },
2342
    {
2343 2344
        "uri": "https://jenkins-zh.cn/tags/contributors/",
        "title": "Contributors",
2345
        "type": "tags",
2346
        "date": "2019-11-22 00:00:00 +0000 UTC",
2347 2348 2349 2350 2351 2352 2353 2354
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2355
    {
2356 2357
        "uri": "https://jenkins-zh.cn/tags/contributorsummit/",
        "title": "Contributorsummit",
2358
        "type": "tags",
2359
        "date": "2019-09-15 00:00:00 +0000 UTC",
2360 2361 2362 2363
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2364
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2365 2366 2367
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2368
    {
2369 2370
        "uri": "https://jenkins-zh.cn/tags/core/",
        "title": "Core",
2371
        "type": "tags",
2372
        "date": "2019-07-15 00:00:00 +0000 UTC",
2373 2374 2375 2376 2377
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2378 2379 2380 2381
        "original": "",
        "poster": ""
    },
    {
2382 2383 2384 2385 2386 2387 2388 2389
        "uri": "https://jenkins-zh.cn/tags/coverage/",
        "title": "Coverage",
        "type": "tags",
        "date": "2019-05-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2390 2391
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2392
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2393
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2394
    {
2395 2396 2397 2398 2399 2400 2401 2402
        "uri": "https://jenkins-zh.cn/tags/credentials/",
        "title": "Credentials",
        "type": "tags",
        "date": "2019-07-04 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2403 2404 2405 2406
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2407
    {
2408 2409
        "uri": "https://jenkins-zh.cn/tags/developer/",
        "title": "Developer",
2410
        "type": "tags",
2411
        "date": "2019-11-22 00:00:00 +0000 UTC",
2412 2413 2414 2415
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2416
        "translator": "",
2417
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2418
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2419 2420
    },
    {
2421 2422 2423
        "uri": "https://jenkins-zh.cn/tags/devops/",
        "title": "Devops",
        "type": "tags",
2424
        "date": "2020-03-02 00:00:00 +0000 UTC",
2425 2426 2427 2428
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2429
        "translator": "",
2430
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2431 2432 2433
        "poster": ""
    },
    {
2434 2435
        "uri": "https://jenkins-zh.cn/tags/devops-jenkins/",
        "title": "Devops Jenkins",
2436
        "type": "tags",
2437
        "date": "2019-09-23 00:00:00 +0000 UTC",
2438 2439 2440 2441 2442
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2443 2444
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2445
    },
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
    {
        "uri": "https://jenkins-zh.cn/tags/devops-%E6%8C%87%E6%A0%87/",
        "title": "Devops 指标",
        "type": "tags",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/devops-%E7%8A%B6%E6%80%81/",
        "title": "Devops 状态",
        "type": "tags",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/devops-%E7%8A%B6%E6%80%81%E6%8A%A5%E5%91%8A/",
        "title": "Devops 状态报告",
        "type": "tags",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2485
    {
2486 2487 2488 2489 2490 2491 2492 2493
        "uri": "https://jenkins-zh.cn/tags/devopsworld2019/",
        "title": "Devopsworld2019",
        "type": "tags",
        "date": "2019-09-15 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2494 2495
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2496 2497 2498
        "poster": ""
    },
    {
2499 2500 2501
        "uri": "https://jenkins-zh.cn/tags/docker/",
        "title": "Docker",
        "type": "tags",
2502
        "date": "2020-02-21 00:00:00 +0000 UTC",
2503
        "tags": [],
2504 2505
        "description": "",
        "content": "",
2506 2507 2508
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2509 2510 2511
        "poster": ""
    },
    {
2512 2513 2514 2515 2516 2517 2518 2519
        "uri": "https://jenkins-zh.cn/tags/docs/",
        "title": "Docs",
        "type": "tags",
        "date": "2019-05-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2520 2521
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2522 2523 2524
        "poster": ""
    },
    {
2525 2526
        "uri": "https://jenkins-zh.cn/tags/documentation/",
        "title": "Documentation",
2527
        "type": "tags",
2528
        "date": "2019-11-22 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2529
        "tags": [],
2530 2531 2532
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2533 2534 2535
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2536
    },
2537
    {
2538 2539
        "uri": "https://jenkins-zh.cn/tags/elections/",
        "title": "Elections",
2540
        "type": "tags",
2541
        "date": "2019-11-12 00:00:00 +0000 UTC",
2542 2543 2544 2545 2546 2547 2548 2549
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2550
    {
2551 2552
        "uri": "https://jenkins-zh.cn/tags/electron/",
        "title": "Electron",
2553
        "type": "tags",
2554
        "date": "2019-03-13 00:00:00 +0000 UTC",
2555
        "tags": [],
2556 2557 2558
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2559
        "translator": "",
2560
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2561
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2562
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2563
    {
2564 2565
        "uri": "https://jenkins-zh.cn/tags/events/",
        "title": "Events",
2566
        "type": "tags",
2567
        "date": "2020-02-18 00:00:00 +0000 UTC",
2568 2569 2570 2571
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2572
        "translator": "",
2573
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2574 2575 2576
        "poster": ""
    },
    {
2577 2578 2579 2580 2581 2582 2583 2584
        "uri": "https://jenkins-zh.cn/tags/evergreen/",
        "title": "Evergreen",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2585 2586 2587 2588
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2589
    {
2590 2591 2592 2593 2594 2595 2596 2597 2598
        "uri": "https://jenkins-zh.cn/tags/flagger/",
        "title": "Flagger",
        "type": "tags",
        "date": "2019-04-26 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2599 2600 2601 2602
        "original": "",
        "poster": ""
    },
    {
2603 2604
        "uri": "https://jenkins-zh.cn/tags/general/",
        "title": "General",
2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615
        "type": "tags",
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
2616 2617
        "uri": "https://jenkins-zh.cn/tags/git/",
        "title": "Git",
2618
        "type": "tags",
2619
        "date": "2019-06-17 00:00:00 +0000 UTC",
2620 2621 2622 2623 2624
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2625 2626 2627
        "original": "",
        "poster": ""
    },
2628
    {
2629 2630
        "uri": "https://jenkins-zh.cn/tags/git-secrets/",
        "title": "Git Secrets",
2631
        "type": "tags",
2632
        "date": "2019-11-29 00:00:00 +0000 UTC",
2633 2634 2635 2636 2637 2638 2639 2640
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2641
    {
2642 2643 2644 2645 2646 2647 2648 2649
        "uri": "https://jenkins-zh.cn/tags/gitlab/",
        "title": "Gitlab",
        "type": "tags",
        "date": "2019-09-11 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
2650
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2651 2652
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2653
    },
2654
    {
2655 2656
        "uri": "https://jenkins-zh.cn/tags/governance/",
        "title": "Governance",
2657
        "type": "tags",
2658
        "date": "2019-11-12 00:00:00 +0000 UTC",
2659 2660 2661 2662 2663 2664 2665 2666
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2667
    {
2668 2669 2670
        "uri": "https://jenkins-zh.cn/tags/gsoc/",
        "title": "Gsoc",
        "type": "tags",
2671
        "date": "2020-02-18 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2672
        "tags": [],
2673 2674 2675
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2676 2677 2678
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2679
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2680
    {
2681 2682 2683
        "uri": "https://jenkins-zh.cn/tags/gsoc2019/",
        "title": "Gsoc2019",
        "type": "tags",
2684
        "date": "2020-02-18 00:00:00 +0000 UTC",
2685
        "tags": [],
2686 2687 2688
        "description": "",
        "content": "",
        "auhtor": "",
2689 2690 2691 2692
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2693
    {
2694 2695 2696 2697 2698 2699 2700 2701 2702
        "uri": "https://jenkins-zh.cn/tags/hacktoberfest/",
        "title": "Hacktoberfest",
        "type": "tags",
        "date": "2019-11-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2703
        "original": "",
2704
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2705
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2706
    {
2707 2708 2709 2710 2711 2712 2713 2714 2715
        "uri": "https://jenkins-zh.cn/tags/installers/",
        "title": "Installers",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2716 2717 2718 2719
        "original": "",
        "poster": ""
    },
    {
2720 2721
        "uri": "https://jenkins-zh.cn/tags/istio/",
        "title": "Istio",
2722
        "type": "tags",
2723
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2724
        "tags": [],
2725 2726
        "description": "",
        "content": "",
2727
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2728 2729
        "translator": "",
        "original": "",
2730
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2731
    },
2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744
    {
        "uri": "https://jenkins-zh.cn/tags/j-%E8%BD%AC%E6%8D%A2%E6%9B%B2%E7%BA%BF/",
        "title": "J 转换曲线",
        "type": "tags",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2745
    {
2746 2747
        "uri": "https://jenkins-zh.cn/tags/jacoco/",
        "title": "Jacoco",
2748
        "type": "tags",
2749
        "date": "2019-05-22 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2750
        "tags": [],
2751
        "description": "",
2752
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2753 2754 2755
        "auhtor": "",
        "translator": "",
        "original": "",
2756
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2757
    },
2758
    {
2759 2760 2761 2762
        "uri": "https://jenkins-zh.cn/tags/java/",
        "title": "Java",
        "type": "tags",
        "date": "2019-12-19 00:00:00 +0000 UTC",
2763
        "tags": [],
2764 2765 2766
        "description": "",
        "content": "",
        "auhtor": "",
2767 2768 2769 2770
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2771
    {
2772 2773 2774 2775
        "uri": "https://jenkins-zh.cn/tags/java11/",
        "title": "Java11",
        "type": "tags",
        "date": "2019-07-15 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2776
        "tags": [],
2777 2778 2779
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2780 2781
        "translator": "",
        "original": "",
2782
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2783 2784
    },
    {
2785 2786 2787
        "uri": "https://jenkins-zh.cn/tags/jenkins/",
        "title": "Jenkins",
        "type": "tags",
2788
        "date": "2020-02-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2789
        "tags": [],
2790 2791
        "description": "",
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2792 2793 2794
        "auhtor": "",
        "translator": "",
        "original": "",
2795
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2796
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2797
    {
2798 2799 2800
        "uri": "https://jenkins-zh.cn/about/meetups/",
        "title": "Jenkins Area Meetup",
        "type": "about",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2801
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2802
        "tags": [],
2803 2804
        "description": "Jenkins 中国本地活动",
        "content": " 各地活动组织者    城市 组织者 邮箱     北京  Rick  📭    希望在当地组织活动? 我们非常欢迎全国各地的 Jenkins 爱好者积极地承担起在当地组织 Jenkins 线下活动的责任。为了能够保证我们社区的健康发展,申请人需要清楚、明确地了解下面的权益和义务:\n权益 组织线下活动是比较累但有趣的工作,要举办一次好的活动,需要投入不少的精力来筹划、安排、宣传等。因此,活动组织者将会享受到如下的权益:\n 优先获得合作社区(公司)举办的会议门票 社区协调场地、茶歇以及礼品等赞助 丰富的人脉资源 使用社区邮箱 其他社区提供的激励  义务 在享受权益的前提,必须要尊重和遵守我们的义务要求:\n 积极主动,有自驱力 一年内,平均每月要参加一次社区线上例会(如有其他事情耽搁,可以在会议记录中备注) 所在地一年内至少要举办一次线下活动  活动形式 我们欢迎每一位愿意一起合作、组织的个人、企业、社区,形式包括但不局限于:\n 案例、经验分享 工作坊,实际操作演练 活动拍照、录像 茶歇、场地赞助 礼品、奖品赞助  下面是目前收集到的,在国内组织过 Meetup 的城市。\n  北京   上海   西安   杭州   成都   深圳   广州   ",
2805 2806 2807
        "auhtor": "",
        "translator": "",
        "original": "",
2808
        "poster": ""
2809
    },
2810
    {
2811 2812 2813 2814
        "uri": "https://jenkins-zh.cn/tags/jenkins-ci/",
        "title": "Jenkins Ci",
        "type": "tags",
        "date": "2019-11-18 00:00:00 +0000 UTC",
2815 2816 2817 2818 2819 2820
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
2821
        "poster": ""
2822
    },
2823
    {
2824 2825 2826
        "uri": "https://jenkins-zh.cn/tags/jenkins-x/",
        "title": "Jenkins X",
        "type": "tags",
2827
        "date": "2020-02-17 00:00:00 +0000 UTC",
2828
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2829 2830 2831
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2832 2833
        "translator": "",
        "original": "",
2834
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2835
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2836
    {
2837 2838 2839 2840
        "uri": "https://jenkins-zh.cn/",
        "title": "Jenkins 中文社区",
        "type": "page",
        "date": "2019-09-07 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2841
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2842
        "description": "",
2843
        "content": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2844
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2845 2846
        "translator": "",
        "original": "",
2847
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2848
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2849
    {
2850 2851 2852
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-kubecon-cn/",
        "title": "Jenkins 中文社区邀您来上海共同参与2019年的国际开源盛宴",
        "type": "wechat",
2853
        "date": "0001-01-01 00:00:00 +0000 UTC",
2854
        "tags": ["cloud-native", "kubernetes", "kubecon", "ci", "cd", "cdsummit"],
2855
        "description": "",
2856 2857
        "content": " KubeCon + CloudNativeCon | Open Source Summit | 持续交付峰会 中国2019 2019年4月10日,旧金山 - Linux基金会是一家以开源促进大众创新的非营利组织,今天公布将于2019年6月24至26日在中国上海举行的 KubeCon + CloudNativeCon + Open Source Summit 中国2019日程。\nOpen Source Summit 中国2019前身为 LinuxCon + ContainerCon + CloudOpen 中国(LC3),是开源社区寻求合作、共享信息、了解当今最有影响力的开源技术和议题的重要平台,包括:云原生、无服务器、微服务、物联网、人工智能、网络、Linux 等。\n2019年,首次将Open Source Summit中国和KubeCon + CloudNativeCon中国整合成一项活动,只需购票一次即可参加KubeCon + CloudNativeCon + Open Source Summit中国。\n本届持续交付峰会将由 CNCF 承办在大会的第 0 天举行,汇聚了各个开源 CI/CD 社区。\nJenkins 中文社区成员在大会上将进行分享 Jenkins 中文社区成员夏润泽(北京优帆科技有限公司)将在大会上作为演讲嘉宾为大家带来主题为 Jenkins X 在 kubernetes 之上运行的无服务器 Jenkins 的分享。\nJenkins 中文社区邀您参与社区共同成长 在开源盛会开展的同时,我们希望能够与更多的小伙伴们一同在线上完善开源社区氛围、线下深度互动,努力构建一个有内容、有态度的优质技术社区。\n",
        "auhtor": "runzexia",
2858 2859
        "translator": "",
        "original": "",
2860
        "poster": ""
2861 2862
    },
    {
2863 2864 2865
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-16-localization-zh-cn-plugin/",
        "title": "Jenkins 中文语言包",
        "type": "wechat",
2866 2867
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
2868 2869 2870
        "description": "Jenkins 中文版本升级通知",
        "content": "部分 Jenkins 中文用户可能已经发现,在最近升级 Jenkins 版本,或下载较新的 Jenkins 后,界面上很多部分显示的是英文。对此,我简单介绍一下原因以及如何安装中文插件。\n各种语言的本地化资源文件都是集中存放在 Jenkins Core 及其插件中,这对于要做本地化贡献的人来说,需要向很多代码仓库中提交 PR。最明显的一个现象就是,这些仓库不一定都会有熟悉中文的维护者,因此导致 PR 无法真实、及时地进行 Review 以及合并发布。基于以上的考虑,我开发了简体中文插件,并从 Jenkins 2.145 版本中把大部分的中文本地化资源文件迁移到了该插件中。而且,最终会对 Jenkins Core 以及流行的插件中所有的中文本地化资源文件进行迁移。\n安装简体中文插件也很简单,只要在 Jenkins 的插件管理界面上,搜索*中文*就能找到该插件。安装并重启后就能看到中文界面。\n更多细节请查看 变更记录 。欢迎对中文本地化工作感兴趣的同学加入我们!\n",
        "auhtor": "linuxsuren",
2871 2872 2873 2874 2875
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
2876 2877 2878
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-30-k8s-jenkins-secet-agent/",
        "title": "Jenkins 和 Kubernetes -云上的神秘代理",
        "type": "wechat",
2879
        "date": "0001-01-01 00:00:00 +0000 UTC",
2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892
        "tags": ["jenkinsworld", "jenkinsworld2018", "cloud-native", "kubernetes"],
        "description": "运行在 K8S 上的 Jenkins 动态节点",
        "content": " 最近我们构建和部署服务的方式与原来相比简直就是突飞猛进,像那种笨拙的、单一的、用于构建单体式应用程序的方式已经是过去式了。我们努力了这么久,终于达到了现在的效果。现在的应用为了提供更好的拓展性和可维护性,都会去拆解成各种相互依赖小、解耦性强的微服务,这些服务有各自的依赖和进度。如果你想去构建你所负责的服务,那么从一开始,就应该使用 CI/CD 的方式;当然,如果你走上了这条路, Jenkins 就是你的良师益友。\n如果你是做微服务的话,那让我们在开始之前先花些时间想一想。如果你只在 Jenkins 上构建单体式应用程序,那你肯定每天都会运行很多 Jenkins job, 而且还要不厌其烦地运行很多次。所以,我们应该好好想清楚怎么样来做出一些改变来适应这种事情。其实只需要付出一些努力,Jenkins 就可以帮我们很好地解决这种事情。\n我的 Jenkins 的进阶之路 作为一个 Devops 从业者,我遇到的最大问题是如何管理并优化自己的 Jenkins agent 结构。如果只是用 Jenkins 玩玩,实验性地跑一些流水线,那根本不用考虑 agent 的事情。如果你每天要跑成百上千条流水线的话,那考虑怎么去做优化就是一件非常非常重要的事情了。在 Jenkins 进阶之路中,我也尝试了各种不同的方式来寻找最好的 Jenkins agent 的使用方式。相信如果你也和我一样经历过,那下面这些事情你一定会很熟悉喽。\n下面是我在这些年中使用 Jenkins 的各个阶段.\n 所有的构建都在 master 节点上跑,在这个节点上运行所有的组件. (我给这个阶段起了个可爱的名字, Hello Jenkins) 创建一个 Jenkins EC2 代理,并且在这个代理上运行所有的构建,怎么说呢, 就是大而全,这个节点什么都能做。如果需要同时做多条任务,那就把这个大而全的节点克隆一份。 (这个阶段我起的名字是 Monster Agent.) 为每种服务创建不同的 Jenkins EC2 的节点 (这个阶段我起的名字叫做 Snowflake Agent.) 在容器中运行流水线的所有步骤。 打个比方,在 Jenkins 中使用 Docker Plugin 这个插件将代理挂载到容器中,或者使用 multi-stage Dockerfiles 把所有构建,测试打包的流程都封装起来。这两种方法都是很好的容器抽象化的开端,并且允许您轻松地将制品从一个容器复制到另一个容器。当然了,每一种方法都是需要访问 Docker engine 的。为了让我的 Jenkins 代理能够正常工作,现在我用以下几种方式来管理 docker host 在我的 Jenkins 主容器中运行一个Docker engine - Docker in Docker (DinD) 把主机上的 Docker socket 挂载到我的容器中来,让我的容器能够以 sidecar 的方式运行。 为 Jenkins 主服务器配置单个外部 EC2 Docker 主机,以用于在容器中启动构建 使用 EC2 插件和包含 Docker Engine 的 AMI 动态启动代理,然后运行多阶段 Dockerfile 中的所有步骤  以上这些阶段各有利弊,但都是为了让我们从管理 Jenkins 节点中解放出来。不过,最近我又进阶到了另外一个阶段:Jenkins on Kubernetes.\n一旦你在 Jenkins 中把构建节点和 job 都容器化了的话,迁移工作平台将变的十分简单易行。在这里郑重声明一下,在我用这个方法之前我一直没有接触过 Kubernetes,一次也没有。也就是说,在 Google Cloud Platform(GCP)GKE 中创建 Kubernetes 集群,使用 Helm Chart启动 Jenkins master ,并在 Kubernetes 集群中的 Jenkins 代理中运行构建是非常简单的。\n流水线脚本中启动 K8s 中的代理 这篇文章就是为了向大家说明,如何配置 Jenkins 才能使流水线脚本能够在 K8s 集群中启动 Jenkins 节点。首先你要先安装 Kubernetes plugin 这个插件。有意思的是,当我用 Helm chart 来安装我的 Jenkins 时,安装好的 Jenkins 里面已经有了这个插件。还有一个前提,是你启动的 Jenkins 节点要和你的 Jenkins master 在同一个 K8s 集群里。\n一旦在 K8s 中运行了你的 Jenkins master 节点,那只需要再简单地配置几步,就能启动一个小构建啦。\n配置 Jenkins Master 为了保证 Jenkins 能够访问 K8s 集群的资源,首先你需要按照以下步骤创建一些凭据:\n 进入 Jenkins 的 UI 界面,点击左边导航栏里的凭据链接 点击 Stores scoped to Jenkins 列表下 global 中的 Add credentials (将鼠标悬停在链接旁边即可看到箭头) 点击添加凭证 写好 Kubernetes Service Account 将范围设置为全局 点击 OK 按钮  这样之后 Jenkins 就可以使用这个凭据去访问 K8s 的资源啦\n在 Jenkins Master 中配置云 下一步就是在 Jenkins 中设置云的配置\n 进入 Jenkins UI 界面,点击 系统管理 → 系统设置 进入管理界面后查找 『云』,一般在下面,然后点击 『新增一个云』,选择 kubernetes 类型 然后这些是必填的参数 Name: 这个自定义, 默认的是kubernetes Kubernetes URL: https://kubernetes.default- 这个一般是从你的 service account 自动配置的 Kubernetes Namespace: 一般是 default 除非你要在一个特殊的命名空间 ,否则不要动他 Credentials: 选择上一步你创建的凭据 Jenkins URL: http://\u0026lt;your_jenkins_hostname\u0026gt;:8080 Jenkins tunnel: \u0026lt;your_jenkins_hostname\u0026gt;:5555 - 这就是用来和 Jenkins 启动的 agent 进行交互的端口  你看,只需要几个参数就能在 K8s 集群中启动一些节点了,当然你的环境有需要的话,你也可以做一些其他的调整\n现在你已经可以通过定义一些 pod 来让 Jenkins master 访问 K8s 集群了。pod其实是 K8s 中的概念,在一个 pod 中里面会有一个或者多个容器,它们共享网络还有存储,然后我们可以在这个 pod 中执行一些构建工作。每一个 Jenkins 节点都是作为 K8s pod 来启动的。这个 pod 里面经常都会包含一个默认的 JNLP 的容器,还有一些你在 pod 模板中定义的容器。现在有至少两种方法来定义你的 pod template。\n通过 Jenkins UI 配置一个 pod template  还是老地方 Manage Jenkins → Configure Systems 还是老地方 找到之前配置 Jenkins K8s 的地方 点击 Add Pod Template button 选择 Kubernetes Pod Template 输入下面的值   Name:自定义 Namespace: default-除非你想换个你在上一步自定义的命名空间 Labels: 自定义 - 这个将用来匹配你在 jenkinsfile 中的 label 值 Usage: 如果你想让这个 pod 作为默认节点的话,就选择 \u0026ldquo;Use this node as much as possible\u0026rdquo;, 如果选择 \u0026ldquo;Only build jobs with label matching expressions matching this node\u0026rdquo; 的话 那就是只有在 Jenkins 脚本中定义的label匹配的构建才能使用这个节点 The name of the pod template to inherit from: - 这个可以置空. 现在还用不到 Containers: 你想在这个 pod 中启动的容器,在下面会有详细的介绍 EnvVars: 你想在 pod 中注入的环境变量 下面会有接受 Volumes: 你想在 pod 中挂载的任何一种的卷  需要记住,在一个 pod 中会有不止一个容器,它们都是同生共死的。如果你是用 Helm chart 安装 Jenkins 的话,pod 中就会包含 JNLP 这个容器,这个容器也是 Jenkins agent 中必须包含的。然而为了完成更多的服务的构建,你还需要添加一些其他工具链的容器。\n添加容器模板  进入 Jenkins UI 界面,回到上一步创建 pod template 的地方 点击 Add Container 按钮, 选择 Container Template 输入下面的值 Name:自定义 Docker image: 根据你自己的需求来写,比如你在构建一个用 go 写的应用,那你就可以输入 golang:1.11-alpine3.8 Label: 表明要用在流水线脚本中引用此容器模板的标签字符串 Always pull image: - 如果你想让 pod 启动的时候都去拉取镜像 那就选择这个  你可以保留其他参数的默认值,但是你可以看到该插件可以对你的 pod 以及在其中运行的各个容器进行很详细地控制。你可以通过此插件设置在 Kubernetes pod 配置中的任何值。你还可以通过输入原始 YAML 来注入配置数据。你无需因选项过多而分心,选择配置它们中得一小部分就可以获得工作环境啦。\n您可以单击容器模板中的“添加环境变量”按钮,将环境变量注入特定容器,也可以单击模板中的“添加环境变量”按钮,将环境变量注入所有的容器。 以下环境变量会自动注入默认的 JNLP 容器,来保障它能自动连接到 Jenkins 主服务器:\n JENKINS_URL: Jenkins 网页界面网址 JENKINS_JNLP_URL: Jenkins 特定 slave 中 jnlp 的 url JENKINS_SECRET: 身份验证的密钥 JENKINS_NAME: Jenkins 代理的名称  如果单击“添加卷”按钮,您将看到几个用于添加卷的选项,在这里我使用 Host Path Volume 选项将 docker socket 安装在 pod 中。然后,我可以运行安装了 Docker 客户端的容器,并且来构建和推送 Docker 镜像。\n此时,我们为 Kubernetes 集群创建了一个云配置,并定义了一个由一个或多个容器组成的 pod。现在,我们如何使用它来运行 Jenkins 工作? 很简单,只需要我们在 Jenkins 流水线脚本中通过标签引用 pod 和容器就可以了。 本文中的示例是使用脚本流水线,当然您可以使用声明式流水线语法实现相同的结果:\nnode('test-pod') { stage('Checkout') { checkout scm } stage('Build'){ container('go-agent') { // This is where we build our code. } } }  用 jenkinsfile 来实现相同的功能 通过 UI 配置插件现在看起来是很不错的。但是有一个明显的问题是,配置不能像源代码一样能够进行版本控制和存储。幸运的是,您可以直接在 Jenkinsfile 中创建整个 pod 定义。哈哈,在 Jenkinsfile 中有什么你不能做的???\n可以将 UI 或 YAML 定义中可用的任何配置参数添加到 podTemplate 和 containerTemplate 部分。 在下面的示例中,我已经定义了一个包含两个容器模板的 pod。 pod 标签将会用于节点,表示我们想要启动此 pod 的实例。 直接在节点内定义但没有在容器块中定义的任何步骤,都可以在默认的 JNLP 容器中运行。\n容器块用于表示该容器块内的步骤应在具有给定标签的容器内运行。我已经定义了一个标签为 golang 的容器模板,我将用它来构建 Go 可执行文件,我最终将其打包成 Docker 镜像。在 volumes 中,我已经指出我想要挂载主机的 Docker 套接字,但我仍然需要 Docker 客户端使用 Docker API 与它进行交互。因此,我已经定义了一个标签为 docker 的容器模板,该模板使用安装了 Docker 客户端的镜像。\npodTemplate( name: 'test-pod', label: 'test-pod', containers: [ containerTemplate(name: 'golang', image: 'golang:1.9.4-alpine3.7'), containerTemplate(name: 'docker', image:'trion/jenkins-docker-client'), ], volumes: [ hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock', ], { //node = the pod label node('test-pod'){ //container = the container label stage('Build'){ container('golang'){ // This is where we build our code. } } stage('Build Docker Image'){ container(‘docker’){ // This is where we build the Docker image } } } })  在我的基于 Docker 的流水线脚本中,我构建了 Docker 镜像并将它们推送到了 Docker 仓库,对我来说,能够复制这些配置信息非常重要。完成后,我已准备好使用 gcloud(Google Cloud SDK)构建我的镜像,并将该镜像推送到 Google Container Registry,以便部署到我的 K8s 群集。\n为此,我使用 gcloud 镜像指定了一个容器模板,并将我的 docker 命令更改为 gcloud 命令。 就这么简单!\npodTemplate( name: 'test-pod', label: 'test-pod', containers: [ containerTemplate(name: 'golang', image: 'golang:1.9.4-alpine3.7'), containerTemplate(name: 'gcloud', image:'gcr.io/cloud-builders/gcloud'), ], { //node = the pod label node('test-pod'){ //container = the container label stage('Build'){ container('golang'){ // This is where we build our code. } } stage('Build Docker Image'){ container(‘gcloud’){ //This is where we build and push our Docker image. } } } })  在 Kubernetes 上运行 Jenkins master、 Jenkins 代理,构建和部署示例应用程序其实只花了我几个小时。但这之后,我花了一个周末的时间才深入了解了平台。如果你学得够快,我相信你在几天内就可以完全掌握并且灵活运用这个平台了。\n",
        "auhtor": "devmandy",
        "translator": "yuzp1996",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/jenkins-%E6%B5%81%E6%B0%B4%E7%BA%BF/",
        "title": "Jenkins 流水线",
        "type": "tags",
        "date": "2019-11-29 00:00:00 +0000 UTC",
2893 2894 2895 2896 2897 2898
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
2899
        "poster": ""
2900
    },
2901
    {
2902 2903 2904 2905
        "uri": "https://jenkins-zh.cn/tags/jenkinsworld/",
        "title": "Jenkinsworld",
        "type": "tags",
        "date": "2019-09-15 00:00:00 +0000 UTC",
2906
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2907
        "description": "",
2908
        "content": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2909
        "auhtor": "",
2910 2911
        "translator": "",
        "original": "",
2912
        "poster": ""
2913 2914
    },
    {
2915 2916 2917
        "uri": "https://jenkins-zh.cn/tags/jenkinsworld2018/",
        "title": "Jenkinsworld2018",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2918
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2919
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2920 2921 2922
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2923 2924
        "translator": "",
        "original": "",
2925
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2926 2927
    },
    {
2928 2929 2930 2931
        "uri": "https://jenkins-zh.cn/tags/jira/",
        "title": "Jira",
        "type": "tags",
        "date": "2019-05-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2932 2933
        "tags": [],
        "description": "",
2934
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2935 2936 2937 2938
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2939
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2940
    {
2941 2942 2943 2944
        "uri": "https://jenkins-zh.cn/tags/jmh/",
        "title": "Jmh",
        "type": "tags",
        "date": "2019-07-04 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2945 2946 2947 2948 2949 2950
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2951
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2952
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2953
    {
2954 2955 2956 2957
        "uri": "https://jenkins-zh.cn/tags/jte/",
        "title": "Jte",
        "type": "tags",
        "date": "2019-07-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2958 2959 2960 2961 2962 2963 2964 2965 2966
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
2967 2968 2969 2970
        "uri": "https://jenkins-zh.cn/tags/k8s/",
        "title": "K8s",
        "type": "tags",
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2971 2972
        "tags": [],
        "description": "",
2973
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2974 2975 2976 2977 2978
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2979
    {
2980 2981 2982 2983
        "uri": "https://jenkins-zh.cn/tags/kafka-kubernetes-helm/",
        "title": "Kafka Kubernetes Helm",
        "type": "tags",
        "date": "2019-11-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2984 2985
        "tags": [],
        "description": "",
2986
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
2987 2988 2989 2990
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2991 2992
    },
    {
2993 2994 2995
        "uri": "https://jenkins-zh.cn/tags/kubecon/",
        "title": "Kubecon",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2996
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2997 2998
        "tags": [],
        "description": "",
2999
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3000 3001 3002 3003
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3004
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3005
    {
3006 3007 3008 3009
        "uri": "https://jenkins-zh.cn/tags/kubernetes/",
        "title": "Kubernetes",
        "type": "tags",
        "date": "2019-07-29 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3010 3011
        "tags": [],
        "description": "",
3012
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3013 3014 3015 3016 3017
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3018
    {
3019 3020 3021 3022
        "uri": "https://jenkins-zh.cn/tags/maven/",
        "title": "Maven",
        "type": "tags",
        "date": "2019-05-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3023 3024
        "tags": [],
        "description": "",
3025
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3026 3027 3028 3029
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3030
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3031
    {
3032 3033 3034 3035
        "uri": "https://jenkins-zh.cn/tags/multi-branch/",
        "title": "Multi Branch",
        "type": "tags",
        "date": "2019-12-31 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3036 3037
        "tags": [],
        "description": "",
3038
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3039 3040 3041 3042 3043
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3044
    {
3045 3046 3047 3048
        "uri": "https://jenkins-zh.cn/tags/multibranch/",
        "title": "Multibranch",
        "type": "tags",
        "date": "2019-09-11 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3049 3050
        "tags": [],
        "description": "",
3051
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3052 3053 3054 3055
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
3056
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3057
    {
3058 3059 3060 3061
        "uri": "https://jenkins-zh.cn/tags/newcomer/",
        "title": "Newcomer",
        "type": "tags",
        "date": "2019-04-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3062 3063
        "tags": [],
        "description": "",
3064
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3065 3066 3067 3068
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3069
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3070
    {
3071 3072 3073 3074
        "uri": "https://jenkins-zh.cn/tags/nginx/",
        "title": "Nginx",
        "type": "tags",
        "date": "2019-04-25 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3075 3076
        "tags": [],
        "description": "",
3077
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3078 3079 3080 3081
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3082
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3083
    {
3084 3085 3086 3087
        "uri": "https://jenkins-zh.cn/tags/open-source/",
        "title": "Open Source",
        "type": "tags",
        "date": "2019-08-30 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3088 3089
        "tags": [],
        "description": "",
3090
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3091 3092 3093 3094 3095 3096
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3097 3098 3099 3100
        "uri": "https://jenkins-zh.cn/tags/opensource/",
        "title": "Opensource",
        "type": "tags",
        "date": "2019-09-15 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3101 3102
        "tags": [],
        "description": "",
3103
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3104 3105 3106 3107
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
3108
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3109
    {
3110 3111 3112 3113
        "uri": "https://jenkins-zh.cn/tags/outreachy/",
        "title": "Outreachy",
        "type": "tags",
        "date": "2019-02-13 00:00:00 +0000 UTC",
3114 3115
        "tags": [],
        "description": "",
3116
        "content": "",
3117
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3118 3119 3120
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3121
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3122
    {
3123 3124 3125 3126
        "uri": "https://jenkins-zh.cn/tags/outreachy2018/",
        "title": "Outreachy2018",
        "type": "tags",
        "date": "2019-02-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3127 3128
        "tags": [],
        "description": "",
3129
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3130 3131 3132 3133 3134 3135
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3136 3137 3138 3139
        "uri": "https://jenkins-zh.cn/tags/performance/",
        "title": "Performance",
        "type": "tags",
        "date": "2019-07-04 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3140 3141
        "tags": [],
        "description": "",
3142
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3143 3144 3145 3146 3147 3148
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3149 3150 3151 3152
        "uri": "https://jenkins-zh.cn/tags/pipeline/",
        "title": "Pipeline",
        "type": "tags",
        "date": "2019-12-29 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3153
        "tags": [],
3154
        "description": "",
3155
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3156 3157 3158 3159
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3160
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3161
    {
3162 3163 3164 3165
        "uri": "https://jenkins-zh.cn/tags/pipeline-authoring/",
        "title": "Pipeline Authoring",
        "type": "tags",
        "date": "2019-07-01 00:00:00 +0000 UTC",
3166
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
3167
        "description": "",
3168
        "content": "",
3169
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3170 3171 3172 3173
        "translator": "",
        "original": "",
        "poster": ""
    },
3174
    {
3175 3176 3177 3178 3179 3180 3181 3182
        "uri": "https://jenkins-zh.cn/tags/platform-sig/",
        "title": "Platform Sig",
        "type": "tags",
        "date": "2019-10-25 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
3183 3184 3185 3186
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3187
    {
3188 3189 3190 3191
        "uri": "https://jenkins-zh.cn/tags/plugin/",
        "title": "Plugin",
        "type": "tags",
        "date": "2019-09-19 00:00:00 +0000 UTC",
3192 3193
        "tags": [],
        "description": "",
3194
        "content": "",
3195
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3196 3197 3198 3199
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3200
    {
3201 3202 3203 3204
        "uri": "https://jenkins-zh.cn/tags/pluginmanagement/",
        "title": "Pluginmanagement",
        "type": "tags",
        "date": "2019-10-25 00:00:00 +0000 UTC",
3205 3206
        "tags": [],
        "description": "",
3207
        "content": "",
3208 3209
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3210 3211
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3212
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3213
    {
3214 3215 3216 3217
        "uri": "https://jenkins-zh.cn/tags/plugins/",
        "title": "Plugins",
        "type": "tags",
        "date": "2019-10-25 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3218
        "tags": [],
3219 3220 3221
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3222 3223 3224 3225 3226
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3227 3228
        "uri": "https://jenkins-zh.cn/tags/progressive-delivery/",
        "title": "Progressive Delivery",
3229
        "type": "tags",
3230
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3231
        "tags": [],
3232 3233
        "description": "",
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3234 3235 3236 3237 3238 3239
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3240 3241
        "uri": "https://jenkins-zh.cn/tags/react/",
        "title": "React",
3242
        "type": "tags",
3243
        "date": "2019-09-19 00:00:00 +0000 UTC",
3244
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
3245
        "description": "",
3246 3247
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3248 3249 3250 3251
        "translator": "",
        "original": "",
        "poster": ""
    },
3252
    {
3253 3254
        "uri": "https://jenkins-zh.cn/tags/react-plugins-gsoc-gsoc2019/",
        "title": "React Plugins Gsoc Gsoc2019",
3255
        "type": "tags",
3256
        "date": "2019-11-14 00:00:00 +0000 UTC",
3257 3258 3259 3260 3261 3262 3263 3264
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3265
    {
3266 3267 3268 3269 3270 3271 3272 3273 3274
        "uri": "https://jenkins-zh.cn/tags/release/",
        "title": "Release",
        "type": "tags",
        "date": "2019-07-09 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
3275
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3276 3277 3278
        "poster": ""
    },
    {
3279 3280 3281 3282 3283 3284 3285 3286 3287
        "uri": "https://jenkins-zh.cn/tags/remote-file/",
        "title": "Remote File",
        "type": "tags",
        "date": "2019-08-05 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3288 3289 3290
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3291
    {
3292 3293 3294 3295
        "uri": "https://jenkins-zh.cn/tags/security/",
        "title": "Security",
        "type": "tags",
        "date": "2019-04-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3296
        "tags": [],
3297
        "description": "",
3298
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3299 3300 3301 3302 3303
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3304
    {
3305 3306
        "uri": "https://jenkins-zh.cn/tags/shared-library/",
        "title": "Shared Library",
3307
        "type": "tags",
3308
        "date": "2019-03-06 00:00:00 +0000 UTC",
3309
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3310
        "description": "",
3311 3312
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3313 3314 3315
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3316
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3317
    {
3318 3319
        "uri": "https://jenkins-zh.cn/tags/shipper/",
        "title": "Shipper",
3320
        "type": "tags",
3321
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3322
        "tags": [],
3323 3324 3325
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3326 3327 3328 3329
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3330
    {
3331 3332 3333 3334
        "uri": "https://jenkins-zh.cn/tags/spec/",
        "title": "Spec",
        "type": "tags",
        "date": "2019-05-20 00:00:00 +0000 UTC",
3335
        "tags": [],
3336 3337
        "description": "",
        "content": "",
3338 3339
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3340 3341 3342 3343
        "original": "",
        "poster": ""
    },
    {
3344 3345 3346
        "uri": "https://jenkins-zh.cn/sponsor/",
        "title": "Sponsors",
        "type": "sponsor",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3347
        "date": "0001-01-01 00:00:00 +0000 UTC",
3348 3349 3350 3351 3352
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3353 3354 3355
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3356
    {
3357 3358 3359 3360 3361
        "uri": "https://jenkins-zh.cn/tags/spring-boot/",
        "title": "Spring Boot",
        "type": "tags",
        "date": "2019-05-24 00:00:00 +0000 UTC",
        "tags": [],
3362
        "description": "",
3363 3364
        "content": "",
        "auhtor": "",
3365
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3366 3367 3368 3369
        "original": "",
        "poster": ""
    },
    {
3370 3371 3372 3373
        "uri": "https://jenkins-zh.cn/tags/springboot/",
        "title": "Springboot",
        "type": "tags",
        "date": "2019-05-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3374
        "tags": [],
3375 3376 3377
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3378 3379 3380
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3381
    },
3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394
    {
        "uri": "https://jenkins-zh.cn/tags/t-mobile/",
        "title": "T Mobile",
        "type": "tags",
        "date": "2020-02-28 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3395
    {
3396 3397 3398 3399 3400 3401 3402 3403 3404
        "uri": "https://jenkins-zh.cn/tags/",
        "title": "Tags",
        "type": "tags",
        "date": "2019-04-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3405 3406
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3407
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3408
    {
3409 3410 3411 3412
        "uri": "https://jenkins-zh.cn/tags/template/",
        "title": "Template",
        "type": "tags",
        "date": "2019-09-19 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3413
        "tags": [],
3414 3415 3416
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3417 3418 3419 3420
        "translator": "",
        "original": "",
        "poster": ""
    },
3421
    {
3422 3423 3424 3425 3426 3427 3428 3429 3430
        "uri": "https://jenkins-zh.cn/tags/updatebot/",
        "title": "Updatebot",
        "type": "tags",
        "date": "2019-11-15 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
3431 3432 3433
        "original": "",
        "poster": ""
    },
3434
    {
3435 3436
        "uri": "https://jenkins-zh.cn/tags/webhook/",
        "title": "Webhook",
3437
        "type": "tags",
3438
        "date": "2019-12-23 00:00:00 +0000 UTC",
3439 3440 3441 3442 3443 3444 3445 3446
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3447
    {
3448 3449
        "uri": "https://jenkins-zh.cn/tags/webhooks/",
        "title": "Webhooks",
3450
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3451
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3452 3453
        "tags": [],
        "description": "",
3454
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3455 3456 3457 3458 3459
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3460
    {
3461 3462 3463 3464
        "uri": "https://jenkins-zh.cn/tags/websocket/",
        "title": "Websocket",
        "type": "tags",
        "date": "2020-02-10 00:00:00 +0000 UTC",
3465 3466
        "tags": [],
        "description": "",
3467
        "content": "",
3468 3469 3470 3471 3472
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3473
    {
3474 3475 3476
        "uri": "https://jenkins-zh.cn/wechat/",
        "title": "Wechats",
        "type": "wechat",
3477
        "date": "2020-03-02 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3478 3479
        "tags": [],
        "description": "",
3480
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3481 3482 3483 3484 3485 3486
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3487 3488 3489 3490
        "uri": "https://jenkins-zh.cn/tags/weekly/",
        "title": "Weekly",
        "type": "tags",
        "date": "2019-03-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3491 3492
        "tags": [],
        "description": "",
3493
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3494 3495 3496 3497
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
3498 3499
    },
    {
3500 3501 3502
        "uri": "https://jenkins-zh.cn/weibo/",
        "title": "Weibos",
        "type": "weibo",
LinuxSuRen's avatar
LinuxSuRen 已提交
3503
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3504 3505
        "tags": [],
        "description": "",
3506
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
3507 3508 3509 3510
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3511
    },
3512
    {
3513 3514
        "uri": "https://jenkins-zh.cn/tags/wiki/",
        "title": "Wiki",
3515
        "type": "tags",
3516
        "date": "2019-11-22 00:00:00 +0000 UTC",
3517 3518 3519 3520 3521 3522 3523 3524
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3525
    {
3526 3527 3528
        "uri": "https://jenkins-zh.cn/tags/windows/",
        "title": "Windows",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3529
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3530 3531
        "tags": [],
        "description": "",
3532
        "content": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3533 3534 3535
        "auhtor": "",
        "translator": "",
        "original": "",
3536 3537 3538
        "poster": ""
    },
    {
3539 3540 3541
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-windows-installers/",
        "title": "Windows 安装程序更新",
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3542
        "date": "0001-01-01 00:00:00 +0000 UTC",
3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
        "tags": ["windows", "platform-sig", "installers"],
        "description": "平台特别兴趣小组提供了 Windows 安装程序的更新",
        "content": " Jenkins 的 Windows 安装程序已经存在很多年了,它是用户在 Windows 上安装 Jenkins Master 作为服务的一种方式。 从被开发出来至今,它还没有什么新特性,但现在是时候做出改变了。\n首先,让我们瞧瞧现版本安装程序的使用经验。\n第1步 启动安装程序 这是使用 WiX Toolset Windows 安装程序的默认界面外观,算不上太好看,而且没有太多对安装程序进行说明的品牌信息。\n第2步 安装目录 同样,没有太多的品牌信息。\n第3步 安装 除了选择安装位置外,安装程序大体上没有提供一些安装 Jenkins 的选项。\n问题 现在的安装程序存在一些问题,平台特别兴趣小组会修复这些问题,并为用户提供新的安装体验。\n 安装程序只支持32位安装。 用户不能选择 Jenkins 作为 Windows 服务启动时的端口以及账户。 安装程序捆绑了32位的 Java Runtime,而没有使用已存在的 JRE。 安装程序不支持 Jenkins for Java 11中的实验性支持。 JENKINS_HOME 目录并不适合现代 Windows。 安装程序中没有品牌。  前进 使用实验性的 Jenkins Windows 安装程序,大部分问题都已解决!\n 安装程序将只支持64位系统,这也是如今大多数 Windows 系统的现状,所以能让更多的用户能够使用安装包来安装 Jenkins。 用户能够为服务输入用户信息,同时选择端口以便于 Jenkins 验证端口是否可用。 安装程序不再捆绑 JRE 而是在操作系统中寻找合适的 JRE。如果用户想要使用一个不同的 JRE,可以在安装时指定。 安装程序已经支持 Java 11,包括在 Java 11 预览上面列出的组件。 JENKINS_HOME 目录被放置在启动服务用户的 LocalAppData 目录下,这与现代 Windows 文件系统布局一致。 安装程序已经升级带有品牌了,这让它看起来更酷并能提供一个更好的用户体验。  截图 以下是新安装程序的系列屏幕截图:\n第1步 启动安装程序 Jenkins logo 现在是安装程序 UI 的重要组成部分。\n第2步 安装目录 在安装程序的所有阶段,Jenkins logo 和名称都出现在标题中。\n第3步 选择账户 安装程序现在允许您指定要运行的帐户的用户名/密码,并检查该帐户是否具有 LogonAsService 权限。\n第4步 端口选择 安装程序还允许您指定 Jenkins 运行的端口,并且在输入和测试有效端口之前不会继续。\n第5步 JRE 选择 安装程序现在不再捆绑 JRE,而是在系统上搜索兼容的 JRE (现在是 JRE 8)。 如果你想使用与安装程序搜索到不同的 JRE,你可以浏览目录并指定它。只支持 JRE 8 和 JRE 11 Runtime。如果发现选定的 JRE 是版本11,安装程序将自动添加必要的参数和其他 jar 文件,以便在 Java 11下运行。\n第6步 安装 用户能在安装程序中输入的所有选项也可以在命令行上覆盖以进行自动部署。可以覆盖的完整属性列表即将推出。\n接下来的步骤 新版本安装程序正在被平台特别兴趣小组的成员 Review 中,但我们需要人测试安装程序并给予反馈。你过你对测试新安装程序感兴趣的话,请加入平台特别兴趣小组 gitter room 获取更多信息。\n在新安装程序中还使用了许多一些正在研发的东西(例如,在进行升级时保留端口和其他选择),但它已接近发布。\n除了基于 MSI 的 Windows 安装程序的更新之外,平台特别兴趣小组还在努力接管 Chocolatey Jenkins 软件包并为每次更新发布一个版本。\n",
        "auhtor": "slide_o_mix",
        "translator": "arjenzhou",
        "original": "https://jenkins.io/blog/2019/02/01/windows-installers/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/zabbix/",
        "title": "Zabbix",
        "type": "tags",
        "date": "2019-04-15 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
3556 3557 3558 3559 3560 3561 3562 3563
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3564
    {
3565 3566 3567
        "uri": "https://jenkins-zh.cn/tutorial/notify/email/",
        "title": "email",
        "type": "tutorial",
LinuxSuRen's avatar
LinuxSuRen 已提交
3568 3569 3570
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3571
        "content": "我们可以通过发送电子邮件的方式来通知流水线的构建状态。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3572 3573 3574 3575 3576 3577
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3578 3579 3580
        "uri": "https://jenkins-zh.cn/tutorial/notify/",
        "title": "notify",
        "type": "tutorial",
LinuxSuRen's avatar
LinuxSuRen 已提交
3581 3582 3583
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3584
        "content": "notify\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3585 3586 3587 3588 3589 3590
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3591 3592 3593
        "uri": "https://jenkins-zh.cn/tutorial/pipeline/",
        "title": "pipeline",
        "type": "tutorial",
LinuxSuRen's avatar
LinuxSuRen 已提交
3594 3595 3596
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3597
        "content": "流水线相关\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3598 3599 3600 3601 3602 3603
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3604 3605 3606
        "uri": "https://jenkins-zh.cn/tutorial/plugin-dev/",
        "title": "plugin-dev",
        "type": "tutorial",
LinuxSuRen's avatar
LinuxSuRen 已提交
3607 3608 3609
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3610
        "content": "plugin dev\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3611 3612 3613 3614 3615 3616
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
3617 3618 3619
        "uri": "https://jenkins-zh.cn/tutorial/scm/",
        "title": "scm",
        "type": "tutorial",
LinuxSuRen's avatar
LinuxSuRen 已提交
3620 3621 3622
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3623
        "content": "有关 SCM 的教程\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3624 3625 3626 3627 3628
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3629
    {
3630
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-12-what-is-cicd/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3631
        "title": "什么是 CI/CD?",
LinuxSuRen's avatar
LinuxSuRen 已提交
3632 3633
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3634
        "tags": ["ci", "cd"],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3635
        "description": "本文介绍了 CI/CD 的概念及应用场景",
LinuxSuRen's avatar
LinuxSuRen 已提交
3636 3637 3638 3639 3640
        "content": " CI/CD 的出现改变了开发人员和测试人员发布软件的方式。本文是描述这一变化的系列文章第一篇, 这些文章将提供各种工具和流程的讲解,以帮助开发人员更好的使用 CI/CD。\n从最初的 瀑布模型, 到后来的 敏捷开发, 再到今天的 DevOps, 这是现代开发人员构建出色产品的技术路线。 随着 DevOps 的兴起,出现了持续集成,持续交付(CI/CD)和持续部署的新方法, 而传统的软件开发和交付方式在迅速变得过时。过去的敏捷时代里, 大多数公司的软件发布周期是每月、每季度甚至每年(还记得那些日子吗?), 而在现在 DevOps 时代,每周、每天甚至每天多次都是常态。 当 SaaS 成为业界主流后尤其如此,您可以轻松地动态更新应用程序, 而无需强迫用户下载更新组件。很多时候,用户甚至都不会注意到正在发生变化。\n开发团队通过软件交付流水线(Pipeline)实现自动化,以缩短交付周期, 大多数团队都有自动化流程来检查代码并部署到新环境。 我们一直在关注自动化测试流程,但这将在之后的文章中介绍。 今天,我们将介绍什么是 CI/CD/CD ,以及现代软件公司如何使用工具将部署代码的流程自动化。\n持续集成注重将各个开发者的工作集合到一个代码仓库中,通常每天会进行几次, 主要目的是尽早发现集成错误,使团队更加紧密结合,更好地协作。 持续交付的目的是最小化部署或发布过程中团队固有的摩擦, 它的实现通常能够将构建部署的每个步骤自动化,以便任何时刻能够安全地完成代码发布(理想情况下)。 持续部署是一种更高程度的自动化,无论何时代码有较大改动, 都会自动进行构建/部署。\n以上的每一个阶段都是交付流水线的一部分。 Humble 和 Ferley 在他们的书作《持续交付:通过自动化构建、测试和部署实现可靠软件版本发布》中解释说: 「对软件的每次更改都要经过一个复杂的过程才能发布,该过程包括多个测试和部署阶段进行软件的构建。 反过来看,这个过程需要许多人之间的合作,甚至可能需要几个团队间合作。 部署流水线对这一过程进行建模,并且它的持续集成和发布管理工具能让您在代码从版本控制转移到各种测试和部署时, 查看和控制每次更改的过程。」\n持续集成(CI) 通过持续集成,开发人员能够频繁地将其代码集成到公共代码仓库的主分支中。 开发人员能够在任何时候多次向仓库提交作品,而不是独立地开发每个功能模块并在开发周期结束时一一提交。\n这里的一个重要思想就是让开发人员更快更、频繁地做到这一点,从而降低集成的开销。 实际情况中,开发人员在集成时经常会发现新代码和已有代码存在冲突。 如果集成较早并更加频繁,那么冲突将更容易解决且执行成本更低。\n当然,这里也有一些权衡,这个流程不提供额外的质量保障。 事实上,许多组织发现这样的集成方式开销更大,因为它们依赖人工确保新代码不会引起新的 bug 或者破坏现有代码。 为了减少集成期间的摩擦,持续集成依赖于测试套件和自动化测试。 然而,要认识到自动化测试和持续测试是完全不同的这一点很重要,我们会在文章结尾处详细说明。\nCI 的目标是将集成简化成一个简单、易于重复的日常开发任务, 这样有助于降低总体的构建成本并在开发周期的早期发现缺陷。 要想有效地使用 CI 必须转变开发团队的习惯,要鼓励频繁迭代构建, 并且在发现 bug 的早期积极解决。\n持续交付(CD)实际上是 CI 的扩展,其中软件交付流程进一步自动化,以便随时轻松地部署到生成环境中。 成熟的持续交付方案也展示了一个始终可部署的代码库。使用 CD 后,软件发布将成为一个没有任何紧张感的例行事件。 开发团队可以在日常开发的任何时间进行产品级的发布,而不需要详细的发布方案或者特殊的后期测试。\nCD 集中依赖于部署流水线,团队通过流水线自动化测试和部署过程。此流水线是一个自动化系统, 可以针对构建执行一组渐进的测试套件。CD 具有高度的自动化,并且在一些云计算环境中也易于配置。\n在流水线的每个阶段,如果构建无法通过关键测试会向团队发出警报。否则,将继续进入下一个测试, 并在连续通过测试后自动进入下一个阶段。流水线的最后一个部分会将构建部署到和生产环境等效的环境中。 这是一个整体的过程,因为构建、部署和环境都是一起执行和测试的,它能让构建在实际的生产环境可部署和可验证。\nAWS 上提供了可靠的当前 CI/CD 的展示,亚马逊是云计算的提供商之一,提供出色的 CI/CD 流水线环境和实验过程, 有众多开发资源可供选择,您可以将它们在一个易于配置和监控的流水线中组合起来。\n许多人认为持续交付的吸引力主要在于,它自动化了从提交代码到仓库,再到测试和发布产品过程的所有步骤。 这是构建和测试过程细致的自动化,但是如何发布以及发布什么仍然是需要人工操作,持续部署可以改变这一点。\n持续部署(CD) 持续部署扩展了持续交付,以便软件构建在通过所有测试时自动部署。在这样的流程中, 不需要人为决定何时及如何投入生产环境。CI/CD 系统的最后一步将在构建后的组件/包退出流水线时自动部署。 此类自动部署可以配置为快速向客户分发组件、功能模块或修复补丁,并准确说明当前提供的内容。\n采用持续部署的组织可以将新功能快速传递给用户,得到用户对于新版本的快速反馈,并且可以迅速处理任何明显的缺陷。 用户对无用或者误解需求的功能的快速反馈有助于团队规划投入,避免将精力集中于不容易产生回报的地方。\n随着 DevOps 的发展,新的用来实现 CI/CD 流水线的自动化工具也在不断涌现。这些工具通常能与各种开发工具配合, 包括像 GitHub 这样的代码仓库和 Jira 这样的 bug 跟踪工具。此外,随着 SaaS 这种交付方式变得更受欢迎, 许多工具都可以在现代开发人员运行应用程序的云环境中运行,例如 GCP 和 AWS。\n最受欢迎的自动化工具是 Jenkins(以前的 Hudson), 这是一个由数百名贡献者和商业公司 Cloudbees 支持的开源项目。 Cloudbees 甚至聘请了 Jenkins 的创始人,并提供了一些 Jenkins 培训项目和附加组件。 除了开源项目之外,还有一些更现代化的商业产品例如 CircleCI,Codeship 和 Shippable。 这些产品各有优缺点,我鼓励开发人员在开发流程中一一尝试它们,以了解它们在您的环境中的工作方式, 以及它们如何与您的工具、云平台、容器系统等协作。\n在 mabl 中,我们在 Google Cloud Platform 上进行构建, 因此,我们正在寻找与 GSP 兼容或者最好是已经集成进 GSO 的产品。我们尝试过 CircleCI,Codeship 和 Shippable, 下面有一个简单的表格,展示了每个工具的一些细节:\n我们最终选择了 Codeship,我认为我们的选择是正确的, 也感谢 Codeship 团队的支持。\n接下来? 一旦部署了现代化的 CI/CD 流水线,您可能会意识到开发人员工作流程中的一些工具和流程也需要进行现代化改造。 测试是一个要着重关注的领域,如果您的部署频率是每天或者一天多次,您的每次测试可能需要数小时甚至一晚上才能完成。 mabl 正在使用机器学习解决这个问题。\n",
        "auhtor": "Izzyazeri",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/what-is-cicd",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3641
    },
3642
    {
3643
        "uri": "https://jenkins-zh.cn/tutorial/best-practice/android/android-best-practice/",
3644 3645 3646 3647 3648
        "title": "使用 Jenkins 构建 Android 应用",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3649
        "content": " 本教程将展示 Jenkins 如何使用 Jenkins 和 Gradle 构建一个简单的 Android 应用程序。\n如果你是一个对 CI/CD 概念不了解的 Android 开发者,或者你熟悉这些概念却不知道如何使用 Jenkins 完成构建,那么本教程很适合你。你将在 GitHub 上获取一个简单的 Android 应用项目,并包含单元测试。\n耗时:本教程需要 20-40 分钟来完成(假设你的机器已经满足配置要求)。\n配置要求 对于本教程,您将需要:\n 安装有 macOS、Linux 或 Windows 操作系统的机器,并拥有以下配置:\n 最小 256 MB 内存,推荐 512MB 以上。\n 10 GB 硬盘空间,用于安装 Jenkins,您的 Docker 镜像和容器。\n  安装有以下软件:\n Docker - 在安装 Jenkins 页面的安装 Docker 章节阅读更多信息。\n注意:如果您使用 Linux,本教程假定您没有以 root 用户的身份运行 Docker 命令,而是使用单个用户帐户访问本教程中使用的其他工具。\n Git 和 GitHub Desktop。\n   在 Docker 中运行 Jenkins 在本教程中,将 Jenkins 作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。\n要在 Docker 中运行 Jenkins,请遵循下面的 macOS 和 Linux 或 Windows 相关文档说明进行操作。\n你可以在 Docker 和 Installing Jenkins 页面的 Downloading and running Jenkins in Docker 部分阅读更多有关 Docker 容器和镜像概念的信息。\n在 macOS 和 Linux 系统上  打开终端窗口。\n 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为 Docker 中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):\n  docker run \\ --rm \\ -u root \\ -p 8080:8080 \\ -v jenkins-data:/var/jenkins_home \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v \u0026quot;$HOME\u0026quot;:/home \\ jenkinsci/blueocean   ① `-v jenkins-data:/var/jenkins_home` 表示将容器中的 /var/jenkins_home 目录映射到 Docker volume,并将其命名为 jenkins-data。如果该卷不存在,那么 docker run 命令会自动为你创建卷。 ② `-v \u0026quot;$HOME\u0026quot;:/home` 将主机上的 $HOME 目录(即你的本地)映射到(通常是 /Users/\u0026lt;your-username\u0026gt; 目录)到容器的 /home 目录。   继续向导  在 Windows 系统  打开命令提示窗口。\n 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为 Docker 中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):\n  docker run ^ --rm ^ -u root ^ -p 8080:8080 ^ -v jenkins-data:/var/jenkins_home ^ -v /var/run/docker.sock:/var/run/docker.sock ^ -v \u0026quot;%HOMEPATH%\u0026quot;:/home ^ jenkinsci/blueocean  对这些选项的解释,请参考上面的 macOS 和 Linux 说明。   继续安装向导。  访问 Jenkins/Blue Ocean Docker 容器 如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器,你可以添加如 \u0026ndash;name jenkins-tutorials 选项(与上面的 docker run),这将会给 Jenkins/Blue Ocean Docker 容器一个名字 \u0026ldquo;jenkins-tutorials\u0026rdquo;。\n这意味着你可以通过 docker exec 命令访问 Jenkins/Blue Ocean 容器(通过一个单独的终端/命令提示窗口),例如:\ndocker exec -it jenkins-tutorials bash  安装向导 在你访问 Jenkins 之前,你需要执行一些快速的\u0026rdquo;一次性\u0026rdquo;步骤。\n解锁 Jenkins 当你第一次访问一个新的 Jenkins 实例时,要求你使用自动生成的密码对其进行解锁。\n 当在终端/命令提示窗口出现两组星号时,浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。\n 再次从终端/命令提示窗口,复制自动生成的字母数字密码(在两组星号之间)。\n 在 Unlock Jenkins 页面,粘贴该密码到 Administrator password 字段并点击 Continue。\n  使用插件自定义 Jenkins 在解锁 Jenkins 后,Customize Jenkins 页面出现。\n在该页面,点击 Install suggested plugins。\n安装向导显示了正在配置的 Jenkins 的进程,以及建议安装的插件,这个过程可能需要几分钟。\n创建第一个管理员用户 最后,Jenkins 要求创建你的第一个管理员用户。\n 当 Create First Admin User 页面出现,在相应的字段中指定你的详细消息并点击 Save and Finish。\n 当 Jenkins is ready 页面出现,点击 Start using Jenkins。\n注意:该页面可能表明 Jenkins is almost ready!如果相反,点击 Restart。\n 如果该页面在一分钟后没有自动刷新,使用你的 web 浏览器手动刷新。\n  如果需要,登录 Jenkins,你就可以开始使用 Jenkins 了!\n停止和重启 Jenkins 在本教程的其余部分,你可以通过在终端/命令提示窗口输入 Ctrl-C 停止 Jenkins/Blue Ocean Docker 容器,也可以运行上面 docker run ... 命令启动容器。\n要重启 Jenkins/Blue Ocean Docker 容器:\n 在上面的 macOS、Linux 或 Windows 上运行相同的 docker run \u0026hellip; 命令。\n注意:如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。\n 浏览 http://localhost:8080。\n 等待直到登录页面出现并登陆。\n  Fork 和 clone GitHub 示例仓库 通过将应用程序源代码所在的示例仓库 fork 到你自己的 GitHub 账号中,并 clone 到本地,你就可以获取一简单的 Android 应用程序。\n 请确保你登陆了你的 GitHub 账户。如果你还没有 GitHub 账户,你可以在 GitHub 网站免费注册一个账户。\n 将示例仓库 jenkins-android-sample fork 到你的账户的 GitHub 仓库中。\n 将你的 GitHub 账户中的 jenkins-android-sample 仓库 clone 到你的本地机器,确保你的项目路径为:\n macOS 系统配置为 /Users/\u0026lt;your-username\u0026gt;/Documents/GitHub/jenkins-android-sample\n Linux 系统配置为 /home/\u0026lt;your-username\u0026gt;/GitHub/jenkins-android-sample\n Windows 系统配置为 C:\\Users\\\u0026lt;your-username\u0026gt;\\Documents\\GitHub\\jenkins-android-sample\n   在 Jenkins 中创建你的流水线项目  回到 Jenkins,如果有必要的话重新登录,点击 Welcome to Jenkins!下方的 create new jobs。\n注意:如果你无法看见以上内容,点击左上方的 New Item。\n 在 Enter an item name 域中,为新的流水线项目指定名称(例如 jenkins-android-sample)。\n 向下滚动并单击 Pipeline,然后单击页面末尾的 OK。\n  4.(可选)在下一页中,在 Description 字段中填写流水线的简要描述。\n 点击页面顶部的 Pipeline 选项卡,向下滚动到 Pipeline 部分。\n 在 Definition 域中,选择 Pipeline script from SCM 选项。此选项指示 Jenkins 从源代码管理(SCM)仓库获取你的流水线,这里的仓库就是你 clone 到本地的 Git 仓库。\n 在 SCM 域中,选择 Git。\n 在 Repository URL 域中,填写你本地仓库的目录路径,这是从你主机上的用户账户 home 目录映射到 Jenkins 容器的 /home 目录:\n MacOS系统 - /home/Documents/GitHub/jenkins-android-sample Linux系统 - /home/GitHub/jenkins-android-sample Windows系统 - /home/Documents/GitHub/jenkins-android-sample  点击 Save 保存你的流水线项目。你现在可以开始创建你的 Jenkinsfile,这些文件会被添加到你的本地仓库。\n  创建 Jenkinsfile 为初始流水线 现在我们将开始创建初始流水线,它将使用 Jenkins 构建你的 Android 应用程序。你的流水线将被创建为 Jenkinsfile,它将被提交到你本地的 Git 仓库(jenkins-android-sample)。\n首先,创建一个初始流水线来下载 Android 编译环境的 Docker 镜像,并将其作为 Docker 容器运行。同时添加一个 \u0026ldquo;Build\u0026rdquo; 阶段到流水线中,用于协调整个过程。\n 使用你最称手的文本编辑器或者 IDE,在你本地的 jenkins-android-sample Git 仓库的根目录创建并保存一个名为 Jenkinsfile 的文本文件。\n 复制以下声明式流水线代码并粘贴到 Jenkinsfile 文件中:\n  pipeline{ agent { docker { image 'allbears/jenkins-android:1.0.1' //① } } stages { stage('Build'){ steps { sh './gradlew clean \u0026amp;\u0026amp; rm -rf ./app/build/' //② sh './gradlew assembleRelease' //③ } } } }  ① 这里的 image 参数是用来下载 allbears/jenkins-android:1.0.1 Docker 镜像(如果你的机器还没下载过它)并将该镜像作为单独的容器运行。你也可以用 `docker pull allbears/jenkins-android:1.0.1` 命令预先将镜像下载到你的宿主机上。 ② 这里的 sh step 是在编译前进行一些准备动作,对你的工程环境进行清理,确保工作时,编译工程环境干净。 ③ 这里的 sh step 运行的是一个 gradle 构建 release 包的命令。   保存对 Jenkinsfile 的修改并且将其提交到你本地的 jenkins-android-sample Git 仓库。例如,在 jenkins-android-sample 目录下,运行以下命令:\ngit add .\n继续运行:\ngit commit -m \u0026ldquo;Add initial Jenkinsfile\u0026rdquo;\n 再次回到 Jenkins,如果有必要的话重新登录,点击左侧的 Open Blue Ocean 进入 Jenkins 的 Blue Ocean 界面。\n 在 This job has not been run 消息框中,点击 Run,然后快速点击右下角出现的 OPEN 链接,观察 Jenkins 运行你的流水线项目。如果你不能点击 OPEN 链接,点击 Blue Ocean 主界面的这一行来使用这一特性。\n注意:你可能需要几分钟时间等待第一次运行完成。在 clone 了你的本地 jenkins-android-sample Git 仓库后,Jenkins 接下来做了以下动作,构建过程如图所示:\n 将项目排入队列等待在 agent 上运行。\n 下载 jenkins-android Docker 镜像,并且将其运行在 Docker 中的一个容器中。\n 执行 assembleRelease 包构建 Release 包。\n    构建成功结束后,该界面将会变成绿色的,构建后的产物将会保存在 /var/jenkins_home/workspace/jenkins-android-sample/app/build/outputs/apk/release 目录下。\n点击上面的 X 就可以回到主界面。\n增加单元测试阶段  打开你的 Jenkinsfile 文件,编辑。 下面的代码复制到你的 Jenkinsflie 中并置于 Build 阶段下方,保存。   stage('UnitTest'){ steps { sh './gradlew test' } }  ① `stage('UnitTest')` 这里增加了一个 UnitTest 的 stage,之后会出现在 Jenkins UI 上。 ② `sh './gradlew test'` 这里的 sh step 运行的是一个 gradle 执行单元测试的命令,该命令执行之后会进行单元测试。  最终代码如下所示:\npipeline{ agent { docker { image 'allbears/jenkins-android:1.0.1' } } stages { stage('Build'){ steps { sh './gradlew clean \u0026amp;\u0026amp; rm -rf ./app/build/' sh './gradlew assembleRelease' } } stage('UnitTest'){ steps { sh './gradlew test' } } } }  继续  保存对 Jenkinsfile 的修改并将其提交到你的本地 jenkins-android-sample Git 仓库。例如,在 jenkins-android-sample 目录下,运行以下命令:\ngit add .\n继续运行:\ngit commit -m \u0026ldquo;Add \u0026lsquo;Test\u0026rsquo; stage\u0026rdquo;\n 再次回到 Jenkins,如果有必要的话重新登录,进入 Jenkins 的 Blue Ocean 界面。\n 点击上方的运行,然后快速点击右下方出现的 OPEN 链接,观察 Jenkins 运行你修改过的流水线项目。如果你不能点击 OPEN 链接,点击 Blue Ocean 主界面的 top 行来使用这一特性,如下图。\n 可以看到在我们的 UI 中增加了一个 UnitTest 的阶段,点击右上方的 X 回到 Blue Ocean 主界面。\n  流水线增加交付阶段  回到你的文本编辑器/ IDE,打开你的 Jenkinsfile。 复制以下声明式流水线代码,并粘贴到 Jenkinsfile 中 UnitTest 阶段的下方:   stage('Archive') { steps { archiveArtifacts artifacts: 'app/build/outputs/**/*.apk', fingerprint: true } }  ① `stage('Archive')` 这里定义了一个名为 Archive 的 stage,之后会出现在 Jenkins UI 上。 ② `archiveArtifacts` 这一行执行了一个归档构建产物的操作,执行完这步操作后我们将在任务界面看见我们执行成功后的产物输出。  最终的代码如下:\npipeline{ agent { docker { image 'allbears/jenkins-android:1.0.1' } } stages { stage('Build'){ steps { sh './gradlew clean \u0026amp;\u0026amp; rm -rf ./app/build/' sh './gradlew assembleRelease' } } stage('UnitTest'){ steps { sh './gradlew test' } } stage('Archive') { steps { archiveArtifacts artifacts: 'app/build/outputs/**/*.apk', fingerprint: true } } } }  继续  保存对 Jenkinsfile 的修改并将其提交到你的本地 jenkins-android-sample Git 仓库。例如,在 jenkins-android-sample 目录下,运行以下命令:\ngit add .\n继续运行:\ngit commit -m \u0026ldquo;Add \u0026lsquo;Archive\u0026rsquo; stage\u0026rdquo;\n 再次回到 Jenkins,如果有必要的话重新登录,进入 Jenkins 的 Blue Ocean 界面。\n 点击上方的运行,然后快速点击右下方出现的 OPEN 链接,观察 Jenkins 运行你修改过的流水线项目。如果你不能点击 OPEN 链接,点击 Blue Ocean 主界面的 top 行来使用这一特性,如图。\n  可以看到我们的 UI 中多了一个 Archive 阶段,构建完成后点击 X 关闭回到我们 Job 主界面,我们可以发现这时多了一个产物的归档下载连接。\n总结 刚刚使用 Jenkins 构建了一个简单的 Android 应用程序,覆盖编译,测试,产物输出的全过程,当然其中还有些优化点,比如我们可以将编译环境中的 Gradle 路径挂载到宿主机,避免每次运行都需要下载依赖包。\n",
3650 3651 3652 3653 3654
        "auhtor": "Sakuragi",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3655
    {
3656
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-23-configuring-jenkins-pipeline-with-yaml-file/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3657
        "title": "使用 YAML 文件配置 Jenkins 流水线",
LinuxSuRen's avatar
LinuxSuRen 已提交
3658 3659
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3660 3661
        "tags": ["pipeline"],
        "description": "这也是一种自定义流水线 DSL 的方法",
LinuxSuRen's avatar
LinuxSuRen 已提交
3662 3663 3664 3665 3666
        "content": " 几年前,我们的 CTO 写了一篇关于 使用 Jenkins 和 Docker 为 Ruby On Rails 应用提供持续集成服务 的文章。这些年,我们一直使用这个 CI 流水线解决方案,直到我们最近决定做一次升级。为什么呢?\n Jenkins 的版本过低,已经很难升级 Wolox 过去几年增长显著,一直面临着如何伸缩的问题 只有极少数人如何修复 Jenkins 服务的问题 配置 Jenkins 任务不是一件简单的任务,使我们的项目启动过程变慢 更改每个作业运行的命令也不是一件简单的任务,并且有权限更改的人并不多。 Wolox 拥有广泛的项目,语言种类繁多,使得这个问题尤为突显。  考虑到这些问题,我们开始深入研究最新版的 Jenkins,看看如何提升我们的 CI 服务。我们需要构建一个新的CI服务,至少要解决以下问题:\n 支持 Docker 构建。我们的项目依赖的一个或多个 Docker 镜像的执行(应用,数据库,Redis 等) 如有必要,易于配置和复制 易于增加新项目 易于修改构建步骤。工作在项目上的所有人都应该能修改它,如果他们希望执行 npm install 或 yarn install  安装Jenkins和Docker 安装 Jenkins 非常简单,直接从 官方教程 选择一种方式安装。\n以下是我们在 AWS 上的安装步骤:\nsudo rpm — import https://pkg.jenkins.io/debian/jenkins.io.key sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins.io/redhat/jenkins.repo sudo yum install java-1.8.0 -y sudo yum remove java-1.7.0-openjdk -y sudo yum install jenkins -y sudo yum update -y sudo yum install -y docker  从 GitHub 上自动添加项目 从 Github 上自动添加项目可以通过 GitHub Branch Source 插件实现。它能将 GitHub 的组织中符合规则的项目自动添加到 Jenkins 中。唯一的约束就是在每一个分支下都必须有一个 Jenkinsfile,用于描述如何构建项目。\n易于修改的配置 我们之前使用 Jenkins 最痛苦的是修改项目的构建步骤。在 Jenkins 任务中,你会看到像以下代码(用于构建):\n#!/bin/bash +x set -e # Remove unnecessary files echo -e \u0026quot;\\033[34mRemoving unnecessary files...\\033[0m\u0026quot; rm -f log/*.log \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null rm -rf public/uploads/* \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null # Build Project echo -e \u0026quot;\\033[34mBuilding Project...\\033[0m\u0026quot; docker-compose --project-name=${JOB_NAME} build # Prepare test database COMMAND=\u0026quot;bundle exec rake db:drop db:create db:migrate\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; docker-compose --project-name=${JOB_NAME} run \\ -e RAILS_ENV=test web $COMMAND # Run tests COMMAND=\u0026quot;bundle exec rspec spec\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; unbuffer docker-compose --project-name=${JOB_NAME} run web $COMMAND # Run rubocop lint COMMAND=\u0026quot;bundle exec rubocop app spec -R --format simple\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; unbuffer docker-compose --project-name=${JOB_NAME} run -e RUBYOPT=\u0026quot;-Ku\u0026quot; web $COMMAND  在构建步骤后,执行 Docker 构建的清理工作:\n#!/bin/bash +x docker-compose --project-name=${JOB_NAME} stop \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker-compose --project-name=${JOB_NAME} rm --force \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker stop `docker ps -a -q -f status=exited` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker rm -v `docker ps -a -q -f status=exited` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker rmi `docker images --filter 'dangling=true' -q --no-trunc` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null  尽管这些命令并不复杂,但是更改其中的任何命令都需要具有权限的人员来操作相应的 Jenkins 任务,并清楚知道自己需要做什么。\nJenkinsfile的成与败 使用当前的 Jenkins 版本,我们可以利用 Jenkins pipeline 对我们的构建流进行建模,并保存到一个文件中。 该文件会被签入代码库。因此,任何有权访问它的人都可以修改其中的步骤。棒极了。\nJenkins 流水线还支持:\n Docker 及多个镜像可用于构建 使用 withEnv 设置环境变量,还支持很多其它内建的 函数  这为 Wolox 提供了完美的用例。我们可以将构建配置写入到一个被检入到代码库的文件中,并且允许任务有权限访问的人修改。但是,一个简单的 Rails 项目的 Jenkinsfile 看起来却像这样:\n# sample Jenkinsfile. Might not compile node { checkout scm withEnv(['MYTOOL_HOME=/usr/local/mytool']) { docker.image(\u0026quot;postgres:9.2\u0026quot;).withRun() { db -\u0026gt; withEnv(['DB_USERNAME=postgres', 'DB_PASSWORD=', \u0026quot;DB_HOST=db\u0026quot;, \u0026quot;DB_PORT=5432\u0026quot;]) { docker.image(\u0026quot;redis:X\u0026quot;).withRun() { redis -\u0026gt; withEnv([\u0026quot;REDIS_URL=redis://redis\u0026quot;]) { docker.build(imageName, \u0026quot;--file .woloxci/Dockerfile .\u0026quot;).inside(\u0026quot;--link ${db.id}:postgres --link ${redis.id}:redis\u0026quot;) { sh \u0026quot;rake db:create\u0026quot; sh \u0026quot;rake db:migrate\u0026quot; sh \u0026quot;bundle exec rspec spec\u0026quot; } } } } } } }  这样的文件不仅难以理解,还难以修改。这样的构建逻辑非常容易被破坏,如果你不熟悉 Groovy。如果你对 Jenkins 流水线是如何工作的一无所知,就更容易了。这样,修改或增加一个新的 Docker 镜像就变得不简单,也容易导致混淆。\n通过 YAML 配置 Jenkins 流水线 就个人而言,我总是期望为 CI 配置简单的配置文件。这次我们有机会构建使用 YAML 文件配置的 CI。经过分析,我们总结出以下这样的 YAML,它已经能满足我们的需求:\nconfig: dockerfile: .woloxci/Dockerfile project_name: some-project-name services: - postgresql - redis steps: analysis: - bundle exec rubocop -R app spec --format simple - bundle exec rubycritic --path ./analysis --minimum-score 80 --no-browser setup_db: - bundle exec rails db:create - bundle exec rails db:schema:load test: - bundle exec rspec security: - bundle exec brakeman --exit-on-error audit: - bundle audit check --update environment: RAILS_ENV: test GIT_COMMITTER_NAME: a GIT_COMMITTER_EMAIL: b LANG: C.UTF-8  它描述了项目基本的配置、构建过程中需要的环境变量、依赖的服务、还有构建步骤。\nJenkinsfile + Shared Libraries = WoloxCI 经过调研 Jenkins 和流水线之后,我们发现可以通过扩展共享库(shared libraries)来实现。共享库是用 Groovy 编写的,可以导入到流水线中,并在必要时执行。\n如果你细心观察以下 Jenkinsfile,你会看到代码是一个接收闭包的方法调用链,我们执行另一个方法将一个新的闭包传递给它。\n# sample Jenkinsfile. Might not compile node { checkout scm withEnv(['MYTOOL_HOME=/usr/local/mytool']) { docker.image(\u0026quot;postgres:9.2\u0026quot;).withRun() { db -\u0026gt; withEnv(['DB_USERNAME=postgres', 'DB_PASSWORD=', \u0026quot;DB_HOST=db\u0026quot;, \u0026quot;DB_PORT=5432\u0026quot;]) { docker.image(\u0026quot;redis:X\u0026quot;).withRun() { redis -\u0026gt; withEnv([\u0026quot;REDIS_URL=redis://redis\u0026quot;]) { docker.build(imageName, \u0026quot;--file .woloxci/Dockerfile .\u0026quot;).inside(\u0026quot;--link ${db.id}:postgres --link ${redis.id}:redis\u0026quot;) { sh \u0026quot;rake db:create\u0026quot; sh \u0026quot;rake db:migrate\u0026quot; sh \u0026quot;bundle exec rspec spec\u0026quot; } } } } } } }  Groovy 语言足够灵活,能在在运行时创建声明式代码,这使我们能使用 YAML 来配置我们的流水线!\nWolox-CI介绍 wolox-ci 诞生于 Jenkins 的共享库。以下是关于 Wolox-CI 的具体使用方式。\n使用 wolox-ci,Jenkinsfile 被精简成:\n@Library('wolox-ci') _ node { checkout scm woloxCi('.woloxci/config.yml'); }  它会检出代码,然后调用 wolox-ci。共享库代码会读取到 YAML 文件,如下:\nconfig: dockerfile: .woloxci/Dockerfile project_name: some-project-name services: - postgresql - redis steps: analysis: - bundle exec rubocop -R app spec –format simple - bundle exec rubycritic –path ./analysis –minimum-score 80 –no-browser setup_db: - bundle exec rails db:create - bundle exec rails db:schema:load test: - bundle exec rspec security: - bundle exec brakeman –exit-on-error audit: - bundle audit check –update environment: RAILS_ENV: test GIT_COMMITTER_NAME: a GIT_COMMITTER_EMAIL: b LANG: C.UTF-8  然后,Jenkins 就会执行你的构建任务。\n共享库有一个好处是我们可以集中扩展和修改我们的共享库代码。一旦添加新代码,Jenkins 就会自动更新它,还会通知所有的任务。\n由于我们有不同语言的项目,我们使用 Docker 来构建测试环境。WoloxCI 假设有一个 Dockerfile 要构建,并将在容器内运行所有指定的命令。\nconfig.yml 各部分介绍 config部分 这是 config.yml 的第一部分,用于指定基本配置,包括项目的名称,Dockerfile 的路径。Dockerfile 用于构建镜像,所有的命令都运行在该镜像的容器中。\nServices 部分 这部分定义了哪些服务被暴露到容器中。WoloxCI 支持以下开箱即用的服务:postgresql、mssql 和 redis。你还可以指定 Docker 镜像的版本。\n增加一个新的服务类型也不难。你只需要在该目录下(https://github.com/Wolox/wolox-ci/tree/development/vars)添加,然后告诉共享库该服务是如何被转换的,如https://github.com/Wolox/wolox-ci/blob/development/src/com/wolox/parser/ConfigParser.groovy#L76\nSteps 部分 在此部分列出的命令,都会被运行在 Docker 容器中。你可以在 Jenkins 界面上看到每一步的执行结果。\nEnvironment 部分 如果构建过程需要一些环境变量,你可以在这部分指定它们。Steps 部分中描述的步骤执行过程中,Docker 容器会提供你设置好的所有环境变量。\n总结 目前,WoloxCI 还在我们所有项目中一小部分项目进行测试。这让有权限访问它的人通过 YAML 文件更改构建步骤。这是对我们 CI 工作流程来说是一个重大改进。\nDocker 使我们轻松更换编程语言,而不用对 Jenkins 安装做任何的更改。并且,当检查到 GitHub 组织中的新项目(项目中有 Jenkinsfile)时,Jenkins GitHub Branch Source 插件会自动添加新的 Jenkins 项目。\n所有这些改进节约了我们维护 Jenkins 的大量时间,并使我们可以轻松扩展而无需任何额外配置。\n译者小结 本文最大的亮点是它介绍了一种实现自定义构建语言的方式。通过 Jenkins 的共享库技术,将构建逻辑从 Jenkinsfile 中移到了 YAML 文件中。同样的,我们可以将构建逻辑移动 JSON 文件中,或者任何格式的文件中,只你的共享库能解析它,并将它转换成 Jenkins 能理解的格式。\n",
        "auhtor": "Matias De Santi",
        "translator": "zacker330",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3667
    },
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%85%AC%E5%91%8A/",
        "title": "公告",
        "type": "tags",
        "date": "2020-02-12 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3681
    {
3682
        "uri": "https://jenkins-zh.cn/tutorial/pipeline/shared-library/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693
        "title": "共享库",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待补充\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3694
    {
3695 3696
        "uri": "https://jenkins-zh.cn/about/",
        "title": "关于我们",
LinuxSuRen's avatar
LinuxSuRen 已提交
3697
        "type": "about",
3698
        "date": "2019-09-07 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3699
        "tags": [],
3700 3701
        "description": "有关于 Jenkins 中文社区相关介绍",
        "content": "Jenkins 中文社区是由 Jenkins 国内的爱好者、贡献者组成,共同推广以及完善 CI/CD 技术的学习试用和落地。我们秉承开源的精神,在社区治理上高度开放,代码、文档以及设计等开源免费,致力于为我们的用户带来更好的体验。\n每个双周周三 21:00 的社区例会上,我们会公开讨论社区的事物。\n请准守我们的行为规范,文明留言。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
3702 3703 3704 3705
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3706
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3707
    {
3708 3709 3710
        "uri": "https://jenkins-zh.cn/about/about-site/",
        "title": "关于本站",
        "type": "about",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3711
        "date": "0001-01-01 00:00:00 +0000 UTC",
3712 3713 3714 3715 3716
        "tags": [],
        "description": "本站的架构",
        "content": "Jenkins 中文社区站点是基于 Hugo 生成的静态文件,托管在 GitHub Page 上。下面列出相关的源码位置:\n 网站内容 网站主题 微信订阅号  ",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3717 3718 3719
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3720
    {
3721
        "uri": "https://jenkins-zh.cn/tutorial/notify/email/email/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732
        "title": "在 Jenkins 中配置邮件服务器",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 我们需要在系统管理》系统设置中配置邮件服务器的信息。\n在邮件通知区域,给出类似如下的配置:\n   配置项 样例值 说明     SMTP服务器 smtp.exmail.qq.com    用户默认邮件后缀 @jenkins-zh.cn    SMTP服务器 smtp.exmail.qq.com    用户名 demo@jenkins-zh.cn    密码 demo    使用SSL协议     SMTP端口 465    Reply-To Address demo@jenkins-zh.cn    字符集 UTF-8     腾讯企业邮箱 上面给出的例子就是腾讯企业邮箱的配置,对于密码部分,我们需要生成客户端密码。\n流水线 当我们通过上面的步骤,将邮件服务器配置成功后,就可以使用类似如下的流水线步骤来发送邮件了。\nmail bcc: '', body: 'Here is the content.', cc: 'demo@jenkins-zh.cn', from: '', replyTo: '', subject: 'subject', to: 'demo@jenkins-zh.cn'\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3733
    {
3734
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-16-webhook-firewalls/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3735
        "title": "在安全防火墙内通过 WebHook 触发构建",
LinuxSuRen's avatar
LinuxSuRen 已提交
3736 3737
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3738
        "tags": ["jenkins", "webhooks", "security"],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3739
        "description": "谁说局域网里就不能带 GitHub 的 WebHook 玩?",
LinuxSuRen's avatar
LinuxSuRen 已提交
3740 3741 3742 3743 3744
        "content": " 在这篇文章中,我将向大家展示,如何让运行在防火墙内的 Jenkins 依然可以实时地收到 GitHub 的 WebHook。当然,你也可以把这个方法应用到如 BitBucket、 DockerHub 或任何可以推送 WebHook 的其他服务中。但是,下面的步骤仅适用于托管在 GitHub 上的项目。\n什么是 WebHook 简单地描述下什么是 WebHook:事件消息(通常是 JSON,也可以是其他的)由服务端以 HTTP(S) 协议发送到监听的客户端。\n事件流自左到右,Jenkins 会监听类似 /github-webhook/ 或 /dockerhub-webhook/ 等路径上的 HTTP 请求,唤醒并执行一些任务。\nGitHub 或 BitBucket 可能会报告一个新的提交或 PR,DockerHub 报告一个上游的镜像发生了变更。这些事情的共同之处在于,它们会推送给 Jenkins,并期待可以推送成功(例如:可以访问到 Jenkins)。在网络是开放的情况下时,例如 GitHub 企业版 或 Jenkins 在监听公网时,这是可以正常工作的。\n内网环境 当有东西挡在中间时,也就是防火墙:\n(_按照行业标准,所有防火墙都必须能起到屏障的作用。因此,无论如何,请不要在你的组织内搞破坏_)\n当你在笔记本电脑上运行 Jenkins 并希望从 GitHub 接收 WebHook 时,这也是一样的。可能是为了测试你的设置,也可能是为了在 Mac 上运行 iOS 版本构建,又或者是部分网络没有暴露在互联网中,这都是合理的。 除非你的笔记本电脑可以让整个互联网访问到(这当然不太可能),或者你的网络配置得恰到好处,否则网络连接将无法流动,此时 WebHook是不可用的。\n没关系,我们可以退而求其次,使用轮询变更的方式。只是这样很糟糕。你会用尽 API 配额,还无法实时地获取变更,这真的不是一个好方法。\n问题可能也是机会 我们可以解决这个问题,但也可以把这个视为一个机会。有的东西在互联网中不可访问,或者以某些默认的方法锁定是一个特色,不是一个 Bug。你可以很大程度上减少你的攻击面,同时可以进行深度防护:\n一个 WebHook 转发服务 输入 link:https://smee.io/[Smee] 这个很容易记住的名字。这是一个由 GitHub 提供的 link:https://github.com/probot/smee[开源软件项目],还能以服务的方式托管在 GitHub 上。这可以为你捕获并转发 WebHook。我会用一个图来给你解释它。\nGitHub 把一个事件(该场景下是通过 HTTPS/json)推送给 Smee.io(也就是圆圈标记的部分,暴露在互联网上并能被 GitHub 访问到),而 Jenkins 通过一个客户端使用一个向外的连接订阅 Smee 。注意箭头的方向:Jenkins 只有一个向外的连接。\n这一点很重要,只要防火墙允许向外访问就可以工作(像 NAT 以及其他网络通常就是这样的)。如果 Jenkins 无法访问外部的任何服务,那么,本文也就当然不会有什么帮助了(但是这通常不会出现的)。\n设置 步骤1:首先,访问 https://smee.io/ 并点击 “Start a new channel”:\n你会得到一个唯一的 URL(你应该拷贝出来以便后续使用):\n然后,在你运行 Jenkins 的地方安装 smee 客户端:\nnpm install --global smee-client\n(这让 smee 命令行客户端可以接收并转发 WebHook)。\n现在,启动 smee 客户端并指向你的 Jenkins。在该案例中,我的 Jenkins 运行在 8080 端口(这是默认的,如果在你的笔记本上运行的话,根据需要修改端口和 smee 地址):\nsmee --url https://smee.io/GSm1B40sRfBvSjYS --path /github-webhook/ --port 8080\n这样的话,会连接 smee 服务并转发 WebHook 到 /github-webhook/(最后的斜线很重要,不要丢了)。当运行起来,你将会从日志里看到,它已经连接并转发 WebHook。只要你希望能收到 WebHook 就需要保持该命令的运行。\n下一步,你需要配置一个使用 GitHub 的流水线。这里我从头开始配置。如果你已经有了一个的话,可以跳过:\n我选择 GitHub 作为代码仓库:\n然后,选择你的仓库。这将会设置好来准备接收来自 GitHub 的 WebHook(如果你已经有了流水线,并使用 GitHub 作为 SCM 源,那么也是可以的)。\n最后一步,是告诉 GitHub 为那个仓库(或组织也可以)发送 WebHook 事件给 Smee(最终会由 Jenkins 接收到)。\n选择你的 GitHub 仓库设置选项卡,并点击 “add webhook”:\n然后,配置 WebHook:\n 粘贴从上面步骤中拷贝的 smee 的 URL 选择 application/json 作为内容类型 选择 send everything(你可以选择你想要的事件,但我只是处于简单这么做)。 点击 Add Webhook(或 update)  它看起来应该像这样:\n好,现在 WebHook 应该可以了。你可以在你的仓库中添加一个变更,并稍后检查构建状态:\n祝你好运!\n",
        "auhtor": "michaelneale",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3745
    },
3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%9C%A8%E7%BA%BF%E5%88%86%E4%BA%AB/",
        "title": "在线分享",
        "type": "tags",
        "date": "2019-06-09 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3759
    {
3760
        "uri": "https://jenkins-zh.cn/tutorial/management/backup-restore/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771
        "title": "备份与恢复",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "备份与恢复\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%A4%96%E6%8C%82%E7%A8%8B%E5%BC%8F-%E5%AE%89%E5%85%A8-%E6%80%A7%E8%83%BD-gsoc-gsoc2019/",
        "title": "外挂程式 安全 性能 Gsoc Gsoc2019",
        "type": "tags",
        "date": "2019-10-28 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3785
    {
3786
        "uri": "https://jenkins-zh.cn/tutorial/pipeline/multi-branch/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797
        "title": "多分支流水线",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待补充\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%AE%B9%E5%99%A8%E5%8C%96/",
        "title": "容器化",
        "type": "tags",
        "date": "2020-02-21 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%AF%BC%E5%B8%88/",
        "title": "导师",
        "type": "tags",
        "date": "2019-08-16 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%BC%80%E6%BA%90/",
        "title": "开源",
        "type": "tags",
        "date": "2019-07-30 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3837
    {
3838
        "uri": "https://jenkins-zh.cn/tutorial/plugin-dev/pipeline/demo/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849
        "title": "待完善",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待完善\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3850
    {
3851
        "uri": "https://jenkins-zh.cn/tutorial/management/backup-restore/demo/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862
        "title": "待补充",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待补充\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875
    {
        "uri": "https://jenkins-zh.cn/tags/%E5%BF%97%E6%84%BF%E8%80%85/",
        "title": "志愿者",
        "type": "tags",
        "date": "2019-08-09 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3876
    {
3877
        "uri": "https://jenkins-zh.cn/tutorial/management/auth/lost-password/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888
        "title": "忘记密码",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " 如果忘记了 Jenkins 的管理员密码的话,也不用担心,只要你有权限访问 Jenkins 的根目录,就可以轻松地重置密码。\n通常情况 Jenkins 的根目录,默认是在当前用户(启动 Jenkins 的操作系统用户)目录的 .jenkins 中。对于 unix 系统而言,也就是 ~/.jenkins。\n我们打开配置文件 vim ~/.jenkins/config.xml 后,把字段 useSecurity 的值设置为 false,然后重新启动 Jenkins。你就会发现不需要登陆也能进入管理页面。\n进入页面系统管理-\u0026gt;全局安全配置中,选择启用安全,然后在授权策略中勾选任何用户可以做任何事(没有任何限制)。保存后,找到你希望重置密码的用户,输入新的密码即可。\n其他情况 如果 Jenkins 的根目录在当前用户目录下话,可以通过查找对应进程的方式来确认,下面以 Linux 系统为例说明:\n~# ps -ef | grep jenkins root 26386 26359 0 Jul23 pts/0 00:24:04 java -Duser.home=/var/jenkins_home -Djenkins.model.Jenkins.slaveAgentPort=50000 -jar /usr/share/jenkins/jenkins.war  分析上面的输出,可以得出,该 Jenkins 的根目录为:/var/jenkins_home。\nJENKINS_HOME 如果你的环境变量里设置了 JENKINS_HOME 的话,那么, Jenkins 的根目录就可能是 JENKINS_HOME 指向的目录。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3889
    {
3890
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/06/2019-06-24-becoming-contributor-newbie-tickets/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901
        "title": "成为一名 Jenkins 贡献者:对新手友好的工单",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": ["jenkins", "community", "developer", "contributing", "newcomer"],
        "description": "修复 Jenkins 核心中的一个缺陷——从工单到 PR,再到发布",
        "content": " 两个月前,我发表了一篇介绍性文章, 成为一名 Jenkins 贡献者的旅程。在那篇第一次发表的文章 review 过后,学习到了我们可以参与和贡献的多种途径。 因此,在这个站点仓库中有对首次、基础的贡献的描述。\n现在,我们将会在这篇文章中探索更多高级的贡献,向 Jenkins 核心中提交代码。\n从工单和过程开始 新手贡献指导以及 Jenkins Jira 查看位于 jenins.io 上的开发者章节可能是最好的起点, 参考链接也很方便。同时,向 Jenkins 贡献的新手指导也很有用,因为它指出了不同的仓库、工具(例如问题跟踪系统)以及治理文档。 此外,它还描述了提交消息、代码风格约定、PR 指导等的最佳实践。\n一旦我们对之前描述的有了一般性的了解,并想要真正地开始编码,我们可能会对该做些什么感到困惑。\n似乎浏览Jenkins 问题跟踪系统是顺其自然 的下一步,因为那里充满了已经由社区报告了的潜在的缺陷和待改进的部分。然而,你很容易被无数的可能性列表所淹没。 请记住一点,对于一个像这样有十年历史之久的项目,很多是为新手准备的。因此,通过newbie-friendly tickets来过滤可能是最好的主意。\n选择一个工单 在我案例中,我花了一些时间来浏览带 newbie-friendly 标签的工单,直到发现了一个我似乎感兴趣并看起来有能力修复的:\n过程 在这个阶段,当我们准备接手这个工单时,最好让社区中的其他人知道我们正在开始解决它。我们可以很容易做到这一点, 只要把工单分配给我们自己即可(查看工单概览下的 “_Assign_” 按钮)。\n在 Jenkins 的 Jira 中把工单分配给我们自己的话,可以让其他的贡献者知道我们正在处理;另外,为了保证其他人有兴趣对此一起做贡献时,可以知道 该去联系谁或者如何询问状态。也就是说,把工单分配给你自己,并不意味着其他贡献者就无法继续推进。Jenkins 是一个开源项目,欢迎任何人创建他们自己 的 PR,因此,任何人都可以在工单中提出自己的方案。但是,你也能想到,如果工单分配给某个人的话,大多数人在开始工作前也可能会去联系承接人。\n与之相关的是,请牢记当我们把工单分配给自己时,不应该在这个工作上拖延太久。其他的贡献者,可能会由于工单已被分配而忽略。\n当我们马上就要开始工作时,推荐的做法是先点击\u0026rdquo;Start Progress\u0026ldquo;按钮。这个动作,会把状态修改为“_In progress_”,对社区而言, 意味着我们正在处理这个工单。\n在我们的电脑设置必要的工具 配置,安装和测试 正如在该旅程的第一篇文章中描述的,开始为某个仓库做贡献的第一步 是首先派生到我们自己的 GitHub 账号下,然后,克隆到你的电脑上。\n正如,在 Jenkins Core 仓库中的CONTRIBUTING 文件里 所描述的,让仓库在本地运行的必要步骤。它包括,安装必要的开发工具:Java Development Kit (https://adoptopenjdk.net/[OpenJDK] 为推荐的选择),Maven 以及任意支持 Maven 项目的 IDE。注意,安装 JDK 和 Maven 的步骤在贡献指南中有链接。\n当安装并配置好所需要的工具后,我们就准备好了在本地构建 Jenkins,也可以运行测试。\n开始干活 复查工单细节 现在,我准备好开始处理工单了,我必须仔细查看细节,以便全面地理解问题所在。\n我计划处理的工单的描述中有两个链接。第一个是,体现真正缺陷的截图。它展示出当点击按钮\u0026rdquo;所有\u0026ldquo;时,几个不兼容的插件是如何被选中的,甚至尽管预期的行为是仅选中兼容的插件。 第二个链接是代码片段的引用,它展示了当检查一个插件更新是否与当前版本兼容时需要考虑的校验。\n本地复现问题 尽管我现在已经对该缺陷的细节了解清楚了,但还没有亲眼见过。因此,对我而言,下一个符合逻辑的步骤就是在本地复现。\n为了在我们的电脑上复现该缺陷,可以利用源代码构建出 Jenkins的本地 war 文件,或者也可以 下载最新可用的 Jenkins 版本,并在本地运行。 当我处理该工单时,最新可用的版本为 2.172;当我自行构建源码时看到的版本为 2.173-SNAPSHOT,也就是社区正在进行的下一个版本。\n通常来说,在本地复现缺陷是一个好的主意,这不仅仅是为了能更好的理解,也可以确保问题真实存在。它可能只在报告者的环境中发生(例如:一些用户 错误的配置)。或者,是已经修复了的久的缺陷。也有可能是某人在工单还没有提出时已经修复了。或者,可能是贡献者在修复后忘记了更新工单的状态。\n因此,基于以上的所有原因,我在本地运行最新版本的 Jenkins。从终端进入到 war 文件所在的目录,然后运行 java -jar jenkins.war, 就会在本地启动 Jenkins,访问路径为 http://localhost:8080。\n从首页上,切换到插件管理页面(在左侧点击 “_管理 Jenkins_” 的链接,然后选择在列表中选择 “_管理插件_”)。\n在管理插件的页面中,有一个插件更新的列表。对我而言,由于复用了之前安装的旧的 JENKINS_HOME 目录,已经有一些插件出现在这里,并需要 更新。这使得我可以测试这个假定会失败的行为。\n当我点击了底部的“全选”选项,得到了如下结果:\n正如在它在工单中报告的,该行为是不一致的。在上一个版本中,\u0026rdquo;全选\u0026ldquo;的行为已经改变(试图改进),是为了只选中兼容的插件。然而, 正如在截图中看到的,该行为并未像期待的那样。现在,不管是“全选”还是“兼容性的“插件都会被选中,一些有兼容性问题的插件也会被无意中被选中。\n尝试修复 当在阅读原始 PR 中关于“全选”行为变更的讨论时,我看到了一个采用分离的\u0026rdquo;兼容性的\u0026ldquo;按钮的建议,而保留\u0026rdquo;全选\u0026ldquo;按钮的传统行为。 我喜欢这个主意,因此,我决定把它作为我的变更提议的一部分。\n在这个阶段,我对需要做的变更有了清晰的想法。包括:1)界面UI,为“兼容的”插件增加一个按钮,2)当按钮点击后 JS 代码应用变更,然后3) 后端的方法来决定一个插件是否为兼容的。\n应用变更 正如在贡献指南中推荐的,我创建了一个独立的 feature 分支来处理这个工单。\n复查完代码后,我花了一些时间来搞清楚应该做哪些修改,包括前端和后端的代码。关于我修改的更多细节,你可以看一下在我的 PR 中的变更。\n简单总结下,我了解到经典的 Jenkins UI 是使用Jelly来编写的, 在了解它的基本原理后,我修改文件 index.jelly 让包括新的选择器,并关联检查兼容性插件的函数到这个选择器上,当点击 “_全选_” 时 复用已有的函数 “toggle” 来勾选所有的复选框。我同时必须要为未经检查兼容性的情况修改 JavaScript 函数 checkPluginsWithoutWarnings 的行为,因为现在已经有了一个真正的 “_全选_” 按钮,未经检查的情况不再考虑。然后,我在类 UpdateSite.java 中添加了一个后端的 Java 方法 isCompatible, 来调用所有检查不同的兼容性的方法,并最终返回一个结果。在这次修改中,我还增加了一个自动化测试来验证该方法的正确行为,为项目增加了代码测试覆盖率。 最后,我修改了文件 table.jelly 来从前端调用后端的方法,替换了之前没有把所有类都考虑进去的方法。\n正如你所看到的,变更涉及到了不同的技术,甚至你遇到的是简单的场景,却不是很熟悉。我的建议是,不要让这些困难让你停止了前进的脚步。作为一名软件工程师, 我们应该专注于让我们永远不过时的技能,而不是只了解特定的技术; 在特定的场景下,要适应不同的框架,学习一切为了完成任务所需要的新技术,采用跨框架的原则和最佳实践以提供高质量的方案。\n结果 经过上面的修改后,UI 界面上出现一个新的选项,三个选项对应的行为也如预期的一致:\n发布变更 提交一个 Pull Request 在 Jenkins 核心仓库里的贡献指南中,有一章关于变更提议的内容,描述了为我们的变更创建一个 Pull Request (PR) 所必须要遵守的步骤。\n此外,这个仓库中还有一个PR 模板, 将会在创建一个新的 PR 时自动加载,作为一个让我们给复查者提供必要信息的基础。我们期望的是:工单链接,描述变更的变更日志条目, 完成提交者的检查单,并提醒期望的复查者(如果有的话)。\n在我的案例中,我在创建 PR 时遵照模板,完成了所有部分。 我添加了 Jira 工单链接,提供了两条变更日志条目,完成了提交者的检查单,并增加了三位期望的复查者(并介绍了我为什么认为条目的复查会是有价值的)。 我还添加了工单中提到的原始 PR 链接,以便提供更多的上下文。\n通过和合并的流程 正如在贡献指南中申明的,一个 PR 需要有两个人通过才能被合并;这可能需要几天到几周的时间。有时候,有一个复查者通过了,一周后没有额外的复查 也认为足够设置 PR 为 ready-for-merge。然而,合并所需要的时间以及通过的数量可能不同,这取决于变更的复杂度或者对 Jenkins Core 的影响面。\n当收到必要的通过建议后,一个 Jenkins Core 的维护者讲会把 PR 设置为 ready-for-merge,并会在准备下次发布时被合并到 master 分支。\n对我而言,在提交 PR (四月十四日)当天,我收到了 Daniel(工单的报告者,也是我“期望的复查者”)的复查。他给出了几个非常有用的建议, 我据此进行了修改。之后,Daniel 再次复查我的 PR 并给了一些小的备注,并被核准。之后一周,没有任何动态,我根据 Daniel 的建议增加了一些修改, 最后,Daniel 通过我的 PR,这使得 PR 添加上了 ready-for-merge 的标签,并在后来的某天被合并了(四月二十六日)。\n发布 每次新的发布,仓库的维护者会选择被添加 ready-for-merge 标记的 PR 合并到 master 分支,准备变更日志(通常会采用 PR 作者的提议)并 继续创建新的版本。此时,PR 的作者不需要有额外的参与。\n每周,Jenkins 都会发布一个新的版本,因此,当你的 PR 被合并后,你的变更非常有可能会成为下一个每周发布版的 Jenkins 的一部分。\n最终,你的变更也会到达长期支持 (LTS) 版本,这是一个不同的发布线,目标是更加保守的用户。 这个发布线是与每周发布的版本选择同步的,每12周一个最新的每周发布版会作为新的 LTS 版本基线。在此期间,中间的 LTS 版本只会包括重要的缺陷修复, 来自每周发布版 cherry-pick。新的功能通常会等到下一个 LTS 的基线被确定后。\n鉴于在这篇博客中描述的例子,在合并后 *它发布在了 Jenkins 2.175*(每周发布版)。并可能会包括在下一个 LTS 中, 应该是在下个月发布(2019年6月)。\n完工! 就这么多!到此,我们已经覆盖了向 Jenkins Core 提出一个新的提议的完整生命流程。我们回顾了从流程的开始,在 Jenkins 缺陷跟踪系统中挑选 一个工单;一直到最后,发布我们的变更到一个新的 Jenkins 版本。\n如果你从未但是想要做贡献,我希望这篇文章能够激励你回到标记了 newbie-friendly 的工单列表中, 找到一个你感兴趣的,按照上面描述的步骤,知道你看到自己的变更发布到了一个新的 Jenkins 版本中。\n记住,不要尝试在你的首个工单中解决一个复杂的问题,有很多更轻松的方法你可以做贡献,而且,不管多小都是有帮助的!\n",
        "auhtor": "romenrg",
        "translator": "linuxsuren",
        "original": "https://jenkins.io/blog/2019/05/30/becoming-contributor-newbie-tickets/",
        "poster": ""
    },
3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940
    {
        "uri": "https://jenkins-zh.cn/tags/%E6%8B%9B%E5%8B%9F/",
        "title": "招募",
        "type": "tags",
        "date": "2019-08-16 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E6%8C%81%E7%BB%AD%E4%BA%A4%E4%BB%98/",
        "title": "持续交付",
        "type": "tags",
        "date": "2019-08-14 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E6%8C%81%E7%BB%AD%E6%B5%8B%E8%AF%95/",
        "title": "持续测试",
        "type": "tags",
        "date": "2019-08-14 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
3941
    {
3942
        "uri": "https://jenkins-zh.cn/tutorial/management/plugin/update-center/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3943 3944 3945 3946 3947
        "title": "插件更新中心",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
3948
        "content": " Jenkins 安装完成后,默认的插件更新中心地址为 https://updates.jenkins.io/update-center.json\n除了正式版本以外,部分插件也会发布一些 alpha 或者 beta 版本,以便让部分用户体验实验性功能。我们可以在插件管理-》高级部分,修改为如下地址:\nhttps://updates.jenkins.io/experimental/update-center.json\n镜像地址    维护方 镜像中心地址     Jenkins 中文社区 https://updates.jenkins-zh.cn/update-center.json   清华大学 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json   华为开源镜像站 https://mirrors.huaweicloud.com/jenkins/updates/update-center.json    ",
LinuxSuRen's avatar
LinuxSuRen 已提交
3949 3950 3951 3952 3953
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3954
    {
3955
        "uri": "https://jenkins-zh.cn/tutorial/api/plugin/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966
        "title": "插件相关",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
3967
    {
3968
        "uri": "https://jenkins-zh.cn/tutorial/management/plugin/",
LinuxSuRen's avatar
LinuxSuRen 已提交
3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979
        "title": "插件管理",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "插件管理\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3980
    {
3981
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-security-spring-cleaning/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3982
        "title": "春季安全清查",
LinuxSuRen's avatar
LinuxSuRen 已提交
3983 3984
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3985
        "tags": ["plugins", "security"],
LinuxSuRen's avatar
LinuxSuRen 已提交
3986
        "description": "Jenkins 管理员们应该关注的安全问题",
LinuxSuRen's avatar
LinuxSuRen 已提交
3987 3988 3989 3990 3991
        "content": "今天我们公布了一个 安全报告, 主要是关于 Jenkins 的插件中 还没有被修复 的问题。 发生了什么?\nJenkins 安全团队将 漏洞反馈分类发布在 Jira 和我们的非公开邮件列表中。 一旦我们确定它不是由 Jenkins 安全团队成员维护的插件,我们会尝试将该问题通知插件维护者,以帮助我们开发,审查和发布修复。\n这种情况下,我们会发布 安全报告,将这些问题告知用户,即使没有发布修复版本。 这样可以让管理员作出决定,是否继续使用具有未解决的安全漏洞的插件。 今天发布的报告里大多数都是这样的安全问题。\n在这个列表中看到您感兴趣的插件并且想要帮忙?了解如何 认领一个插件。\n",
        "auhtor": "daniel-beck",
        "translator": "p01son6415",
        "original": "https://jenkins.io/blog/2019/04/03/security-advisory/",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
3992
    },
3993
    {
3994
        "uri": "https://jenkins-zh.cn/tutorial/best-practice/",
3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005
        "title": "最佳实践",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "Jenkins 应用最佳实践\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4006
    {
4007
        "uri": "https://jenkins-zh.cn/tutorial/scm/git/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019
        "title": "有关 Git 的教程",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "有关 Git 的教程\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
4020
        "uri": "https://jenkins-zh.cn/tutorial/scm/git/git/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032
        "title": "有关 Git 的教程",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待完善\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
4033
        "uri": "https://jenkins-zh.cn/tutorial/scm/svn/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045
        "title": "有关 svn 的教程",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "有关 svn 的教程\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
4046
        "uri": "https://jenkins-zh.cn/tutorial/scm/svn/svn/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057
        "title": "有关 svn 的教程",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待完善\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4058
    {
4059
        "uri": "https://jenkins-zh.cn/tutorial/api/core/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070
        "title": "核心",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083
    {
        "uri": "https://jenkins-zh.cn/tags/%E6%B2%BB%E7%90%86/",
        "title": "治理",
        "type": "tags",
        "date": "2020-02-12 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4084
    {
4085
        "uri": "https://jenkins-zh.cn/event/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096
        "title": "活动",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "Jenkins 社区相关活动安排及介绍",
        "content": "sdfsdds\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4097
    {
4098
        "uri": "https://jenkins-zh.cn/tutorial/pipeline/pipeline/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110
        "title": "流水线",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "待完善\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
4111
        "uri": "https://jenkins-zh.cn/tutorial/plugin-dev/pipeline/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122
        "title": "流水线插件",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "plugin dev\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148
    {
        "uri": "https://jenkins-zh.cn/tags/%E6%B5%8B%E8%AF%95/",
        "title": "测试",
        "type": "tags",
        "date": "2019-08-14 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E7%A4%BE%E5%8C%BA/",
        "title": "社区",
        "type": "tags",
        "date": "2020-02-12 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4149
    {
4150
        "uri": "https://jenkins-zh.cn/tutorial/management/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4151 4152 4153 4154 4155
        "title": "管理",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
4156
        "content": "jcli 是用 Go 语言编写的 Jenkins 命令行客户端, 可以帮助你轻松地管理多个 Jenkins 实例,更多细节介绍,请阅读官方文档。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
4157 4158 4159 4160 4161
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174
    {
        "uri": "https://jenkins-zh.cn/tags/%E7%B2%BE%E8%8B%B1%E7%BB%A9%E6%95%88/",
        "title": "精英绩效",
        "type": "tags",
        "date": "2020-03-02 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
4175
    {
4176
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-09-jenkins-evergreen/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
4177
        "title": "自动更新、易于使用的 Jenkins",
LinuxSuRen's avatar
LinuxSuRen 已提交
4178 4179
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
4180 4181
        "tags": ["jenkinsworld", "jenkinsworld2018", "evergreen"],
        "description": "借助 Evergreen 持续提供易于使用的 Jenkins",
LinuxSuRen's avatar
LinuxSuRen 已提交
4182 4183 4184 4185 4186
        "content": " 当我第一次 写 Jenkins Evergreen 相关的文章 , 后来被称为 \u0026ldquo;Jenkins Essentials\u0026rdquo;,我提到的一系列的未来的发展在接下来的几个月里已经变成了 现实 。 今年在旧金山举办的 DevOps World - Jenkins World 会议上,我会介绍 Jenkins Evergreen 背后哲学的更多细节,展示我们已经做了什么,并且讨论这个激进的 Jenkins 发行版的走向。\n正如我在第一篇博客以及 JEP-300 中所讨论的 Jenkins Evergreen 的前两大支柱是我们关注的要点.\n自动更新的发行版 不出所料, 实现安全、自动地更新Jenkins发行版(包括核心和插件)所需的机制需要很多的工作。在 Baptiste 的演讲中 他将讨论如何使 Evergreen \u0026ldquo;走起来\u0026rdquo;,而我会讨论 为何 自动更新的发行版很重要。\n持续集成和持续交付变得越来越普遍,并且是现代软件工程的基础 ,在不同的组织当中有两种不同的方式使用 Jenkins 。在一些组织当中,Jenkins 通过 Chef ,Puppet 等自动化工具有条不紊的被管理和部署着。然而在许多其他组织当中, Jenkins 更像是一个 设备 ,与办公室的无线路由器不同。当安装完毕,只要它能继续完成工作,人们就不会太多的关注这个设备。\nJenkins Evergreen 发行版通过确保最新的功能更新,bug 修复以及安全性修复始终能安装到 Jenkins 当中,\u0026ldquo;让 Jenkins 更像是一个设备\u0026rdquo;。\n除此之外, 我相信 Evergreen 能够向一些我们现在没有完全服务的团队提供良好的服务:这些团体希望能够以 服务 的形式使用 Jenkins 。我们暂时没有考虑提供公有云版本的 Jenkins 。我们意识到了自动接收增量更新,使用户可以在无需考虑更新 Jenkins 的情况下进行持续开发的好处。\n我相信 Jenkins Evergreen 可以并且可以提供相同的体验。\n自动配置默认值 Jenkins 平台真正强大的地方是可以为不同的组织提供不同的模式和做法。对于很多新用户来说,或一些只希望使用通用案例的用户来说, Jenkins 的灵活性与让用户做出合适的选择形成了悖论。使用 Jenkins Evergreen,很多常用的配置将自动配置,使 Jenkins 变成开箱即用的工具。\n默认情况下将包括 Jenkins 流水线和 Jenkins Blue Ocean,我们也删除了一些 Jenkins 的遗留功能。\n我们同样在使用非常棒的 Configuration as Code 进行工作, Configuration as Code 现在已经完成了1.0版本的发布, 我们通过它实现自动进行默认配置。\n现状 迄今为止,这个项目取得了重大的进展,我们非常高兴有用户开始尝试 Jenkins Evergreen,现在 Jenkins Evergreen 已经可以被 早期使用者 尝试. 不过我们现在 不 推荐在生产环境中使用 Jenkins Evergreen 。\n我们希望能够得到您的反馈和想法在我们的 Gitter channel !\n",
        "auhtor": "rtyler",
        "translator": "runzexia",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
4187
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4188
    {
4189
        "uri": "https://jenkins-zh.cn/tutorial/management/agent/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4190 4191
        "title": "计算节点",
        "type": "tutorial",
4192
        "date": "2020-02-27 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
4193 4194 4195 4196 4197 4198 4199 4200
        "tags": [],
        "description": "",
        "content": "计算节点的配置与管理\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
4201
    {
4202
        "uri": "https://jenkins-zh.cn/tutorial/management/auth/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213
        "title": "认证",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "认证\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252
    {
        "uri": "https://jenkins-zh.cn/tags/%E8%B4%A1%E7%8C%AE%E6%BF%80%E5%8A%B1/",
        "title": "贡献激励",
        "type": "tags",
        "date": "2019-09-05 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E8%BD%AF%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/",
        "title": "软件生命周期",
        "type": "tags",
        "date": "2019-08-14 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E8%BF%90%E8%90%A5%E8%BD%AC%E5%9E%8B/",
        "title": "运营转型",
        "type": "tags",
        "date": "2019-11-06 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
4253
    {
4254
        "uri": "https://jenkins-zh.cn/tutorial/management/auth/keyclock/",
LinuxSuRen's avatar
LinuxSuRen 已提交
4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265
        "title": "通过 KeyCloak 认证",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
4266
    {
4267
        "uri": "https://jenkins-zh.cn/tutorial/management/plugin/configuration-as-code/",
4268 4269 4270 4271 4272
        "title": "配置即代码",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
4273
        "content": " Jenkins Configuration as Code Plugin  允许用户将系统配置等 Jenkins 的配置信息写入到一个 YAML 文件中。这样,可以将 Jenkins 的配置标准化,便于在团队内部复用,易于传播、便于快速搭建开箱即用的 Jenkins 服务。\n借助这个插件,我们几乎不再需要通过人工在 UI 界面上点击的方式来配置 Jenkins 服务。而且,绝大部分其他插件几乎(甚至)不需要做任何调整,就可以与该插件兼容。\n配置文件加载流程    类型  描述     文件 $JENKINS_HOME/war/WEB-INF/jenkins.yaml 单一文件   目录 $JENKINS_HOME/war/WEB-INF/jenkins.yaml.d 加载该目录下所有以 yml,yaml,YAML,YML 为后缀的文件   系统属性 casc.jenkins.config    环境变量 CASC_JENKINS_CONFIG    系统配置 无 UI 配置    文件 $JENKINS_HOME/jenkins.yaml 查找顺序为:系统属性-\u0026gt;环境变量-\u0026gt;系统配置-\u0026gt;该文件,这个配置文件,只加载先找到的    资源加载协议 支持的 URI 协议包括:https, http, file\n如果不在上面协议的范围内的话,则尝试以文件(或目录)的方式加载。\n多配置文件 从上面可以看出来,CASC 是支持同时加载多个配置文件的。那么,如果多个配置文件中有相同字段的话,是怎么处理的呢?\n 数组:合并 相同字段:报错  CLI 除了可以在 UI 界面上操作 CasC 的相关功能,CLI 也有对应的支持。\n$ jcli casc Configuration as Code Usage: jcli casc [command] Available Commands: apply 从应用已有的配置 export 导出配置及代码的配置 open 在浏览器中打开配置及代码的页面 reload 重新加载配置及代码的配置 schema 获取配置及代码的结构  注意:该功能从 jcli v0.0.24 开始支持。详情,请参考对应的 PR 链接。\nRestful API 导出配置 curl -X POST -u admin:112e74ac1ded9b9af4854e594405819df9 http://localhost:8080/configuration-as-code/export\n查看 Schema curl -X POST -u admin:112e74ac1ded9b9af4854e594405819df9 http://localhost:8080/configuration-as-code/schema\n重新加载配置 curl -X POST -u admin:112e74ac1ded9b9af4854e594405819df9 http://localhost:8080/configuration-as-code/reload\n从请求中应用配置 curl -X POST -u admin:112e74ac1ded9b9af4854e594405819df9 http://localhost:8080/configuration-as-code/apply\n",
4274 4275 4276 4277 4278
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
    },
4279
    {
4280
        "uri": "https://jenkins-zh.cn/tutorial/management/mirror/",
4281 4282 4283 4284 4285
        "title": "镜像源",
        "type": "tutorial",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
4286
        "content": "下面是部署在中国的和 Jenkins 相关的镜像源。这里只是收录,无法保证源的可信度, 如果大家在使用的过程中,发现有任何问题后,可以在下面留言。\n   维护方 描述     清华大学 不同操作系统下的安装包,以及通用的 War 包,插件等   华为开源镜像站 不同操作系统下的安装包,以及通用的 War 包,插件等   腾讯云    北京理工大学    USTC     Jenkins 官方也给出了其他镜像源列表。\n下面是一些国外的镜像源\n   维护方 描述     XMisson     对于插件镜像源的配置,请参考这里的说明。\n",
4287 4288 4289 4290
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303
    },
    {
        "uri": "https://jenkins-zh.cn/tags/%E9%BB%91%E5%AE%A2%E6%9D%BE/",
        "title": "黑客松",
        "type": "tags",
        "date": "2019-08-16 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
4304
    }]