快速检测泄露的秘密
意外地将凭据传递到共享存储库似乎是一个小错误。 然而,后果可能很严重。 一旦攻击者获得您的密码或 API 密钥,他就会接管您的帐户,将您锁定并欺诈性地使用您的资金。 此外,可能会出现多米诺骨牌效应:访问一个帐户会打开其他帐户的访问权限。 风险很高,因此尽快查明泄露的秘密极其重要。
在此版本中,我们引入了该选项
确保适当的变更管理
随着它的发展和变得更加复杂,保持组织不同部分之间的一致性变得更加困难。 应用程序的用户越多、收入越高,合并不正确或不安全代码的后果就越严重。 对于许多组织来说,在合并代码之前确保适当的审查过程是一项严格的要求,因为风险非常高。
GitLab 11.9 为您提供了更多控制和更高效的结构,这要归功于
这使得组织能够实施复杂的解决流程,同时保持单个 GitLab 应用程序的简单性,其中问题、代码、管道和监控数据都是可见且可访问的,以便做出决策并加快解决流程。
ChatOps 现已开源
GitLab ChatOps 是一个功能强大的自动化工具,允许您运行任何 CI/CD 作业并直接在 Slack 和 Mattermost 等聊天应用程序中查询其状态。
就 ChatOps 而言,我们意识到此功能对每个人都有用,并且社区参与可以使该功能本身受益。
在 GitLab 11.9 中,我们
还有更多!
此版本中有很多很棒的功能,例如
最有价值员工(
最小化可行性产品 )本月得到了 Marcel Amirault 的认可(马塞尔阿米罗 )
Marcel 不断帮助我们改进 GitLab 文档。 他做了很多 提高文档的质量和可用性。 Domo arigato [非常感谢(日语)- 大约。 译]马塞尔,我们衷心感谢!
GitLab 11.9 版本中添加的主要功能
发现存储库中的秘密和凭据
(终极,黄金)
开发人员有时会无意中将机密和凭据泄露到远程存储库。 如果其他人可以访问此源,或者该项目是公开的,那么敏感信息就会暴露,攻击者可以利用这些信息来访问部署环境等资源。
GitLab 11.9 有一个新测试——“秘密检测”。 它扫描存储库的内容,查找 API 密钥和其他不应存在的信息。 GitLab 在合并请求小部件、管道报告和安全仪表板中的 SAST 报告中显示结果。
如果您已经为您的应用程序启用了 SAST,那么您无需执行任何操作,只需利用此新功能即可。 它也包含在配置中
解决合并请求的规则
(高级、终极、白银、黄金)
代码审查是每个成功项目的基本要素,但谁应该审查变更并不总是很清楚。 通常需要来自不同团队的审阅者:开发团队、用户体验团队、生产团队。
权限规则允许您通过定义授权批准者的范围和最小权限数来改进参与代码审查的人员之间的交互过程。 解决规则显示在合并请求小部件中,以便您可以快速分配下一个审阅者。
在 GitLab 11.8 中,默认情况下禁用权限规则。 从 GitLab 11.9 开始,它们默认可用。 在 GitLab 11.3 中我们引入了这个选项
将 ChatOps 移至核心
(核心、入门、高级、终极、免费、青铜、白银、黄金)
ChatOps 最初在 GitLab Ultimate 10.6 中引入,现已迁移到 GitLab Core。 GitLab ChatOps 提供了使用该功能通过 Slack 运行 GitLab CI 作业的能力
我们正在根据我们的要求开源此功能
功能参数审核
(高级、终极、白银、黄金)
添加、删除或更改功能参数等操作现在都会记录在 GitLab 审核日志中,以便您可以查看更改的内容和时间。 发生了事故,您需要看看最近发生了什么变化? 或者您是否只需要检查功能参数如何更改作为审核的一部分? 现在这很容易做到。
解决合并请求漏洞
(终极,黄金)
为了快速解决代码漏洞,过程必须简单。 简化安全补丁非常重要,这样开发人员就可以专注于他们的职责。 在 GitLab 11.7 中,我们
在 GitLab 11.9 中,此过程是自动化的。 无需离开 GitLab Web 界面即可修复漏洞。 合并请求是直接从漏洞信息窗口创建的,并且这个新分支将已经包含修复程序。 检查问题是否解决后,如果管道正常,则将修复添加到上游分支。
在组安全面板中显示容器扫描结果
(终极,黄金)
团队的安全仪表板使团队能够专注于对其工作最关键的问题,提供可能影响应用程序的所有潜在漏洞的清晰、详细的概述。 这就是为什么仪表板将所有必要信息集中在一处并允许用户在解决漏洞之前深入了解数据的原因。
在 GitLab 11.9 中,除了现有的 SAST 和依赖项扫描结果之外,容器扫描结果已添加到仪表板中。 现在,无论问题的根源如何,整个概述都集中在一处。
用于安全作业的 CI/CD 模板
(终极,黄金)
GitLab 的安全功能发展非常迅速,需要不断更新才能保持代码高效和安全。 当您管理多个项目时,更改工作的定义很困难。 我们还了解,在不确定最新版本的 GitLab 是否与当前的 GitLab 实例完全兼容的情况下,没有人愿意冒险使用它。
正是由于这个原因,我们在 GitLab 11.7 中引入了一种新的机制,用于使用定义作业
从 GitLab 11.9 开始,我们将为所有安全作业提供内置模板:例如, sast
и dependency_scanning
, - 兼容GitLab对应版本。
将它们直接包含在您的配置中,每当您升级到新版本的 GitLab 时,它们都会随系统一起更新。 管道配置不变。
定义安全作业的新方法是官方的,不支持任何其他以前的作业定义或代码片段。 您应该尽快更新您的定义以使用新关键字
template
。 GitLab 12.0 或其他未来版本中可能会删除对任何其他语法的支持。
GitLab 11.9 中的其他改进
回复评论
(核心、入门、高级、终极、免费、青铜、白银、黄金)
GitLab 有相关主题的讨论。 到目前为止,撰写原始评论的人必须从一开始就决定是否想要进行讨论。
我们已经放宽了这一限制。 在 GitLab 中发表任何评论(关于问题、合并请求和史诗)并做出回应,从而开始讨论。 这样团队的互动就更有组织性。
适用于 .NET、Go、iOS 和 Pages 的项目模板
(核心、入门、高级、终极、免费、青铜、白银、黄金)
为了方便用户创建新项目,我们提供了几个新的项目模板:
- 初始
.NET Core 项目模板 ,其中包括带有 CI 的基本应用程序。 - 一个现成的模板,结合了
Go Micro 微服务框架 和 GitLab CI/CD。 iOS 应用程序“你好,世界!” ,准备在 GitLab 中进行初始定制。 请注意,由于 iOS 构建需要专用的 MacOS 运行程序,因此如果您想将其与 GitLab CI/CD 一起使用,则需要提供自己的构建服务器。GitLab 页面模板 配置为与 Netlify 一起使用。
需要代码所有者的合并请求许可
(高级、终极、白银、黄金)
谁批准合并请求并不总是显而易见的。
GitLab 现在支持要求根据请求修改的文件来批准合并请求,使用 CODEOWNERS
,格式类似于 gitattributes
.
添加了对自动分配代码所有者作为负责批准合并请求的人员的支持
在 Web IDE 中移动文件
(核心、入门、高级、终极、免费、青铜、白银、黄金)
现在,重命名文件或目录后,您可以沿着新路径将其从 Web IDE 移动到存储库。
标签按字母顺序排列
(核心、入门、高级、终极、免费、青铜、白银、黄金)
GitLab 标签的用途非常广泛,团队不断寻找它们的新用途。 因此,用户经常向问题、合并请求或史诗添加许多标签。
在 GitLab 11.9 中,我们让标签的使用变得更加容易。 对于问题、合并请求和史诗,侧边栏中显示的标签按字母顺序排列。 这也适用于查看这些对象的列表。
按任务过滤操作时的快速评论
(核心、入门、高级、终极、免费、青铜、白银、黄金)
我们最近推出了一项功能,允许用户按任务、合并请求或史诗过滤活动源,这使他们能够只专注于评论或系统注释。 此设置是为系统上的每个用户保存的,并且用户可能没有意识到,在几天后查看问题时,他们看到的是经过过滤的提要。 他觉得自己无法发表评论。
我们改进了这种互动。 现在,用户可以快速切换到允许他们发表评论而无需滚动回提要顶部的模式。 这适用于任务、合并请求和史诗。
更改子史诗的顺序
(终极,黄金)
我们最近发布了
现在,您可以通过简单的拖放来重新排列子史诗的顺序,就像处理子问题一样。 团队可以使用顺序来反映优先级或确定工作完成的顺序。
网络和电子邮件上的自定义页眉和页脚系统消息
(核心、入门、高级、终极)
我们之前添加了一项功能,允许自定义页眉和页脚消息出现在 GitLab 的每个页面上。 它受到热烈欢迎,团队使用它来共享重要信息,例如与其 GitLab 实例相关的系统消息。
我们很高兴将此功能引入 Core,以便更多的人可以使用它。 此外,我们允许用户选择在通过 GitLab 发送的所有电子邮件中显示相同的消息,以确保用户其他 GitLab 接触点的一致性。
按机密任务过滤
(核心、入门、高级、终极、免费、青铜、白银、黄金)
机密问题是团队的一个有用工具,可以在开放项目中就敏感主题进行私下讨论。 特别是,它们非常适合解决安全漏洞。 到目前为止,管理敏感任务并不容易。
在 GitLab 11.9 中,GitLab 问题列表现在按敏感或非敏感问题进行过滤。 这也适用于使用 API 搜索任务。
感谢罗伯特·席林的贡献
部署后编辑 Knative 域
(核心、入门、高级、终极、免费、青铜、白银、黄金)
安装 Knative 时指定自定义域允许您从唯一的端点提供各种无服务器应用程序/功能。
GitLab 中的 Kubernetes 集成现在允许您在将 Knative 部署到 Kubernetes 集群后更改/更新用户域。
检查 Kubernetes CA 证书格式
(核心、入门、高级、终极、免费、青铜、白银、黄金)
添加现有 Kubernetes 集群时,GitLab 现在会验证输入的 CA 证书是否为有效的 PEM 格式。 这消除了 Kubernetes 集成的潜在错误。
将合并请求比较实用程序扩展到整个文件
(核心、入门、高级、终极、免费、青铜、白银、黄金)
当查看合并请求的更改时,您现在可以在每个文件的基础上扩展 diff 实用程序,以显示整个文件以获取更多上下文,并在未更改的行上留下注释。
仅当某些文件发生更改时才根据合并请求执行特定作业
(核心、入门、高级、终极、免费、青铜、白银、黄金)
GitLab 11.6 添加了定义的能力 only: merge_requests
现在我们正在扩展此功能:添加了连接逻辑 only: changes
感谢佐藤博之的贡献(
使用 Grafana 进行自动化 GitLab 监控
(核心、入门、高级、终极)
Grafana 现已包含在我们的 Omnibus 包中,使您可以更轻松地了解实例的功能。
定制 grafana['enable'] = true
в gitlab.rb
,Grafana 将在以下位置提供: https://your.gitlab.instance/-/grafana
。 在不久的将来我们也将
在史诗侧边栏中查看主要史诗
(终极,黄金)
我们最近推出了
在 GitLab 11.9 中,我们让查看这种关系变得更加容易。 现在,您不仅可以看到给定史诗的母史诗,还可以在右侧侧边栏中看到整个史诗树。 你可以看到这些史诗是否已关闭,甚至可以直接进入它们。
从已移动和关闭的任务链接到新任务
(核心、入门、高级、终极、免费、青铜、白银、黄金)
在 GitLab 中,您可以使用侧边栏或快速操作轻松地将问题转移到另一个项目。 在幕后,现有任务将被关闭,并在目标项目中创建一个新任务,其中包含所有复制的数据,包括系统注释和侧边栏属性。 这是一个很棒的功能。
由于存在关于该移动的系统注释,用户在查看已关闭的任务时会感到困惑,并且不自觉地意识到该任务因移动而被关闭。
在此版本中,我们在已关闭问题页面顶部的图标中明确表明该问题已被移动,并且我们还包含指向新问题的嵌入式链接,以便任何访问旧问题的人都可以快速查看导航到新的。
YouTrack 集成
(核心、入门、高级、终极、免费、青铜、白银、黄金)
GitLab 与许多外部问题跟踪系统集成,使团队可以轻松地将 GitLab 用于其他功能,同时维护他们选择的问题管理工具。
在此版本中,我们添加了集成 JetBrains 的 YouTrack 的功能。
我们要感谢 Kotau Jauchen 的贡献(
调整合并请求文件树的大小
(核心、入门、高级、终极、免费、青铜、白银、黄金)
查看合并请求更改时,您现在可以调整文件树的大小以显示长文件名或在较小的屏幕上节省空间。
转到最近的任务栏
(入门版、高级版、终极版、铜牌、银牌、金牌)
仪表板非常有用,团队为每个项目和组创建多个仪表板。 我们最近添加了一个搜索栏,可以快速过滤您感兴趣的所有面板。
在 GitLab 11.9 中我们还引入了一个部分 最新产品 在下拉列表中。 这样您就可以快速跳转到您最近交互过的面板。
开发人员能够创建受保护的分支
(核心、入门、高级、终极、免费、青铜、白银、黄金)
受保护的分支可防止未经审查的代码被移动或合并。 但是,如果不允许任何人移动受保护的分支,则任何人都无法创建新的受保护分支:例如发布分支。
在 GitLab 11.9 中,开发人员可以通过 GitLab 或 API 从已受保护的分支创建受保护的分支。 使用 Git 移动新的受保护分支仍然受到限制,以避免意外创建新的受保护分支。
Open Forks 的 Git 对象重复数据删除(测试版)
(核心、入门、高级、终极)
分叉允许任何人为开源项目做出贡献:无需写入权限,只需将存储库复制到新项目即可。 存储频繁分叉的 Git 存储库的完整副本效率很低。 现在使用 Git alternatives
分支共享对象池中父项目的公共对象,以减少磁盘存储需求。
仅当启用哈希存储时,才会为打开的项目创建 Fork 对象池。 使用函数参数启用对象池 object_pools
.
按分配的审批者过滤合并请求列表
(入门版、高级版、终极版、铜牌、银牌、金牌)
代码审查是任何成功项目的常见做法,但审查者可能很难跟踪合并请求。
在 GitLab 11.9 中,合并请求列表由分配的审批者过滤。 通过这种方式,您可以找到以审阅者身份添加到您的合并请求。
感谢 Glewin Wiechert 的贡献(
合并请求中下一个和上一个文件的快捷方式
(核心、入门、高级、终极、免费、青铜、白银、黄金)
查看合并请求的更改时,您可以使用以下命令在文件之间快速切换 ]
или j
移至下一个文件并 [
или k
转到上一个文件。
简化 .gitlab-ci.yml
对于无服务器项目
(核心、入门、高级、终极、免费、青铜、白银、黄金)
以功能为基础 include
gitlab-ci.yml
大大简化了。 要在未来版本中引入新功能,您无需更改此文件。
入口主机名支持
(核心、入门、高级、终极、免费、青铜、白银、黄金)
部署 Kubernetes Ingress 控制器时,某些平台会回退到 IP 地址(例如 Google 的 GKE),而其他平台则回退到 DNS 名称(例如 AWS 的 EKS)。
我们的 Kubernetes 集成现在支持两种类型的端点在该部分中显示 clusters
项目。
感谢 Aaron Walker 的贡献(
仅限制团队/项目成员的 JupyterHub 登录访问权限
(核心、入门、高级、终极、免费、青铜、白银、黄金)
使用 GitLab 的 Kubernetes 集成部署 JupyterHub 是在大型团队中维护和使用 Jupyter Notebook 的好方法。 在传输机密或个人数据时控制对它们的访问也很有用。
在 GitLab 11.9 中,登录通过 Kubernetes 部署的 JupyterHub 实例的能力仅限于具有开发人员访问权限的项目成员(通过组或项目)。
安全面板方案的可定制时间范围
(终极,黄金)
团队安全仪表板包括一个漏洞图,可提供团队项目当前安全状态的概述。 这对于安全主管设置流程和了解团队如何工作非常有用。
在 GitLab 11.9 中,您现在可以选择此漏洞地图的时间范围。 默认情况下,这是最近 90 天,但您可以将跨度设置为 60 或 30 天,具体取决于您需要的详细程度。
这不会影响计数器或列表中的数据,只会影响图表中显示的数据点。
为标签添加自动 DevOps 构建作业
(核心、入门、高级、终极、免费、青铜、白银、黄金)
Auto DevOps 构建步骤使用 Heroku 项目或构建包的 Dockerfile 创建应用程序的构建。
在 GitLab 11.9 中,嵌入标签管道中的生成的 Docker 镜像的命名方式与传统镜像名称类似,使用标签提交而不是 SHA 提交。
感谢亚伦·沃克的贡献!
将代码气候更新至版本 0.83.0
(入门版、高级版、终极版、铜牌、银牌、金牌)
GitLab
在 GitLab 11.9 中,我们将引擎更新到最新版本(
感谢 GitLab 核心团队成员 Takuya Noguchi 的贡献(
缩放和滚动指标面板
(核心、入门、高级、终极、免费、青铜、白银、黄金)
在调查性能异常时,仔细查看特定指标的各个部分通常会有所帮助。
使用 GitLab 11.9,用户将能够在指标面板中缩放到各个时间段,滚动浏览整个时间段,并轻松返回到原始时间间隔的视图。 这使您可以快速轻松地研究所需的事件。
适用于 TypeScript 的 SAST
(终极,黄金)
在 GitLab 11.9 中,静态应用程序安全测试 (SAST) 分析和检测 TypeScript 代码中的漏洞,并在合并请求小部件、管道级别和安全仪表板中演示它们。 目前的职位定义 sast
无需更改,也自动包含在
用于多模块 Maven 项目的 SAST
(终极,黄金)
Maven 项目通常被组织为组合
GitLab 11.9 为该特定项目配置提供了对 SAST 功能的扩展支持,提供了按原样测试它们是否存在漏洞的能力。 由于分析器的灵活性,配置是自动确定的,您无需更改任何内容即可查看多模块 Maven 应用程序的结果。 与往常一样,类似的改进也可以在
亚搏体育appGitLab跑步者11.9
(核心、入门、高级、终极、免费、青铜、白银、黄金)
今天我们还发布了 GitLab Runner 11.9! GitLab Runner 是一个开源项目,用于运行 CI/CD 作业并将结果发送回 GitLab。
以下是 GitLab Runner 11.9 中的一些更改:
将 alpine 图像更新至 alpine 3.9 .为 gitlab-runner-helper 添加 Windows Dockerfile и添加脚本来构建 Windows 图像助手 .更新docker API版本 ... 一样的消除了 CentOS 6 上的 Docker 执行器支持 .添加屏蔽日志跟踪中变量的功能 为了支持日志中受保护变量的简单屏蔽 ,它将出现在 GitLab 11.10 中。添加 12.0 中遗留操作系统功能的文档 .更新 SNTP 命令以捕获 Parallels 执行器中的时间同步 .- 移动多个脚本 - 包括
服务等待脚本 иbash 缓存脚本 - 在围棋中。 消除辅助图像命令 .从提供的参考规范中提取代码 .修复克隆 LFS 对象大于可用 RAM 的存储库时的内存分配错误 .
完整的更改列表可以在 GitLab Runner 更改日志中找到:
GitLab 架构改进
(核心、入门、高级、终极)
GitLab 图表进行了以下改进:
- 添加了对 Google Cloud Memorystore 的支持。
- Cron 作业设置
现在全球 ,因为它们被多个服务使用。 - 注册表已更新至版本2.7.1。
- 添加了一个新设置,使 GitLab 注册表与 1.10 之前的 Docker 版本兼容。 要激活,请安装
registry.compatibility.schema1.enabled: true
.
性能改进
(核心、入门、高级、终极、免费、青铜、白银、黄金)
我们不断提高各种规模的 GitLab 实例的每个版本的 GitLab 性能。 以下是 GitLab 11.9 中的一些改进:
综合改进
(核心、入门、高级、终极)
GitLab 11.9 包括以下综合改进:
- 亚搏体育appGitLab 11.9包括
最重要的5.8 ,开源 Slack 替代品 ,其最新版本包括 Team Edition 的 MFA、改进的图像性能等。 该版本还包括安全改进 ; 建议更新。 - 添加了一个新设置,使 GitLab 注册表与 1.10 之前的 Docker 版本兼容。 要激活,请安装
registry['compatibility_schema1_enabled'] = true в gitlab.rb
. - GitLab 注册表现在导出 Prometheus 指标,并通过传入的数据自动监控
Prometheus 服务套件 . - 添加了对 Google Cloud Memorystore 的支持,这需要
.отключения redis_enable_client
openssl
更新至版本1.0.2r,nginx
- 最高版本 1.14.2,python
- 最高版本 3.4.9,jemalloc
- 最高版本 5.1.0,docutils
- 最高版本 0.13.1,gitlab-monitor
- 最高版本 3.2.0。
过时的功能
GitLab Geo 将在 GitLab 12.0 中提供哈希存储
需要 GitLab 地理信息
在亚搏体育app实验室
在亚搏体育app实验室 sudo gitlab-rake gitlab: geo: check
检查是否启用了哈希存储以及是否迁移了所有项目。 厘米。
在亚搏体育app实验室
在亚搏体育app实验室
12.0 Geo 将使用散列存储要求。 厘米。gitlab-ee#8690 .
删除日期: 22 6月2019日,
Hipchat 集成
HipChat
删除日期: 三月22 2019
CentOS 6 支持使用 Docker 执行器的 GitLab Runner
在 GitLab 6 上使用 Docker 时,GitLab Runner 不支持 CentOS 11.9。 这是 Docker 核心库更新的结果,不再支持 CentOS 6。有关更多详细信息,请参阅
删除日期: 三月22 2019
过时的 GitLab Runner 遗留代码路径
从 Gitlab 11.9 开始,GitLab Runner 使用
在 GitLab 11.0 中,我们更改了 GitLab Runner 指标服务器配置的外观。 metrics_server
将被删除以利于 listen_address
在 GitLab 12.0 中。 查看更多详细信息
在11.3版本中,GitLab Runner开始支持
这些路径在 GitLab 12.0 中不再可用。 作为用户,在升级到 GitLab Runner 11.9 时,除了确保您的 GitLab 实例运行版本 12.0+ 之外,您不需要进行任何更改。
删除日期: 22 6月2019日,
GitLab Runner 入口点功能的已弃用参数
11.4 GitLab Runner引入特性参数 FF_K8S_USE_ENTRYPOINT_OVER_COMMAND
在 GitLab 12.0 中,我们将切换到正确的行为,就像禁用功能设置一样。 查看更多详细信息
删除日期: 22 6月2019日,
GitLab Runner 已弃用对 Linux 发行版的支持已达到 EOL
一些可以安装 GitLab Runner 的 Linux 发行版已经达到了它们的目的。
在 GitLab 12.0 中,GitLab Runner 将不再将软件包分发到此类 Linux 发行版。 不再支持的发行版的完整列表可以在我们的
删除日期: 22 6月2019日,
删除旧的 GitLab Runner Helper 命令
作为我们努力支持的一部分
在 GitLab 12.0 中,GitLab Runner 使用新命令启动。 这仅影响覆盖的用户
删除日期: 22 6月2019日,
开发者可以在 GitLab 11.10 中删除 Git 标签
过去,在未检查的分支中删除或编辑 Git 标签的版本注释仅限于
由于开发人员可以添加标签以及修改和删除不受保护的分支,因此开发人员应该能够删除 Git 标签。 在 GitLab 11.10 中
如果您想为维护者和所有者保留此限制,请使用
删除日期: 22 4月2019城市
Omnibus GitLab 中的 Prometheus 1.x 支持
从 GitLab 开始
在 GitLab 版本中
12.0 如果尚未安装更新,Prometheus 2.0 将自动安装。 Prometheus 1.0 的数据将会丢失,因为...... 不被容忍。
删除日期: 22 6月2019日,
TLSv1.1
从 GitLab 开始
要立即禁用 TLS v1.1,请设置 nginx['ssl_protocols'] = "TLSv1.2"
в gitlab.rband
并运行 gitlab-ctl reconfigure
.
删除日期: 22 6月2019日,
用于 GitLab 安装的 OpenShift 模板
官方 gitlab
舵图
OpenShift 模板 安装 GitLab 已被弃用,并且将不再受支持亚搏体育app 12.0 .
删除日期: 22 6月2019日,
安全工作的先前定义
带介绍
更新您的作业定义以使用新语法并利用 GitLab 提供的所有新安全功能。
删除日期:22 年 2019 月 XNUMX 日
管理面板中的系统信息部分
GitLab 在以下位置显示有关您的 GitLab 实例的信息 admin/system_info
,但此信息可能不准确。
我们
删除日期: 22 6月2019日,
来源: habr.com